////////////////////////////////////////////////////////////////////////////////
//
//  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.utils
{
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.engine.TextLine;
	import flash.text.engine.TextRotation;
	
	import flashx.textLayout.compose.IFlowComposer;
	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.container.ScrollPolicy;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.elements.TextRange;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.Direction;
	import flashx.textLayout.tlf_internal;
	
	use namespace tlf_internal;
	

	/** 
	 * Utilities for manipulating a TextRange 
	 * The methods of this class are static and must be called using
	 * the syntax <code>NavigationUtil.method(<em>parameter</em>)</code>.
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	public final class NavigationUtil 
	{
		private static function validateTextRange(range:TextRange):Boolean
		{ return range.textFlow != null && range.anchorPosition != -1 && range.activePosition != -1; }
		
		private static function doIncrement(flowRoot:TextFlow, pos:int, incrementer:Function):int
		{
			var para:ParagraphElement = flowRoot.findAbsoluteParagraph(pos);
			return incrementer(flowRoot, para, pos, para.getAbsoluteStart());			
		}
		
		private static function previousAtomHelper(flowRoot:TextFlow, para:ParagraphElement, pos:int, paraStart:int):int
		{
			if (pos - paraStart == 0)
				return (pos > 0) ? pos - 1 : 0;
			
			// mjzhang : for fix bug 2835316, will force to compose to paragraph end to avoid invalid textLine
			var paraEnd:Number = para.getAbsoluteStart() + para.textLength;
			para.getTextFlow().flowComposer.composeToPosition(paraEnd);
			
			return para.findPreviousAtomBoundary(pos - paraStart) + paraStart;
		}
		
		/** 
		 * Returns the absolute position of the previous atom. 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public static function previousAtomPosition(flowRoot:TextFlow, absolutePos:int):int
		{
			return doIncrement(flowRoot,absolutePos,previousAtomHelper);
		}
	
		private static function nextAtomHelper(flowRoot:TextFlow, para:ParagraphElement, pos:int, paraStart:int):int
		{
			if (pos - paraStart == para.textLength - 1)
				return Math.min(flowRoot.textLength, pos + 1);
			
			// mjzhang : for fix bug 2835316, will force to compose to paragraph end to avoid invalid textLine
			var paraEnd:Number = para.getAbsoluteStart() + para.textLength;
			para.getTextFlow().flowComposer.composeToPosition(paraEnd);
			
			return para.findNextAtomBoundary(pos - paraStart) + paraStart;
		}
		
		/** 
		 * Returns the absolute position of the next atom.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public static function nextAtomPosition(flowRoot:TextFlow, absolutePos:int):int
		{
			return doIncrement(flowRoot,absolutePos,nextAtomHelper);
		}
	
		/** 
		 * Returns absolute position of the beginning of the previous word.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public static function previousWordPosition(flowRoot:TextFlow, absolutePos:int):int
		{
			if (isOverset(flowRoot, absolutePos))
				return endOfLastController(flowRoot);
			
			var para:ParagraphElement = flowRoot.findAbsoluteParagraph(absolutePos);
			var paraStart:int = para.getAbsoluteStart();
			
			// mjzhang : for fix bug 2835316, will force to compose to paragraph end to avoid invalid textLine
			var paraEnd:Number = para.getAbsoluteStart() + para.textLength;
			para.getTextFlow().flowComposer.composeToPosition(paraEnd);
			
			var prevWordPos:int = absolutePos - paraStart;
			var nextWordPos:int = 0;
			if (absolutePos - paraStart == 0)
				return (absolutePos > 0) ? absolutePos - 1 : 0;
			do
			{
				nextWordPos = para.findPreviousWordBoundary(prevWordPos);
				if (prevWordPos == nextWordPos) prevWordPos = para.findPreviousWordBoundary(prevWordPos - 1);
				else prevWordPos = nextWordPos;
			} while (prevWordPos > 0 && CharacterUtil.isWhitespace(para.getCharCodeAtPosition(prevWordPos)));
			return prevWordPos + paraStart;
		}
	
		/** 
		 * Returns the absolute position of the beginning of the next word.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public static function nextWordPosition(flowRoot:TextFlow, absolutePos:int):int
		{
			var para:ParagraphElement = flowRoot.findAbsoluteParagraph(absolutePos);
			var paraStart:int = para.getAbsoluteStart();
			
			// mjzhang : for fix bug 2835316, will force to compose to paragraph end to avoid invalid textLine
			var paraEnd:Number = para.getAbsoluteStart() + para.textLength;
			para.getTextFlow().flowComposer.composeToPosition(paraEnd);
			
			var nextWordPos:int = absolutePos - paraStart;
			
			if (absolutePos - paraStart == para.textLength - 1)
				return Math.min(flowRoot.textLength, absolutePos + 1);
			do
			{
				nextWordPos = para.findNextWordBoundary(nextWordPos);
			} while (nextWordPos < (para.textLength - 1) && CharacterUtil.isWhitespace(para.getCharCodeAtPosition(nextWordPos)))
			return nextWordPos + paraStart;
		}
		
		/** @private */
		static tlf_internal function updateStartIfInReadOnlyElement(textFlow:TextFlow, idx:int):int
		{
			return idx;
		}
		
		/** @private */
		static tlf_internal function updateEndIfInReadOnlyElement(textFlow:TextFlow, idx:int):int
		{
			return idx; 
		}
		
		static private function moveForwardHelper(range:TextRange, extendSelection:Boolean, incrementor:Function):Boolean
		{
			var textFlow:TextFlow = range.textFlow;
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
				
			if (extendSelection) 
				endIdx = incrementor(textFlow, endIdx);
			else {
				if (begIdx == endIdx) //no selection, just move insertion point
				{
					begIdx = incrementor(textFlow, begIdx);
					endIdx = begIdx;
				}
				else if (endIdx > begIdx) //change selection to insertion point
					begIdx = endIdx;
				else
					endIdx = begIdx;
			}
			
			if (begIdx == endIdx)
			{
				begIdx = updateStartIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
			} 
					
			if (!extendSelection && (range.anchorPosition == begIdx) && (range.activePosition == endIdx))
			{
				if (begIdx < endIdx)
				{
					begIdx = Math.min(endIdx + 1, textFlow.textLength - 1);
					endIdx = begIdx;
				}else {
					endIdx = Math.min(begIdx + 1, textFlow.textLength - 1);
					begIdx = endIdx;
				}	
			}
			return range.updateRange(begIdx,endIdx);							 	
		}
		
		static private function moveBackwardHelper(range:TextRange, extendSelection:Boolean, incrementor:Function):Boolean
		{
			var textFlow:TextFlow = range.textFlow;
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
				
			if (extendSelection)	//shift key is pressed 
				endIdx = incrementor(textFlow, endIdx);
			else {
				if (begIdx == endIdx) //no selection, just move insertion point
				{
					begIdx = incrementor(textFlow, begIdx);
					endIdx = begIdx;
				}
				else if (endIdx > begIdx) //change selection to insertion point
					endIdx = begIdx;
				else
					begIdx = endIdx;
			}
					
			if (begIdx == endIdx)
			{
				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			} 
					
			if (!extendSelection && (range.anchorPosition == begIdx) && (range.activePosition == endIdx))
			{
				if (begIdx < endIdx)
				{
					endIdx = Math.max(begIdx - 1, 0);
					begIdx = endIdx;
				}else {
					begIdx = Math.max(endIdx - 1, 0);
					endIdx = begIdx;
				}	
			}
			return range.updateRange(begIdx,endIdx);
		 }
		
		/**
		 * Sets the TextRange forward by one character.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 
		static public function nextCharacter(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (validateTextRange(range))
			{
				if (!adjustForOversetForward(range))
					moveForwardHelper(range, extendSelection, nextAtomPosition);
				return true;
			}
		 	return false;
		}
		 
		/**
		 * Sets the TextRange backward by one character.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 
		static public function previousCharacter(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (validateTextRange(range))
			{
				if (!adjustForOversetBack(range))
					moveBackwardHelper(range, extendSelection, previousAtomPosition);
				return true;
			} 
			return false;
		} 
		/**
		 * Sets the TextRange forward by one word.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 
		static public function nextWord(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (validateTextRange(range))
			{
				if (!adjustForOversetForward(range))
					moveForwardHelper(range, extendSelection, nextWordPosition);
				return true;
			}
			return false;
		}
		 
		/**
		 * Sets the TextRange backward by one word.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 
		static public function previousWord(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (validateTextRange(range))
			{
				if (!adjustForOversetBack(range))
		 			moveBackwardHelper(range, extendSelection, previousWordPosition);
		 		return true;
		 	}
		 	return false;
		} 
		
		/** @private */
		static tlf_internal function computeEndIdx(targetFlowLine:TextFlowLine,curTextFlowLine:TextFlowLine,blockProgression:String,isRTLDirection:Boolean,globalPoint:Point):int
		{
			var endIdx:int;
			var targetTextLine:TextLine = targetFlowLine.getTextLine(true);
			var currentTextLine:TextLine = curTextFlowLine.getTextLine(true);
			var bidiRightToLeft:Boolean = ((currentTextLine.getAtomBidiLevel(atomIndex) % 2) != 0); 				
			
			if (targetFlowLine.controller == curTextFlowLine.controller)
			{
				if(blockProgression != BlockProgression.RL)
				{
					globalPoint.y -= (currentTextLine.y - targetTextLine.y);
				} else {
					globalPoint.x += (targetTextLine.x - currentTextLine.x);
				}
			} else {
				var firstAtomRect:Rectangle = targetTextLine.getAtomBounds(0);
				var firstAtomPoint:Point = new Point();
				firstAtomPoint.x = firstAtomRect.left;
				firstAtomPoint.y = 0;
				firstAtomPoint = targetTextLine.localToGlobal(firstAtomPoint);
				if(blockProgression != BlockProgression.RL)
				{
					globalPoint.x -= curTextFlowLine.controller.container.x;
					globalPoint.y = firstAtomPoint.y;
				} else {
					globalPoint.x = firstAtomPoint.x;
					globalPoint.y -= curTextFlowLine.controller.container.y; 
				}					
			} 
			
			var atomIndex:int = targetTextLine.getAtomIndexAtPoint(globalPoint.x,globalPoint.y);
			if (atomIndex == -1)
			{
				if(blockProgression != BlockProgression.RL) {
					if (!bidiRightToLeft)
						endIdx = (globalPoint.x <= targetTextLine.x) ? targetFlowLine.absoluteStart : (targetFlowLine.absoluteStart + targetFlowLine.textLength - 1);
					else
						endIdx = (globalPoint.x <= targetTextLine.x) ? (targetFlowLine.absoluteStart + targetFlowLine.textLength - 1) : targetFlowLine.absoluteStart;						
				} else {
					if (!bidiRightToLeft)
						endIdx = (globalPoint.y <= targetTextLine.y) ? targetFlowLine.absoluteStart : (targetFlowLine.absoluteStart + targetFlowLine.textLength - 1);
					else
						endIdx = (globalPoint.y <= targetTextLine.y)  ? (targetFlowLine.absoluteStart + targetFlowLine.textLength - 1) : targetFlowLine.absoluteStart;						
				}
			} 
			else {
				// get the character box and if check we are past the middle select past this character. 
				var glyphRect:Rectangle = targetTextLine.getAtomBounds(atomIndex);
				var leanRight:Boolean = false;
				if(glyphRect)
				{	
					//if this is TTB and NOT TCY determine lean based on Y coordinates...
					var glyphGlobalPoint:Point = new Point();
					glyphGlobalPoint.x = glyphRect.x;
					glyphGlobalPoint.y = glyphRect.y;
					glyphGlobalPoint = targetTextLine.localToGlobal(glyphGlobalPoint);
					
					if((blockProgression == BlockProgression.RL) && targetTextLine.getAtomTextRotation(atomIndex) != TextRotation.ROTATE_0)
						leanRight = (globalPoint.y > (glyphGlobalPoint.y + glyphRect.height/2));
					else //use X..
						leanRight = (globalPoint.x > (glyphGlobalPoint.x + glyphRect.width/2));
				}
				
				var paraSelectionIdx:int;
				if ((targetTextLine.getAtomBidiLevel(atomIndex) % 2) != 0) // Right to left case, right is "start" unicode
					paraSelectionIdx = leanRight ? targetTextLine.getAtomTextBlockBeginIndex(atomIndex) : targetTextLine.getAtomTextBlockEndIndex(atomIndex);
				else  {// Left to right case, right is "end" unicode
					if (isRTLDirection) {
						if ((leanRight == false) && (atomIndex > 0))
						{
							paraSelectionIdx = targetTextLine.getAtomTextBlockBeginIndex(atomIndex - 1);	
						} else {
							paraSelectionIdx = targetTextLine.getAtomTextBlockBeginIndex(atomIndex);
						}
					} else {
						paraSelectionIdx = leanRight ? targetTextLine.getAtomTextBlockEndIndex(atomIndex) : targetTextLine.getAtomTextBlockBeginIndex(atomIndex);							
					}
				}
				endIdx = targetFlowLine.paragraph.getAbsoluteStart() + paraSelectionIdx;
			}
			return endIdx;
		}
		/**
		 * Sets the TextRange down one line
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 
		static public function nextLine(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (!validateTextRange(range))
				return false;
		
			if (adjustForOversetForward(range))
				return true;
				
			var textFlow:TextFlow = range.textFlow;
			var blockProgression:String = textFlow.computedFormat.blockProgression;
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
			var limitIdx:int = endOfLastController(textFlow);
			
			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
			var isRTLDirection:Boolean = (textFlow.computedFormat.direction == Direction.RTL);			

			if (curLine < textFlow.flowComposer.numLines-1)	//create, expand or shrink the selection
			{
				var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
				var lineStart:int = curTextFlowLine.absoluteStart;
				var lineDelta:int = endIdx - lineStart;
				var currentTextLine:TextLine = curTextFlowLine.getTextLine(true);
				var para:ParagraphElement = curTextFlowLine.paragraph;
				var atomIndex:int = currentTextLine.getAtomIndexAtCharIndex(endIdx - para.getAbsoluteStart());
				var bidiRightToLeft:Boolean = ((currentTextLine.getAtomBidiLevel(atomIndex) % 2) != 0); 
				var curPosRect:Rectangle = currentTextLine.getAtomBounds(atomIndex);
				var currentTextLineX:Number = currentTextLine.x;
				var curPosRectLeft:Number = curPosRect.left;
				var curPosRectRight:Number = curPosRect.right;
				if(blockProgression == BlockProgression.RL)
				{
					currentTextLineX = currentTextLine.y;
					curPosRectLeft = curPosRect.top;
					curPosRectRight = curPosRect.bottom;
				}
				
				//find the atom
				var globalPoint:Point = new Point();				
						
				if(blockProgression != BlockProgression.RL)
				{
					if (!isRTLDirection)
						globalPoint.x = curPosRect.left;
					else
						globalPoint.x = curPosRect.right;
					globalPoint.y = 0;
				} else {						
					globalPoint.x = 0;
					if (!isRTLDirection)
						globalPoint.y = curPosRect.top;
					else
						globalPoint.y = curPosRect.bottom;
				}
				
				globalPoint = currentTextLine.localToGlobal(globalPoint);
				
				//at this point, we have the global point of our current position.  Now adjust x or y to the
				//baseline of the next line.
				var nextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine + 1);
				if (nextFlowLine.absoluteStart >= limitIdx)
				{
					if (!extendSelection)
						range.activePosition = range.anchorPosition = textFlow.textLength - 1;
					else
						range.activePosition = textFlow.textLength;
					return true;
				}
				
				
				// get the last container so that we can make sure the previous line is in view.
				var controller:ContainerController = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);
				var firstPosInContainer:int = controller.absoluteStart;
				var lastPosInContainer:int = firstPosInContainer + controller.textLength;
				if ((nextFlowLine.absoluteStart >= firstPosInContainer) && (nextFlowLine.absoluteStart < lastPosInContainer))
				{
					if (nextFlowLine.isDamaged())
					{
						textFlow.flowComposer.composeToPosition(nextFlowLine.absoluteStart+1);
						nextFlowLine = textFlow.flowComposer.getLineAt(curLine + 1);
						if (nextFlowLine.isDamaged())
							return false;
					}
					// Scroll down one line, but allow scrolling only in the block progression direction
					var curLogicalHorizontalScrollPos:Number = (blockProgression == BlockProgression.TB) ? controller.horizontalScrollPosition : controller.verticalScrollPosition;
					controller.scrollToRange(nextFlowLine.absoluteStart, nextFlowLine.absoluteStart + nextFlowLine.textLength - 1);
					if (blockProgression == BlockProgression.TB)
						controller.horizontalScrollPosition = curLogicalHorizontalScrollPos;
					else
						controller.verticalScrollPosition = curLogicalHorizontalScrollPos; 
				}
				
				endIdx = computeEndIdx(nextFlowLine,curTextFlowLine,blockProgression,isRTLDirection,globalPoint);

				if (endIdx >= textFlow.textLength)
					endIdx = textFlow.textLength;
			}
			else
				endIdx = textFlow.textLength;
				
			if (!extendSelection)
				begIdx = endIdx;
											
			if (begIdx == endIdx)
			{
				begIdx = updateStartIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);			
		}
		  
		/**
		 * Sets the TextRange up one line.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 
		static public function previousLine(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (!validateTextRange(range))
				return false;
			
			if (adjustForOversetBack(range))
				return true;
				
			var textFlow:TextFlow = range.textFlow;
			var blockProgression:String = textFlow.computedFormat.blockProgression;
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
			
			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
			var isRTLDirection:Boolean = (textFlow.computedFormat.direction == Direction.RTL);			

			if (curLine > 0)	//create, expand or shrink the selection
			{
				var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
				var lineStart:int = curTextFlowLine.absoluteStart;
				var lineDelta:int = endIdx - lineStart;
				var currentTextLine:TextLine = curTextFlowLine.getTextLine(true);
				var para:ParagraphElement = curTextFlowLine.paragraph;
				var atomIndex:int = currentTextLine.getAtomIndexAtCharIndex(endIdx - para.getAbsoluteStart());
				var curPosRect:Rectangle = currentTextLine.getAtomBounds(atomIndex);
				var currentTextLineX:Number = currentTextLine.x;
				var curPosRectLeft:Number = curPosRect.left;
				var curPosRectRight:Number = curPosRect.right;
				if(blockProgression == BlockProgression.RL)
				{
					currentTextLineX = currentTextLine.y;
					curPosRectLeft = curPosRect.top;
					curPosRectRight = curPosRect.bottom;
				}
				
				//find the atom
				var globalPoint:Point = new Point();				
						
				if(blockProgression != BlockProgression.RL)
				{
					if (!isRTLDirection)
						globalPoint.x = curPosRect.left;
					else
						globalPoint.x = curPosRect.right;
					globalPoint.y = 0;
				} else {						
					globalPoint.x = 0;
					if (!isRTLDirection)
						globalPoint.y = curPosRect.top;
					else
						globalPoint.y = curPosRect.bottom;
				}
				
				globalPoint = currentTextLine.localToGlobal(globalPoint);
				
				//at this point, we have the global point of our current position.  Now adjust x or y to the
				//baseline of the next line.
				var prevFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine - 1);
				// get the last container so that we can make sure the previous line is in view.
				var controller:ContainerController = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);
				var firstPosInContainer:int = controller.absoluteStart;
				var lastPosInContainer:int = firstPosInContainer + controller.textLength;
				if ((prevFlowLine.absoluteStart >= firstPosInContainer) && (prevFlowLine.absoluteStart < lastPosInContainer))
				{
					// Scroll up one line, but allow scrolling only in the block progression direction
					var curLogicalHorizontalScrollPos:Number = (blockProgression == BlockProgression.TB) ? controller.horizontalScrollPosition : controller.verticalScrollPosition;
					controller.scrollToRange(prevFlowLine.absoluteStart,prevFlowLine.absoluteStart+prevFlowLine.textLength-1);
					if (blockProgression == BlockProgression.TB)
						controller.horizontalScrollPosition = curLogicalHorizontalScrollPos;
					else
						controller.verticalScrollPosition = curLogicalHorizontalScrollPos; 
				}
				
				endIdx = computeEndIdx(prevFlowLine,curTextFlowLine,blockProgression,isRTLDirection,globalPoint);
			}
			else 
			{
				endIdx = 0;
			}
				
			if (!extendSelection)
				begIdx = endIdx;
											
			if (begIdx == endIdx)
			{
				begIdx = updateStartIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);			
		}
		 
		/**
		 * Sets the TextRange down one page.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 
		static public function nextPage(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			var controller:ContainerController;
			
			if (!validateTextRange(range))
				return false;
				
			var textFlow:TextFlow = range.textFlow;
			
			// if not the last container go to the beginning of the next container
			var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(range.activePosition);
			if (controllerIndex != textFlow.flowComposer.numControllers-1)
			{
				range.activePosition = textFlow.flowComposer.getControllerAt(controllerIndex+1).absoluteStart;
				if (!extendSelection)
					range.anchorPosition = range.activePosition;
				return true;
			}
			
			if (!isScrollable(textFlow, range.activePosition))		// paging applies only to containers that scroll
				return false;
								
			if (adjustForOversetForward(range))
				return true;
		 	
			var begIdx:int = range.absoluteStart;
			var endIdx:int = range.absoluteEnd;
			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
			var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
			
			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
			var linePos:int = endIdx - lineStart;
 			var nextLine:int;
 			var nextTextFlowLine:TextFlowLine = curTextFlowLine;
 											
			var isTTB:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL;
			var amount:Number;
			
			// get the last container
			controller = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);

			if (isTTB)
			{
				amount = controller.compositionWidth * textFlow.configuration.scrollPagePercentage;
			} else {
				amount = controller.compositionHeight * textFlow.configuration.scrollPagePercentage;
			}
  								
 			if (isTTB)
 			{
				var contentWidth:Number = controller.contentWidth;
 				if ((controller.horizontalScrollPosition - amount) < -contentWidth)
 				{
 					controller.horizontalScrollPosition = -contentWidth;
					nextLine = textFlow.flowComposer.numLines - 1;
					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								
 				} else
 				{
 					var oldHorzScrollPos:Number = controller.horizontalScrollPosition;
 					controller.horizontalScrollPosition -= amount;
 					var newHorzScrollPos:Number = controller.horizontalScrollPosition;
 					if (oldHorzScrollPos == newHorzScrollPos) {
						nextLine = textFlow.flowComposer.numLines - 1;
						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);													
 					} else {
 						nextLine = curLine;
 						while (nextLine < (textFlow.flowComposer.numLines - 1))
 						{
 							nextLine++;
							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
							if ((curTextFlowLine.x - nextTextFlowLine.x) >= (oldHorzScrollPos - newHorzScrollPos))
								break;
 						}
 					}
 				} 					
 			}
 			else
 			{
				var contentHeight:Number = controller.contentHeight;
 				if ((controller.verticalScrollPosition + amount) > contentHeight)
 				{
 					controller.verticalScrollPosition = contentHeight;
					nextLine = textFlow.flowComposer.numLines - 1;
					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 						
 				} else
 				{
 					var oldVertScrollPos:Number = controller.verticalScrollPosition;
 					controller.verticalScrollPosition += amount;
 					var newVertScrollPos:Number = controller.verticalScrollPosition;
 					if (newVertScrollPos == oldVertScrollPos) {
						nextLine = textFlow.flowComposer.numLines - 1;
						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 											
 					} else {
 						nextLine = curLine;
 						while (nextLine < (textFlow.flowComposer.numLines - 1))
 						{
 							nextLine++;
							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
							if ((nextTextFlowLine.y - curTextFlowLine.y) >= (newVertScrollPos - oldVertScrollPos))
								break;
 						} 						
 					}
 				}
 			}
 			
 			endIdx = nextTextFlowLine.absoluteStart + linePos; 
			var nextLineEnd:int = nextTextFlowLine.absoluteStart + nextTextFlowLine.textLength - 1;
			if (endIdx > nextLineEnd)
			{
				endIdx = nextLineEnd;
			}
			
			if (!extendSelection)
				begIdx = endIdx;							
			if (begIdx == endIdx)
			{
				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			}
			
			return range.updateRange(begIdx,endIdx);				
		 }
		  
		/**
		 * Sets the TextRange up one page.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 		 
		static public function previousPage(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (!validateTextRange(range))
				return false;
				
			var textFlow:TextFlow = range.textFlow;
			
			var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(range.activePosition);
			var controller:ContainerController = textFlow.flowComposer.getControllerAt(controllerIndex);
			
			// first line in container
			var controllerFirstLine:TextFlowLine = textFlow.flowComposer.findLineAtPosition(controller.absoluteStart);

			// if on the first line of a controller go to the beginning of the previous controller
			if (range.activePosition <= controller.absoluteStart+controllerFirstLine.textLength)
			{
				if (controllerIndex == 0)
					return false;
				range.activePosition = textFlow.flowComposer.getControllerAt(controllerIndex-1).absoluteStart;
				if (!extendSelection)
					range.anchorPosition = range.activePosition;
				return true;
			}
			
			// if not the last container go to the beginning of the current container
			if (controllerIndex != textFlow.flowComposer.numControllers-1)
			{
				range.activePosition = controller.absoluteStart;
				if (!extendSelection)
					range.anchorPosition = range.activePosition;
				return true;
			}
				
			if (!isScrollable(textFlow, range.activePosition))		// paging applies only to containers that scroll
				return false;
								
			if (adjustForOversetBack(range))
				return true;
			
			var begIdx:int = range.absoluteStart;
			var endIdx:int = range.absoluteEnd;
			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
			var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
			
			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
			var linePos:int = endIdx - lineStart;
 			var nextLine:int;
 			var nextTextFlowLine:TextFlowLine = curTextFlowLine;
 											
			var isTTB:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL;
			var amount:Number;
			
			// get the last container
			controller = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);
			
			if (isTTB)
			{
				amount = controller.compositionWidth * textFlow.configuration.scrollPagePercentage;
			} else {
				amount = controller.compositionHeight * textFlow.configuration.scrollPagePercentage;
			}
  								
 			if (isTTB)
 			{
 				if ((controller.horizontalScrollPosition + amount + controller.compositionWidth) > 0)
 				{
 					controller.horizontalScrollPosition = 0;
					nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								
 				} else
 				{
 					var oldHorzPos:Number = controller.horizontalScrollPosition;
 					controller.horizontalScrollPosition += amount;
 					var newHorzPos:Number = controller.horizontalScrollPosition;
 					if (oldHorzPos == newHorzPos) {
						nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);													
 					} else {
 						nextLine = curLine;
 						while (nextLine > 0)
 						{
 							nextLine--;
							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
							if ((nextTextFlowLine.x - curTextFlowLine.x) >= (newHorzPos - oldHorzPos) || nextTextFlowLine.absoluteStart < controller.absoluteStart)
								break;
 						}
 					}
 				} 					
 			}
 			else
 			{
 				if ((controller.verticalScrollPosition - amount + controller.compositionHeight) < 0)
 				{
 					controller.verticalScrollPosition = 0;
					nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 						
 				} else
 				{
 					var oldVertPos:Number = controller.verticalScrollPosition;
 					controller.verticalScrollPosition -= amount;
 					var newVertPos:Number = controller.verticalScrollPosition;
 					if (oldVertPos == newVertPos) {
						nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 											
 					} else {
 						nextLine = curLine;
 						while (nextLine > 0)
 						{
 							nextLine--;
							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
							if ((curTextFlowLine.y - nextTextFlowLine.y) >= (oldVertPos - newVertPos) || nextTextFlowLine.absoluteStart < controller.absoluteStart)
								break;
 						}
 					} 						
 				}
 			}
 			
 			endIdx = nextTextFlowLine.absoluteStart + linePos; 
			var nextLineEnd:int = nextTextFlowLine.absoluteStart + nextTextFlowLine.textLength - 1;
			if (endIdx > nextLineEnd)
			{
				endIdx = nextLineEnd;
			}
			
			if (!extendSelection)
				begIdx = endIdx;							
			if (begIdx == endIdx)
			{
				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);						
		} 
		/**
		 * Sets the TextRange at the end of the line.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 		 		 
		static public function endOfLine(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (!validateTextRange(range))
				return false;
			

			var textFlow:TextFlow = range.textFlow;
			checkCompose(textFlow.flowComposer, range.absoluteEnd);

			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
			var lineEnd:int = lineStart + textFlow.flowComposer.getLineAt(curLine).textLength - 1;
			
			var leaf:FlowLeafElement = textFlow.findLeaf(endIdx);
			var para:ParagraphElement = leaf.getParagraph();
			if (CharacterUtil.isWhitespace(para.getCharCodeAtPosition(lineEnd - para.getAbsoluteStart())))
			{
				endIdx = lineEnd;
			} else {
				endIdx = lineEnd + 1;
			}
			if (!extendSelection)
				begIdx = endIdx;							
			if (begIdx == endIdx)
			{
				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);
		 }
		 
		/**
		 * Sets the TextRange at the beginning of the line.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 		 		 		 
		static public function startOfLine(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (!validateTextRange(range))
				return false;
				
			var textFlow:TextFlow = range.textFlow;
			checkCompose(textFlow.flowComposer, range.absoluteEnd);
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
		
			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
			endIdx = lineStart;
			if (!extendSelection)
				begIdx = endIdx;							
			if (begIdx == endIdx)
			{
				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);
		} 
		/**
		 * Sets the TextRange at the end of the document.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 		 		 		 		 
		static public function endOfDocument(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (!validateTextRange(range))
				return false;
				
			var textFlow:TextFlow = range.textFlow
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
			endIdx = textFlow.textLength;
			if (!extendSelection)
				begIdx = endIdx;							
			if (begIdx == endIdx)
			{
				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			} else {
				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);				
		}
		
		/**
		 * Sets the TextRange at the beginning of the document.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 		 		 		 		 		 
		static public function startOfDocument(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			var begIdx:int = range.anchorPosition;
			var endIdx:int = 0;

			if (!extendSelection)
				begIdx = endIdx;							
			if (begIdx == endIdx)
			{
				begIdx = updateEndIfInReadOnlyElement(range.textFlow, begIdx);
				endIdx = updateStartIfInReadOnlyElement(range.textFlow, endIdx);
			} else {
				endIdx = updateStartIfInReadOnlyElement(range.textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);				
		}
		 
		/**
		 * Sets the TextRange at the beginning of the paragraph.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 		 		 		 		 		 		 
		static public function startOfParagraph(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
			var leaf:FlowLeafElement = range.textFlow.findLeaf(endIdx);
			var para:ParagraphElement = leaf.getParagraph();
			
			endIdx = para.getAbsoluteStart();
			if (!extendSelection)
				begIdx = endIdx;							

			if (begIdx == endIdx)
			{
				begIdx = updateStartIfInReadOnlyElement(range.textFlow, begIdx);
				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
			} else {
				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);
		 }
		 
		/**
		 * Sets the TextRange at the end of the paragraph.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return true if selection changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */		 		 		 		 		 		 		 		 		 		 		 		 		 		 
		static public function endOfParagraph(range:TextRange, extendSelection:Boolean = false):Boolean
		{
			if (!validateTextRange(range))
				return false;
				
			var begIdx:int = range.anchorPosition;
			var endIdx:int = range.activePosition;
			var leaf:FlowLeafElement = range.textFlow.findLeaf(endIdx);
			var para:ParagraphElement = leaf.getParagraph();
			
			endIdx = para.getAbsoluteStart() + para.textLength - 1;
			if (!extendSelection)
				begIdx = endIdx;							
			if (begIdx == endIdx)
			{
				begIdx = updateStartIfInReadOnlyElement(range.textFlow, begIdx);
				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
			} else {
				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
			}
			return range.updateRange(begIdx,endIdx);
		 }
	
		/** If the range is in overset text (after the last container in a non-scrolling flow), adjust the range so it is at the end of the flow. */
		static private function adjustForOversetForward(range:TextRange):Boolean
		{
			var flowComposer:IFlowComposer = range.textFlow.flowComposer;
			var controller:ContainerController = null;
			checkCompose(flowComposer, range.absoluteEnd);
			if (range.absoluteEnd > flowComposer.damageAbsoluteStart - 1)
			{
				clampToFit(range, flowComposer.damageAbsoluteStart - 1);
				return true;
			}
			if (flowComposer && flowComposer.numControllers)
			{
				var controllerIndex:int = flowComposer.findControllerIndexAtPosition(range.absoluteEnd);
				if (controllerIndex >= 0)
					controller = flowComposer.getControllerAt(controllerIndex);
				if (controllerIndex == flowComposer.numControllers-1)
				{
					if (controller.absoluteStart + controller.textLength <= range.absoluteEnd && controller.absoluteStart + controller.textLength != range.textFlow.textLength)
						controller = null;
				}
			}

			if (!controller)		// we're overset, or one position before overset
			{
				range.anchorPosition = range.textFlow.textLength;
				range.activePosition = range.anchorPosition;
				return true;
			}
			return false;
		}
		
		static private function clampToFit(range:TextRange, endPos:int):void
		{
			if (endPos < 0)
				endPos = 0;
			range.anchorPosition = Math.min(range.anchorPosition, endPos);
			range.activePosition = Math.min(range.activePosition, endPos); 
		}
		
		/** If the range is in overset text (after the last container in a non-scrolling flow), adjust the range so it is at the end of the last controller in the flow. */
		static private function adjustForOversetBack(range:TextRange):Boolean
		{
			var flowComposer:IFlowComposer = range.textFlow.flowComposer;
			if (flowComposer)
			{
				checkCompose(flowComposer, range.absoluteEnd);
				if (range.absoluteEnd > flowComposer.damageAbsoluteStart - 1)
				{
					clampToFit(range, flowComposer.damageAbsoluteStart - 1);
					return true;
				} 
				if (flowComposer.findControllerIndexAtPosition(range.absoluteEnd) == -1)
				{
					range.anchorPosition = endOfLastController(range.textFlow);
					range.activePosition = range.anchorPosition;
					return true;
				}				
			}
				
			return false;
		}
		
		private static function checkCompose(flowComposer:IFlowComposer, pos:int):void
		{
			if (flowComposer.damageAbsoluteStart <= pos)
				flowComposer.composeToPosition(pos);
		}
		
		// Returns absolute position of the last controller in the flow, or 0 if the flow has no controllers
		private static function endOfLastController(flowRoot:TextFlow):int
		{
			var flowComposer:IFlowComposer = flowRoot.flowComposer;
			if (!flowComposer || flowComposer.numControllers <= 0)
				return 0;
				
			var controller:ContainerController = flowComposer.getControllerAt(flowComposer.numControllers - 1);
			return controller.absoluteStart + Math.max(controller.textLength - 1, 0);
		}
		
		// Returns true if the position is in the overset text after the last container in the flow.
		private static function isOverset(flowRoot:TextFlow, absolutePos:int):Boolean
		{
			var flowComposer:IFlowComposer = flowRoot.flowComposer;
			return (!flowComposer || flowComposer.findControllerIndexAtPosition(absolutePos) == -1);
		}
	
		// Returns true if the position is in a scollable container
		private static function isScrollable(flowRoot:TextFlow, absolutePos:int):Boolean
		{
			var flowComposer:IFlowComposer = flowRoot.flowComposer;
			if (!flowComposer)
				return false;
			var controllerIndex:int = flowComposer.findControllerIndexAtPosition(absolutePos);
			if (controllerIndex >= 0)
			{
				var controller:ContainerController = flowComposer.getControllerAt(controllerIndex);
				var blockProgression:String = controller.rootElement.computedFormat.blockProgression;
				return ((blockProgression == BlockProgression.TB && controller.verticalScrollPolicy != ScrollPolicy.OFF) ||
					(blockProgression == BlockProgression.RL && controller.horizontalScrollPolicy != ScrollPolicy.OFF));
			}
			return false;
		}
		
	}
}
