////////////////////////////////////////////////////////////////////////////////
//
//  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.edit
{
	import flash.geom.Point;
	import flash.utils.getQualifiedClassName;
	
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowGroupElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.InlineGraphicElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.SubParagraphGroupElementBase;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.Float;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.tlf_internal;
	
	use namespace tlf_internal;

	[ExcludeClass]
	/**
	 * Encapsulates all methods necessary for dynamic editing of a text.  The methods are all static member functions of this class.
	 * @private - because we can't make it tlf_internal. Used by the operations package 
	 */
 	public class ParaEdit
	{
		/**
		 * Inserts text into specified paragraph
		 * @param textFlow		TextFlow to insert into
		 * @param absoluteStart	index relative to beginning of the TextFlow to insert text
		 * @param text	actual text to insert 
		 * @param createNewSpan	flag to force creation of a new span
		 */
		public static function insertText(textFlow:TextFlow, absoluteStart:int,insertText:String, createNewSpan:Boolean):SpanElement
		{
			if (insertText.length == 0)
				return null;	// error? other sanity checks needed here?
				
			var sibling:FlowElement = textFlow.findLeaf(absoluteStart);
			var siblingIndex:int;
			var paragraph:ParagraphElement = sibling.getParagraph();
			var paraStart:int = paragraph.getAbsoluteStart();
			var paraSelBegIdx:int = absoluteStart - paraStart;
			
			if (paraStart == absoluteStart)		// insert to start of paragraph
				siblingIndex = 0;
			else 
			{
				// If we're at the start a span, go to the previous span in the same paragraph, and insert at the end of it
				if (paraSelBegIdx == sibling.getElementRelativeStart(paragraph))
					sibling = FlowLeafElement(sibling).getPreviousLeaf(paragraph);	
				siblingIndex = sibling.parent.getChildIndex(sibling) + 1;
			}
			var insertParent:FlowGroupElement = sibling.parent;
			
			// If we are adding text to the start or end of a link, it doesn't allow the insertion to group with the link.
			// So in that case, we will insert to the element beside the position that is *not* part of the link.
			var curSPGElement:SubParagraphGroupElementBase = sibling.getParentByType(SubParagraphGroupElementBase) as SubParagraphGroupElementBase;
			while (curSPGElement != null)
			{
				var subParInsertionPoint:int = paraSelBegIdx - curSPGElement.getElementRelativeStart(paragraph);
				if (((subParInsertionPoint == 0) && (!curSPGElement.acceptTextBefore())) ||
					((!curSPGElement.acceptTextAfter() && (subParInsertionPoint == curSPGElement.textLength || 
					(subParInsertionPoint == curSPGElement.textLength - 1 && (sibling == paragraph.getLastLeaf()))))))
				{
					createNewSpan = true;
					sibling = insertParent;
					insertParent = insertParent.parent;
					curSPGElement = curSPGElement.getParentByType(SubParagraphGroupElementBase) as SubParagraphGroupElementBase;
					siblingIndex = insertParent.getChildIndex(sibling) + 1;
				} else {
					break;
				}
			}
				
			// adjust the flow so that we are in a span for the insertion
			var insertSpan:SpanElement = sibling as SpanElement;
			if (!insertSpan || createNewSpan)
			{
				var newSpan:SpanElement = new SpanElement();
				var insertIdx:int;
				if (siblingIndex > 0)
				{
					var relativeStart:int = paraSelBegIdx - sibling.getElementRelativeStart(paragraph);
					if (createNewSpan)
					{
						if (relativeStart == 0)
							siblingIndex--;
						else if (relativeStart != sibling.textLength)
							sibling.splitAtPosition(relativeStart);		// we'll insert between the two elements
					}
				}
				insertParent.replaceChildren(siblingIndex, siblingIndex, newSpan);
				var formatElem:FlowLeafElement = newSpan.getPreviousLeaf(paragraph);
				if (formatElem == null)
					newSpan.format = newSpan.getNextLeaf(paragraph).format;
				else
					newSpan.format = formatElem.format;
					
				insertSpan = newSpan;
			}
			
			var runInsertionPoint:int = paraSelBegIdx - insertSpan.getElementRelativeStart(paragraph);
			
				
			insertSpan.replaceText(runInsertionPoint, runInsertionPoint, insertText);
			return insertSpan;
		}
		
		private static function deleteTextInternal(para:ParagraphElement, paraSelBegIdx:int, totalToDelete:int):void
		{
			var composeNode:FlowElement;
			var curSpan:SpanElement;
			
			var curNumToDelete:int;
			var curSpanDeletePos:int = 0;
			
			while (totalToDelete > 0)
			{
				composeNode = para.findLeaf(paraSelBegIdx);
				CONFIG::debug { assert(composeNode is SpanElement,"deleteTextInternal: leaf element is not a span"); }
								
				curSpan = composeNode as SpanElement;
				var curSpanRelativeStart:int = curSpan.getElementRelativeStart(para);
				curSpanDeletePos = paraSelBegIdx - curSpanRelativeStart;
				if (paraSelBegIdx > (curSpanRelativeStart + curSpan.textLength))
				{
					curNumToDelete = curSpan.textLength;
				}
				else
				{
					curNumToDelete = (curSpanRelativeStart + curSpan.textLength) - paraSelBegIdx;
				}
				
				if (totalToDelete < curNumToDelete)
				{
					curNumToDelete = totalToDelete;
				}
				
				curSpan.replaceText(curSpanDeletePos, curSpanDeletePos + curNumToDelete, "");
				if (curSpan.textLength == 0)
				{
					var delIdx:int = curSpan.parent.getChildIndex(curSpan);
					curSpan.parent.replaceChildren(delIdx,delIdx+1,null);						
				}
				totalToDelete -= curNumToDelete;
			}			
		}
		
		public static function deleteText(para:ParagraphElement, paraSelBegIdx:int, totalToDelete:int):void
		{
			var lastParPos:int = para.textLength - 1;
			if ((paraSelBegIdx < 0) || (paraSelBegIdx > lastParPos))
			{
				//not much we can do. There's nothing to delete in this paragraph
				return;
			}
			
			if (totalToDelete <= 0)
			{
				//can't delete a negative number of characters... just return
				return;
			}
			
			var endPos:int = paraSelBegIdx + totalToDelete - 1;
			if (endPos > lastParPos)
			{
				endPos = lastParPos;
				totalToDelete = endPos - paraSelBegIdx + 1
			}
			
			deleteTextInternal(para,paraSelBegIdx,totalToDelete);
		}
		
		/**
		 * Creates image and inserts it into specified FlowGroupElement
		 * @param flowBlock	FlowGroupElement to insert image into
		 * @param flowSelBegIdx	index relative to beginning of the FlowGroupElement to insert image
		 * @param urlString	the url of image to insert
		 * @param width	the width of the image
		 * @param height the height of the image
		 * @param options none supported
		 */
		public static function createImage(flowBlock:FlowGroupElement, flowSelBegIdx:int,source:Object, width:Object, height:Object, options:Object, pointFormat:ITextLayoutFormat):InlineGraphicElement
		{
			//first, split the element that we are on
			var curComposeNode:FlowElement = flowBlock.findLeaf(flowSelBegIdx);
			var posInCurComposeNode:int = 0;
			if (curComposeNode != null)
			{
				posInCurComposeNode = flowSelBegIdx - curComposeNode.getElementRelativeStart(flowBlock); // curComposeNode.parentRelativeStart;
			}			
			
			if ((curComposeNode != null) && (posInCurComposeNode > 0) && (posInCurComposeNode < curComposeNode.textLength))
			{
				//it is a LeafElement, and not position 0. It has to be a Span 
				(curComposeNode as SpanElement).splitAtPosition(posInCurComposeNode);
			}
			
			//the FlowElement or FlowGroupElement is now split.  Insert the image now.
			var imgElem:InlineGraphicElement = new InlineGraphicElement();
			imgElem.height = height;
			imgElem.width = width;
			imgElem.float = options ? options.toString() : undefined;
			
			var src:Object = source;
			var embedStr:String = "@Embed";
			if (src is String && src.length > embedStr.length && src.substr(0, embedStr.length) == embedStr) {
				// we should be dealing with an embedded asset. They are of the form "url=@Embed(source='path-to-asset')"
				var searchStr:String = "source=";
				var index:int = src.indexOf(searchStr, embedStr.length);
				if (index > 0) {
					index += searchStr.length;
					index = src.indexOf("'", index);
					src = src.substring(index+1, src.indexOf("'", index+1));
				}
			}
			imgElem.source = src;
			
			while (curComposeNode && curComposeNode.parent != flowBlock)
			{
				curComposeNode = curComposeNode.parent;
			}

			var elementIdx:int = curComposeNode != null ? flowBlock.getChildIndex(curComposeNode) : flowBlock.numChildren;
			if (curComposeNode && posInCurComposeNode > 0)
				elementIdx++;
			flowBlock.replaceChildren(elementIdx,elementIdx,imgElem);
			
			//clone characterFormat from the left OR iff the the first element the right
			var p:ParagraphElement = imgElem.getParagraph();
			var attrElem:FlowLeafElement = imgElem.getPreviousLeaf(p);
			if (!attrElem)
				attrElem = imgElem.getNextLeaf(p);
			CONFIG::debug { assert(attrElem != null, "no element to get attributes from"); }
			
			if (attrElem.format || pointFormat)
			{
				var imageElemFormat:TextLayoutFormat = new TextLayoutFormat(attrElem.format);
				if (pointFormat)
					imageElemFormat.apply(pointFormat);
				imgElem.format = imageElemFormat;
			}
			return imgElem;			
		}		
		
		/** Merge changed attributes into this
		 */
		static private function splitForChange(span:SpanElement,begIdx:int,rangeLength:int):SpanElement
		{
			var startOffset:int = span.getAbsoluteStart();
			if (begIdx == startOffset && rangeLength == span.textLength)
				return span;
				
			// element must be split into spans
			var elemToUpdate:SpanElement;
			var origLength:int = span.textLength;
			
			var begRelativeIdx:int = begIdx - startOffset;
			if (begRelativeIdx > 0)
			{
				// We create an initial span to hold the text before the new span, then
				// a following span for the specified range.
				elemToUpdate = span.splitAtPosition(begRelativeIdx) as SpanElement;
				if (begRelativeIdx + rangeLength < origLength)
					elemToUpdate.splitAtPosition(rangeLength);
			}
			else
			{
				// The specified range falls at the start of the element, so this span is the 
				// one that's getting the new format.
				span.splitAtPosition(rangeLength);
				elemToUpdate = span;
			}

			return elemToUpdate;
		}
		
		private static function undefineDefinedFormats(target:TextLayoutFormat,undefineFormat:ITextLayoutFormat):void
		{
			if (undefineFormat)
			{
				// this is fairly rare so this operation is not optimizied
				var tlfUndefineFormat:TextLayoutFormat;
				if (undefineFormat is TextLayoutFormat)
					tlfUndefineFormat = undefineFormat as TextLayoutFormat;
				else 
					tlfUndefineFormat = new TextLayoutFormat(undefineFormat);
				for (var prop:String in tlfUndefineFormat.styles)
					target.setStyle(prop, undefined);
			}
		}

		/**
		 * Apply formatting changes to a range of text in the FlowElement
		 *
		 * @param begIdx	text index of first text in span
		 * @param rangeLength	number of characters to modify
		 * @param applyFormat		Character Format to apply to content
		 * @param undefineFormat	Character Format to undefine to content
		 * @return begIdx + number of actual actual characters modified.
		 */
		static private function applyCharacterFormat(leaf:FlowLeafElement, begIdx:int, rangeLength:int, applyFormat:ITextLayoutFormat, undefineFormat:ITextLayoutFormat):int
		{
			var newFormat:TextLayoutFormat = new TextLayoutFormat(leaf.format);
			if (applyFormat)
				newFormat.apply(applyFormat);
			undefineDefinedFormats(newFormat,undefineFormat);
			return setCharacterFormat(leaf, newFormat, begIdx, rangeLength);
		}
		
		/**
		 * Set formatting to a range of text in the FlowElement
		 *
		 * @param format	Character Format to apply to content
		 * @param begIdx	text index of first text in span
		 * @param rangeLength	number of characters to modify
		 * @return starting position of following span
		 */
		static private function setCharacterFormat(leaf:FlowLeafElement, format:ITextLayoutFormat, begIdx:int, rangeLength:int):int
		{
			var startOffset:int = leaf.getAbsoluteStart();
			if (!(format is ITextLayoutFormat) || !TextLayoutFormat.isEqual(ITextLayoutFormat(format),leaf.format))
			{				
				var para:ParagraphElement = leaf.getParagraph();
				var paraStartOffset:int = para.getAbsoluteStart();
				
				// clip rangeLength to the length of this span. Extend the rangeLength by one to include the terminator if
				// it is in the span, and the end of the range abuts the terminator. That way the terminator will stay in the 
				// last span.
				var begRelativeIdx:int = begIdx - startOffset;
				if (begRelativeIdx + rangeLength > leaf.textLength)
					rangeLength = leaf.textLength - begRelativeIdx;
				if (begRelativeIdx + rangeLength == leaf.textLength - 1 && (leaf is SpanElement) && SpanElement(leaf).hasParagraphTerminator)
					++rangeLength;
				
				var elemToUpdate:FlowLeafElement
				if (leaf is SpanElement)
					elemToUpdate = splitForChange(SpanElement(leaf),begIdx,rangeLength);
				else
				{
					CONFIG::debug { assert(rangeLength >= leaf.textLength,"unable to split non-span leaf"); }
					elemToUpdate = leaf;
				}
				
				if (format is ITextLayoutFormat)
					elemToUpdate.format = ITextLayoutFormat(format);
				else
					elemToUpdate.setStylesInternal(format);
				
				return begIdx+rangeLength;
			}
			
			rangeLength = leaf.textLength;
			return startOffset+rangeLength;
		}
		
		public static function applyTextStyleChange(flowRoot:TextFlow,begChange:int,endChange:int,applyFormat:ITextLayoutFormat,undefineFormat:ITextLayoutFormat):void
		{	
			// TODO: this code only works for span's.  Revisit when new FlowLeafElement types enabled
			var workIdx:int = begChange;
			while (workIdx < endChange)
			{
				var elem:FlowLeafElement = flowRoot.findLeaf(workIdx);
				CONFIG::debug  { assert(elem != null,"null FlowLeafElement found"); }
				workIdx = applyCharacterFormat(elem,workIdx,endChange-workIdx,applyFormat,undefineFormat); 
			}
		}
		
		// used for undo of operation
		public static function setTextStyleChange(flowRoot:TextFlow,begChange:int, endChange:int, coreStyle:ITextLayoutFormat):void
		{
			// TODO: this code only works for span's.  Revisit when new FlowLeafElement types enabled
			var workIdx:int = begChange;
			while (workIdx < endChange)
			{
				var elem:FlowElement = flowRoot.findLeaf(workIdx);
				CONFIG::debug  { assert(elem != null,"null FlowLeafElement found"); }
				workIdx = setCharacterFormat(FlowLeafElement(elem),coreStyle,workIdx,endChange-workIdx);
			}
		}
		
		public static function splitElement(elem:FlowGroupElement, splitPos:int):FlowGroupElement
		{
			CONFIG::debug { assert(splitPos >= 0 && splitPos <= elem.textLength, "Invalid call to ParaEdit.splitElement"); }
			
			var rslt:FlowGroupElement = elem.splitAtPosition(splitPos) as FlowGroupElement;
			
			// rslt always follows elem
			

			if (!(rslt is SubParagraphGroupElementBase))
			{
				
				// need to insure there is a paragraph and a span on each side
				var rsltParagraph:FlowGroupElement = rslt;
				while (!(rsltParagraph is ParagraphElement) && rsltParagraph.numChildren)
					rsltParagraph = rsltParagraph.getChildAt(0) as FlowGroupElement;
				
				var elemParagraph:FlowGroupElement = elem;
				while (!(elemParagraph is ParagraphElement) && elemParagraph.numChildren)
					elemParagraph = elemParagraph.getChildAt(elemParagraph.numChildren-1) as FlowGroupElement;
				
				CONFIG::debug { assert (elemParagraph is ParagraphElement || rsltParagraph is ParagraphElement,"ParaEdit.splitElement didn't find at least one paragraph"); }
				
				var p:ParagraphElement;
				
				if (!(elemParagraph is ParagraphElement))
				{
					// clone rlstParagraph
					p = rsltParagraph.shallowCopy() as ParagraphElement;
					elemParagraph.addChild(p);
					elemParagraph = p;
				}
				else if (!(rsltParagraph is ParagraphElement))
				{
					p = elemParagraph.shallowCopy() as ParagraphElement;
					rsltParagraph.addChild(p);
					rsltParagraph = p;						
				}
				
				// if we have an empty before or after para need to make sure the formats got copied
				if (elemParagraph.textLength <= 1)
				{
					elemParagraph.normalizeRange(0,elemParagraph.textLength);
					elemParagraph.getLastLeaf().quickCloneTextLayoutFormat(rsltParagraph.getFirstLeaf());
				}
				else if (rsltParagraph.textLength <= 1)
				{
					rsltParagraph.normalizeRange(0,rsltParagraph.textLength);
					rsltParagraph.getFirstLeaf().quickCloneTextLayoutFormat(elemParagraph.getLastLeaf());
				}
			}

			return rslt;
		}		
		// TODO: rewrite this method by moving the elements.  This is buggy.
		public static function mergeParagraphWithNext(para:ParagraphElement):Boolean
		{
			var indexOfPara:int = para.parent.getChildIndex(para);
			
			// last can't merge
			if (indexOfPara == para.parent.numChildren-1)
				return false;
				
			var nextPar:ParagraphElement  = para.parent.getChildAt(indexOfPara + 1) as ParagraphElement;
			// next is not a paragraph
			if (nextPar == null)
				return false;
				
			// remove nextPar from its parent - do this first because it will require less updating of starts and lengths
			para.parent.replaceChildren(indexOfPara+1,indexOfPara+2,null);
			if (nextPar.textLength <= 1) 
				return true;
			
			// move all the elements
			while (nextPar.numChildren)
			{
				var elem:FlowElement = nextPar.getChildAt(0);
				nextPar.replaceChildren(0,1,null);
				para.replaceChildren(para.numChildren,para.numChildren,elem);
				if ((para.numChildren >  1) && (para.getChildAt(para.numChildren - 2).textLength == 0))
				{
					//bug 1658164
					//imagine that the last element of para is only a kParaTerminator (like a single
					//span of length 1 that only contains a kParaTerminator, and you merge with the
					//next paragraph. That kParaTerminator will move, leaving an empty leaf element
					para.replaceChildren(para.numChildren - 2, para.numChildren - 1, null);
				}
			}

			return true;
		}
		
		public static function cacheParagraphStyleInformation(flowRoot:TextFlow,begSel:int,endSel:int,undoArray:Array):void
		{
			while (begSel <= endSel && begSel >= 0)
			{
				var para:ParagraphElement = flowRoot.findLeaf(begSel).getParagraph();
				
				// build an object holding the old style and format
				var obj:Object = new Object();
				obj.begIdx = para.getAbsoluteStart();
				obj.endIdx = obj.begIdx + para.textLength - 1;
				obj.attributes = new TextLayoutFormat(para.format);
				undoArray.push(obj);

				begSel = obj.begIdx + para.textLength;
			}
		}

		/**
		 * Replace the existing paragraph attributes with the incoming attributes.
		 * 
		 * @param flowRoot	text flow where paragraphs are
		 * @param format	attributes to apply
		 * @param beginIndex	text index within the first paragraph in the range
		 * @param endIndex		text index within the last paragraph in the range
		 */
		// used for undo of operation
		public static function setParagraphStyleChange(flowRoot:TextFlow,begChange:int, endChange:int, format:ITextLayoutFormat):void
		{
			var beginPara:int = begChange;
			while (beginPara <= endChange)
			{
				var para:ParagraphElement = flowRoot.findLeaf(beginPara).getParagraph();
				
				para.format = format ? new TextLayoutFormat(format) : null;
				beginPara = para.getAbsoluteStart() + para.textLength;
			}
		}
		
		/**
		 * Additively apply the paragraph formating attributes to the paragraphs in the specified range.
		 * Each non-null field in the incoming format is copied into the existing paragraph attributes.
		 * 
		 * @param flowRoot	text flow where paragraphs are
		 * @param format	attributes to apply
		 * @param beginIndex	text index within the first paragraph in the range
		 * @param endIndex		text index within the last paragraph in the range
		 */
		public static function applyParagraphStyleChange(flowRoot:TextFlow,begChange:int,endChange:int,applyFormat:ITextLayoutFormat,undefineFormat:ITextLayoutFormat):void
		{	
			var curIndex:int = begChange;
			while (curIndex <= endChange)
			{
				var leaf:FlowLeafElement = flowRoot.findLeaf(curIndex);
				if (!leaf)
					break;
				var para:ParagraphElement = leaf.getParagraph();
				
				// now, need to get the change from "format" and apply to para. We make
				// a new ParagraphFormat object instead of changing the ParagraphFormat
				// already in the paragraph so that if the object is shared, other uses
				// in other paragraphs will not be affected.
				var newFormat:TextLayoutFormat = new TextLayoutFormat(para.format);
				if (applyFormat)
					newFormat.apply(applyFormat);
				undefineDefinedFormats(newFormat,undefineFormat);
				para.format = newFormat;
				
				curIndex = para.getAbsoluteStart() + para.textLength;
			}		
		}

		public static function cacheStyleInformation(flowRoot:TextFlow,begSel:int,endSel:int,undoArray:Array):void
		{
			var elem:FlowElement = flowRoot.findLeaf(begSel);
			var elemLength:int = elem.getAbsoluteStart()+elem.textLength-begSel;
			var countRemaining:int = endSel - begSel;
			CONFIG::debug { assert(countRemaining != 0,"cacheStyleInformation called on point selection"); }
			for (;;)
			{
				// build an object holding the old style and format
				var obj:Object = new Object();

				obj.begIdx = begSel;
				var objLength:int = Math.min(countRemaining, elemLength);
				obj.endIdx = begSel + objLength;
				
				// just the styles
				obj.style = new TextLayoutFormat(elem.format);
				undoArray.push(obj);
				
				countRemaining -= Math.min(countRemaining, elemLength);
				if (countRemaining == 0)
					break;
				
				// advance
				begSel = obj.endIdx;
				
				elem = flowRoot.findLeaf(begSel);
				elemLength = elem.textLength;
			}
		}
		
		public static function cacheContainerStyleInformation(flowRoot:TextFlow,begIdx:int,endIdx:int,undoArray:Array):void
		{
			CONFIG::debug { assert(begIdx <= endIdx,"bad indexeds passed to ParaEdit.cacheContainerStyleInformation");  }
			if (flowRoot.flowComposer)
			{
				var startIdx:int = flowRoot.flowComposer.findControllerIndexAtPosition(begIdx,false);
				if (startIdx == -1)
					return;
				var endIdx:int = flowRoot.flowComposer.findControllerIndexAtPosition(endIdx,true);
				if (endIdx == -1)
					endIdx = flowRoot.flowComposer.numControllers-1;
				while (startIdx <= endIdx)
				{
					var controller:ContainerController = flowRoot.flowComposer.getControllerAt(startIdx);
					var obj:Object = new Object();
					obj.container = controller;
					// save just the styles
					obj.attributes = new TextLayoutFormat(controller.format);
					undoArray.push(obj);
					startIdx++;
				}
			}
		}

		public static function applyContainerStyleChange(flowRoot:TextFlow,begIdx:int,endIdx:int,applyFormat:ITextLayoutFormat,undefineFormat:ITextLayoutFormat):void
		{
			CONFIG::debug { assert(begIdx <= endIdx,"bad indexes passed to ParaEdit.cacheContainerStyleInformation");  }
			if (flowRoot.flowComposer)
			{
				var startIdx:int = flowRoot.flowComposer.findControllerIndexAtPosition(begIdx,false);
				if (startIdx == -1)
					return;
				var endIdx:int = flowRoot.flowComposer.findControllerIndexAtPosition(endIdx,true);
				if (endIdx == -1)
					endIdx = flowRoot.flowComposer.numControllers-1;
				var controllerIndex:int = flowRoot.flowComposer.findControllerIndexAtPosition(begIdx,false);
				while (startIdx <= endIdx)
				{
					var controller:ContainerController = flowRoot.flowComposer.getControllerAt(startIdx);
					var newFormat:TextLayoutFormat = new TextLayoutFormat(controller.format);
					if (applyFormat)
						newFormat.apply(applyFormat);
					undefineDefinedFormats(newFormat,undefineFormat);
					controller.format = newFormat;
					startIdx++;
				}
			}
		}

		/** obj is created by cacheContainerStyleInformation */
		public static function setContainerStyleChange(obj:Object):void
		{
			obj.container.format = obj.attributes as ITextLayoutFormat;
		}
	}
}
