http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as 
b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
index f4579fc..1fec299 100644
--- a/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
+++ b/textLayout/src/flashx/textLayout/elements/ParagraphElement.as
@@ -31,9 +31,9 @@ package flashx.textLayout.elements
        import flash.text.engine.TextLine;
        import flash.text.engine.TextLineValidity;
        import flash.text.engine.TextRotation;
+       import flash.utils.Dictionary;
        import flash.utils.getQualifiedClassName;
        
-       import flashx.textLayout.tlf_internal;
        import flashx.textLayout.compose.TextFlowLine;
        import flashx.textLayout.container.ContainerController;
        import flashx.textLayout.debug.Debugging;
@@ -50,6 +50,7 @@ package flashx.textLayout.elements
        import flashx.textLayout.formats.TextJustify;
        import flashx.textLayout.formats.TextLayoutFormat;
        import flashx.textLayout.property.Property;
+       import flashx.textLayout.tlf_internal;
        import flashx.textLayout.utils.CharacterUtil;
        import flashx.textLayout.utils.LocaleUtil;
        
@@ -79,7 +80,8 @@ package flashx.textLayout.elements
         
        public final class ParagraphElement extends ParagraphFormattedElement
        {
-               private var _textBlock:TextBlock;
+               //private var _textBlock:TextBlock;
+               private var _textBlockChildren:Dictionary;
                private var _terminatorSpan:SpanElement;
                
                private var _interactiveChildrenCount:int;
@@ -95,6 +97,7 @@ package flashx.textLayout.elements
                        super();
                        _terminatorSpan = null;
                        _interactiveChildrenCount = 0 ;
+                       _textBlockChildren = new Dictionary();
                }
                tlf_internal function get interactiveChildrenCount():int
                {
@@ -106,26 +109,83 @@ package flashx.textLayout.elements
                {
                        CONFIG::debug { assert(_textBlock == 
null,"createTextBlock called when there is already a textblock"); }
                        computedFormat; // recreate the format BEFORE the 
_textBlock is created
-                       _textBlock = new TextBlock();
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       //tbs.length = 0;
+                       var tableCount:int = 0;
+                       if(tbs.length == 0 && !(getChildAt(0) is TableElement) )
+                               tbs.push(new TextBlock());
+                       //getTextBlocks()[0] = new TextBlock();
                        CONFIG::debug { 
Debugging.traceFTECall(_textBlock,null,"new TextBlock()"); }
                        for (var i:int = 0; i < numChildren; i++)
                        {
                                var child:FlowElement = getChildAt(i);
+                               if(child is TableElement)
+                                       tableCount++;
+//                                     tbs.push(new TextBlock());
+                               else
+                               {
+                                       //child.releaseContentElement();
+                                       //child.createContentElement();
+                               }
+                       }
+                       while(tableCount >= tbs.length)
+                               tbs.push(new TextBlock());
+                       
+                       for (i = 0; i < numChildren; i++)
+                       {
+                               child = getChildAt(i);
                                child.createContentElement();
                        }
-                       updateTextBlock();
+                       tbs.length = tableCount + 1;
+                       var tb:TextBlock;
+                       for each(tb in tbs){
+                               updateTextBlock(tb);
+                       }
                }
-               
-               /** @private */
-               
-               tlf_internal function releaseTextBlock():void
+               private function updateTextBlockDict():void
+               {
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       if(tbs.length == 0)
+                               return;//nothing to do
+                       var tbIdx:int = 0;
+                       var tb:TextBlock = tbs[tbIdx];
+                       var items:Array = [];
+                       var child:FlowElement;
+                       for (var i:int = 0; i < numChildren; i++)
+                       {
+                               child = getChildAt(i);
+                               if(child is TableElement)
+                               {
+                                       _textBlockChildren[tb] = items;
+                                       tb = tbs[++tbIdx];
+                                       items = [];
+                                       continue;
+                               }
+                               items.push(child);
+                       }
+                       _textBlockChildren[tb] = items;
+               }
+               private function removeTextBlock(tb:TextBlock):void
+               {
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       if(tbs)
+                       {
+                               var idx:int = getTextBlocks().indexOf(tb);
+                               if(idx > -1)
+                               {
+                                       tbs.splice(idx,1);
+                                       delete _textBlockChildren[tb];
+                               }
+                       }
+               }
+               private function releaseTextBlockInternal(tb:TextBlock):void
                {
-                       if (!_textBlock)
+                       if (!tb)
                                return;
-                               
-                       if (_textBlock.firstLine)       // A TextBlock may have 
no firstLine if it has previously been released.
+                       
+                       if (tb.firstLine)       // A TextBlock may have no 
firstLine if it has previously been released.
                        {
-                               for (var textLineTest:TextLine = 
_textBlock.firstLine; textLineTest != null; textLineTest = 
textLineTest.nextLine)
+                               for (var textLineTest:TextLine = tb.firstLine; 
textLineTest != null; textLineTest = textLineTest.nextLine)
                                {       
                                        if(textLineTest.numChildren != 0)
                                        {       
@@ -138,55 +198,169 @@ package flashx.textLayout.elements
                                        }
                                }
                                
-                               CONFIG::debug { 
Debugging.traceFTECall(null,_textBlock,"releaseLines",_textBlock.firstLine, 
_textBlock.lastLine); }                             
-                               _textBlock.releaseLines(_textBlock.firstLine, 
_textBlock.lastLine);     
+                               CONFIG::debug { 
Debugging.traceFTECall(null,tb,"releaseLines",tb.firstLine, tb.lastLine); }     
                        
+                               tb.releaseLines(tb.firstLine, tb.lastLine);     
                        }       
-
-                       _textBlock.content = null;
-                       for (var i:int = 0; i < numChildren; i++)
+                       var items:Array = _textBlockChildren[tb];
+                       var len:int = items.length;
+                       for (var i:int = 0; i < len; i++)
                        {
-                               var child:FlowElement = getChildAt(i);
+                               var child:FlowElement = items[i];
                                child.releaseContentElement();
                        }
-                       _textBlock = null;
+                       items.length = 0;
+                       tb.content = null;
+                       removeTextBlock(tb);
+               }
+               /** @private */
+               tlf_internal function releaseTextBlock(tb:TextBlock=null):void
+               {
+                       updateTextBlockDict();
+                       if(tb)
+                       {
+                               releaseTextBlockInternal(tb);
+                               return;
+                       }
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       for each(var tb:TextBlock in tbs)
+                       {
+                               releaseTextBlockInternal(tb);
+                       }
+                       //_textBlock = null;
                        if (_computedFormat)
                                _computedFormat = null;
                }
-               
+               private var _textBlocks:Vector.<TextBlock>;
+               tlf_internal function getTextBlocks():Vector.<TextBlock>
+               {
+                       if(_textBlocks == null)
+                               _textBlocks = new Vector.<TextBlock>();
+                       return _textBlocks;
+               }
                /** TextBlock where the text of the paragraph is kept. @private 
*/
                tlf_internal function getTextBlock():TextBlock
-               { 
-                       if (!_textBlock)
+               {
+                       if (!getTextBlocks().length)
+                               createTextBlock();
+                       
+                       return getTextBlocks()[0]; 
+               }
+               /** Last TextBlock where the text of the paragraph is kept. 
@private */
+               tlf_internal function getLastTextBlock():TextBlock
+               {
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       if(!tbs.length)
                                createTextBlock();
-                       return _textBlock; 
+                       
+                       return tbs[tbs.length-1];
+               }
+
+               /** Get TextBlock at specified position. @private */
+               tlf_internal function getTextBlockAtPosition(pos:int):TextBlock
+               {
+                       var curPos:int = 0;
+                       var posShift:int = 0;
+                       var tables:Vector.<TableElement> = getTables();
+                       if(!tables.length)
+                               return getTextBlock();
+                       
+                       for each(var table:TableElement in tables)
+                       {
+                               if(table.getElementRelativeStart(this) < pos)
+                                       posShift++;
+                       }
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       for each(var tb:TextBlock in tbs)
+                       {
+                               if(tb.content == null)
+                                       return tb;
+                               curPos += tb.content.rawText.length;
+                               if(curPos + posShift > pos)
+                               {
+                                       if(getTextBlockStart(tb) > pos)
+                                               return null;
+                                       return tb;
+                               }
+                       }
+                       return null;
+               }
+               
+               tlf_internal function 
getTextBlockAbsoluteStart(tb:TextBlock):int
+               {
+                       var start:int = getTextBlockStart(tb);
+                       if(start < 0)
+                               start = 0;
+                       return getAbsoluteStart() + start;
+               }
+               tlf_internal function getTextBlockStart(tb:TextBlock):int
+               {
+                       var i:int;
+                       var curPos:int = 0;
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       if(tbs.length == 0)
+                               return -1;
+                       var tables:Vector.<TableElement> = getTables();
+                       for each(var curTB:TextBlock in tbs)
+                       {
+                               for each(var table:TableElement in tables)
+                               {
+                                       if(table.getElementRelativeStart(this) 
<= curPos)
+                                       {
+                                               curPos++;
+                                               
tables.splice(tables.indexOf(table),1);
+                                       }
+                               }
+                               if(tb == curTB)
+                                       return curPos;
+                               if(tb.content)
+                                       curPos += curTB.content.rawText.length;
+                       }
+                       
+                       return -1;
                }
                
+               private function getTables():Vector.<TableElement>
+               {
+                       var tables:Vector.<TableElement> = new 
Vector.<TableElement>();
+                       for (var i:int = 0; i < numChildren; i++)
+                       {
+                               var child:FlowElement = getChildAt(i);
+                               if(child is TableElement)
+                                       tables.push(child as TableElement);
+                       }
+                       return tables;
+               }
+
                /** TextBlock where the text of the paragraph is kept, or null 
if we currently don't have one. @private */
                tlf_internal function peekTextBlock():TextBlock
                { 
-                       return _textBlock; 
+                       return getTextBlocks().length == 0 ? null : 
getTextBlocks()[0];
                }
                
                /** @private */
                tlf_internal function releaseLineCreationData():void
                {
                        CONFIG::debug { 
assert(Configuration.playerEnablesArgoFeatures,"bad call to 
releaseLineCreationData"); }
-                       if (_textBlock)
-                               _textBlock["releaseLineCreationData"]();
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       for each(var tb:TextBlock in tbs)
+                       {
+                               tb["releaseLineCreationData"]();
+                       }
                }
                
                /** @private */
-               tlf_internal override function 
createContentAsGroup():GroupElement
-               {                       
-                       var group:GroupElement = _textBlock.content as 
GroupElement;
+               tlf_internal override function 
createContentAsGroup(pos:int=0):GroupElement
+               {
+                       var tb:TextBlock = getTextBlockAtPosition(pos);
+                       var group:GroupElement = tb.content as GroupElement;
                        if (!group)
                        {
-                               var originalContent:ContentElement = 
_textBlock.content;
+                               var originalContent:ContentElement = tb.content;
                                
                                group = new GroupElement();
                                CONFIG::debug { 
Debugging.traceFTECall(group,null,"new GroupElement()"); }
-                               _textBlock.content = group;
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"content",group); }
+                               tb.content = group;
+                               CONFIG::debug { 
Debugging.traceFTEAssign(tb,"content",group); }
 
                                if (originalContent)
                                {
@@ -199,7 +373,7 @@ package flashx.textLayout.elements
                                }
                                
                                // Now we've got to force damage the entire 
paragraph, because we restructured it in FTE.
-                               if (_textBlock.firstLine && textLength)
+                               if (tb.firstLine && textLength)
                                {
                                        var textFlow:TextFlow = getTextFlow();
                                        if (textFlow)
@@ -212,7 +386,15 @@ package flashx.textLayout.elements
                /** @private */
                tlf_internal override function 
removeBlockElement(child:FlowElement, block:ContentElement):void
                {
-                       if (numChildren == 1)
+                       var tb:TextBlock = 
getTextBlockAtPosition(child.getElementRelativeStart(this));
+                       if(!tb)
+                               tb = getTextBlock();
+                       
+                       if(tb.content == null)
+                               return;
+                       var relativeStart:int = 
child.getElementRelativeStart(this);
+
+                       if (getChildrenInTextBlock(relativeStart).length < 2)
                        {
                                if (block is GroupElement)
                                {
@@ -221,18 +403,20 @@ package flashx.textLayout.elements
                                        CONFIG::debug { 
assert(_textBlock.content is GroupElement,"removeBlockElement: bad content"); }
                                        CONFIG::debug { 
assert(GroupElement(_textBlock.content).elementCount == 1,"removeBlockElement: 
bad element count"); }
                                        CONFIG::debug { 
assert(GroupElement(_textBlock.content).getElementAt(0) == 
block,"removeBlockElement: bad group content"); }
-                                       
GroupElement(_textBlock.content).replaceElements(0,1,null);
+                                       
GroupElement(tb.content).replaceElements(0,1,null);
                                        CONFIG::debug { 
Debugging.traceFTECall(null,_textBlock.content,"replaceElements",0,1,null); }
                                }
-                               _textBlock.content = null;
+                               tb.content = null;
                                CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"content",null); }
                        }
-                       else
+                       else if(block.groupElement)
                        {
-                               var idx:int = this.getChildIndex(child);
-                               var group:GroupElement = 
GroupElement(_textBlock.content);
+                               var idx:int = getChildIndexInBlock(child);
+                               var group:GroupElement = 
GroupElement(tb.content);
                                CONFIG::debug { assert(group.elementCount == 
numChildren,"Mismatched group and elementCount"); }
                                group.replaceElements(idx,idx+1,null);
+                               if(group.elementCount == 0)
+                                       return;
                                CONFIG::debug { 
Debugging.traceFTECall(null,group,"replaceElements",idx,idx+1,null); }
                                if (numChildren == 2)   // its going to be one 
so ungroup
                                {
@@ -243,18 +427,22 @@ package flashx.textLayout.elements
                                        {
                                                group.replaceElements(0,1,null);
                                                CONFIG::debug { 
Debugging.traceFTECall(null,group,"replaceElements",0,1,null); }
-                                               _textBlock.content = elem;
-                                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"content",elem); }
+                                               tb.content = elem;
+                                               CONFIG::debug { 
Debugging.traceFTEAssign(tb,"content",elem); }
                                        }
                                }
                        }
+                       else {
+                               //trace("1");
+                               //tb.content = null;
+                       }
                }
                
                
                /** @private */
                tlf_internal override function hasBlockElement():Boolean
                {
-                       return _textBlock != null;
+                       return getTextBlocks().length > 0;
                }
                
                /** @private */
@@ -264,9 +452,42 @@ package flashx.textLayout.elements
                }
                
                /** @private */
+               private function getChildrenInTextBlock(pos:int):Array
+               {
+                       var retVal:Array = [];
+                       if(numChildren == 0)
+                               return retVal;
+                       if(numChildren == 1)
+                       {
+                               retVal.push(getChildAt(0));
+                               return retVal
+                       }
+                       var chldrn:Array = mxmlChildren.slice();
+                       for(var i:int = 0; i<chldrn.length;i++)
+                       {
+                               if(chldrn[i] is TableElement)
+                               {
+                                       if(chldrn[i].parentRelativeStart == pos)
+                                               return [chldrn[i]];
+                                       if(chldrn[i].parentRelativeStart < pos)
+                                       {
+                                               retVal.length = 0;
+                                               continue;
+                                       }
+                                       if(chldrn[i].parentRelativeStart > pos)
+                                               break;
+                               }
+                               retVal.push(chldrn[i]);         
+                       }
+                       return retVal;
+               }
+               
+               /** @private */
                tlf_internal override function 
insertBlockElement(child:FlowElement, block:ContentElement):void
                {
-                       if (_textBlock == null)
+                       var relativeStart:int = 
child.getElementRelativeStart(this);
+                       var tb:TextBlock = 
getTextBlockAtPosition(relativeStart);
+                       if (getTextBlocks().length == 0 || !tb)
                        {
                                child.releaseContentElement();
                                createTextBlock();      // does the whole tree
@@ -274,7 +495,7 @@ package flashx.textLayout.elements
                        }
                        var gc:Vector.<ContentElement>; // scratch var
                        var group:GroupElement;                 // scratch
-                       if (numChildren == 1)
+                       if (getChildrenInTextBlock(relativeStart).length < 2)
                        {
                                if (block is GroupElement)
                                {
@@ -285,19 +506,23 @@ package flashx.textLayout.elements
                                        CONFIG::debug { 
Debugging.traceFTECall(null,gc,"push",block); }
                                        group = new GroupElement(gc);
                                        CONFIG::debug { 
Debugging.traceFTECall(group,null,"new GroupElement",gc); }
-                                       _textBlock.content = group;
+                                       tb.content = group;
                                        CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"content",group); }
                                }
                                else
                                {
-                                       _textBlock.content = block;
+                                       if(block.groupElement)
+                                       {
+                                               block.groupElement.elementCount;
+                                       }
+                                       tb.content = block;
                                        CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"content",block);  }
                                }
                        }
                        else
                        {
-                               group = createContentAsGroup();
-                               var idx:int = this.getChildIndex(child);
+                               group = createContentAsGroup(relativeStart);
+                               var idx:int = getChildIndexInBlock(child);
                                gc = new Vector.<ContentElement>();
                                CONFIG::debug { 
Debugging.traceFTECall(gc,null,"new Vector.<ContentElement>") }
                                gc.push(block);
@@ -307,6 +532,21 @@ package flashx.textLayout.elements
                        }
                }
                
+               private function getChildIndexInBlock(elem:FlowElement):int
+               {
+                       var relIdx:int = 0;
+                       for (var i:int = 0; i < numChildren; i++)
+                       {
+                               var child:FlowElement = getChildAt(i);
+                               if(child == elem)
+                                       return relIdx;
+                               relIdx++;
+                               if(child is TableElement)
+                                       relIdx = 0;
+                       }
+                       return -1;
+               }
+               
                /** @private */
                override protected function get abstract():Boolean
                { return false; }       
@@ -315,24 +555,63 @@ package flashx.textLayout.elements
                tlf_internal override function get defaultTypeName():String
                { return "p"; }
 
+               tlf_internal function removeEmptyTerminator():void
+               {
+                       if(numChildren == 1 && _terminatorSpan && 
_terminatorSpan.textLength == 1)
+                       {
+                               _terminatorSpan.removeParaTerminator();
+                               super.replaceChildren(0, 1);
+                               this._terminatorSpan = null;
+                       }
+               }
                /** @private */
                public override function 
replaceChildren(beginChildIndex:int,endChildIndex:int,...rest):void
                {
                        var applyParams:Array;
-                       
-                       // makes a measurable difference - rest.length zero and 
one are the common cases
-                       if (rest.length == 1)
-                               applyParams = [beginChildIndex, endChildIndex, 
rest[0]];
-                       else
-                       {
-                               applyParams = [beginChildIndex, endChildIndex];
-                               if (rest.length != 0)
-                                       applyParams = 
applyParams.concat.apply(applyParams, rest);
-                       }
 
-                       super.replaceChildren.apply(this, applyParams);
+                       do{
+                               if(_terminatorSpan)
+                               {
+                                       var termIdx:int = 
getChildIndex(_terminatorSpan);
+                                       if(termIdx !=0 && 
_terminatorSpan.textLength == 1)
+                                       {
+                                               super.replaceChildren(termIdx, 
termIdx+1);
+                                               _terminatorSpan = null;
+                                               if(beginChildIndex >= termIdx)
+                                               {
+                                                       beginChildIndex--;
+                                                       if(rest.length == 0) // 
delete of terminator was already done.
+                                                               break;
+                                               }
+                                               if(endChildIndex >= termIdx && 
beginChildIndex != endChildIndex)
+                                                       endChildIndex--;
+                                       }
+                               }
+                               
+                               // makes a measurable difference - rest.length 
zero and one are the common cases
+                               if (rest.length == 1)
+                                       applyParams = [beginChildIndex, 
endChildIndex, rest[0]];
+                               else
+                               {
+                                       applyParams = [beginChildIndex, 
endChildIndex];
+                                       if (rest.length != 0)
+                                               applyParams = 
applyParams.concat.apply(applyParams, rest);
+                               }
+                               
+                               super.replaceChildren.apply(this, applyParams);
+                               
+                       }while(false);
                        
                        ensureTerminatorAfterReplace();
+                       // ensure correct text blocks
+                       createTextBlock();
+               }
+               
+               public override function 
splitAtPosition(relativePosition:int):FlowElement
+               {
+                       // need to handle multiple TextBlocks
+                       // maybe not. It might be handled in replaceChildren().
+                       return super.splitAtPosition(relativePosition);
                }
                /** @private */
                tlf_internal function ensureTerminatorAfterReplace():void
@@ -340,27 +619,43 @@ package flashx.textLayout.elements
                        var newLastLeaf:FlowLeafElement = getLastLeaf();
                        if (_terminatorSpan != newLastLeaf)
                        {
-                               if (_terminatorSpan)
+                               if (newLastLeaf && _terminatorSpan)
                                {
                                        _terminatorSpan.removeParaTerminator();
+                                       if(_terminatorSpan.textLength == 0)
+                                       {
+                                               var termIdx:int = 
getChildIndex(_terminatorSpan);
+                                               super.replaceChildren(termIdx, 
termIdx+1);
+                                       }
                                        this._terminatorSpan = null;
                                }
                                
-                               if (newLastLeaf)
+                               if (newLastLeaf is SpanElement)
                                {
-                                       if (newLastLeaf is SpanElement)
-                                       {
-                                               (newLastLeaf as 
SpanElement).addParaTerminator();
-                                               this._terminatorSpan = 
newLastLeaf as SpanElement;
-                                       }
-                                       else
-                                       {
-                                               var s:SpanElement = new 
SpanElement();
-                                               
super.replaceChildren(numChildren,numChildren,s);
-                                               s.format = newLastLeaf.format;
-                                               s.addParaTerminator();
-                                               this._terminatorSpan = s;
-                                       }
+                                       (newLastLeaf as 
SpanElement).addParaTerminator();
+                                       this._terminatorSpan = newLastLeaf as 
SpanElement;
+                               }
+                               else
+                               {
+                                       var s:SpanElement = new SpanElement();
+                                       
super.replaceChildren(numChildren,numChildren,s);
+                                       s.format = newLastLeaf ? 
newLastLeaf.format : _terminatorSpan.format;
+                                       s.addParaTerminator();
+                                       this._terminatorSpan = s;
+                               }
+                       }
+                       //merge terminator span to previous if possible
+                       if(_terminatorSpan.textLength == 1)
+                       {
+                               var prev:FlowLeafElement = 
_terminatorSpan.getPreviousLeaf(this);
+                               if(prev && prev is SpanElement)
+                               {
+                                       _terminatorSpan.removeParaTerminator();
+                                       termIdx = 
getChildIndex(_terminatorSpan);
+                                       super.replaceChildren(termIdx, 
termIdx+1);
+                                       s = prev as SpanElement;
+                                       s.addParaTerminator();
+                                       this._terminatorSpan = s;
                                }
                        }
                }
@@ -387,7 +682,7 @@ package flashx.textLayout.elements
                                                child.bindableElement = true;
                                        
                                        // Note: calling super.replaceChildren 
because we don't want to transfer para terminator each time
-                                       super.replaceChildren(numChildren, 
numChildren, child as FlowElement); 
+                                       super.replaceChildren(numChildren, 
numChildren, child as FlowElement);
                                }
                                else if (child is String)
                                {
@@ -404,6 +699,9 @@ package flashx.textLayout.elements
                        
                        // Now ensure para terminator
                        ensureTerminatorAfterReplace();
+                       
+                       // recreate text blocks to handle possible TableElement 
changes
+                       createTextBlock();
                }
                
                /** @private
@@ -411,17 +709,26 @@ package flashx.textLayout.elements
                public override function getText(relativeStart:int=0, 
relativeEnd:int=-1, paragraphSeparator:String="\n"):String
                {
                        // Optimization for getting text of the entire paragraph
-                       if (relativeStart == 0 && (relativeEnd == -1 || 
relativeEnd >= textLength-1) && _textBlock)
+                       if (relativeStart == 0 && (relativeEnd == -1 || 
relativeEnd >= textLength-1) && getTextBlocks().length)
                        {
-                               if (_textBlock.content && 
_textBlock.content.rawText)
+                               var tb:TextBlock;
+                               var tbs:Vector.<TextBlock> = getTextBlocks();
+                               var text:String = "";
+                               for each(tb in tbs)
                                {
-                                       var text:String = 
_textBlock.content.rawText;
-                                       return text.substring(0, text.length - 
1);
+                                       text = text + getTextInBlock(tb);
                                }
-                               return "";              // content is null
+                               if(tb.content && tb.content.rawText)
+                                       return text.substring(0, text.length - 
1);
+                               return text;
                        }
                        return super.getText(relativeStart, relativeEnd, 
paragraphSeparator);
                }
+               private function getTextInBlock(tb:TextBlock):String{
+                       if(!tb.content || !tb.content.rawText)
+                               return "";
+                       return tb.content.rawText;
+               }
                
                /** Returns the paragraph that follows this one, or null if 
there are no more paragraphs. 
                 *
@@ -478,39 +785,46 @@ package flashx.textLayout.elements
                 
                public function 
findPreviousAtomBoundary(relativePosition:int):int
                {
+                       var tb:TextBlock = 
getTextBlockAtPosition(relativePosition);
+                       var tbStart:int = getTextBlockStart(tb);
+                       var textBlockPos:int = relativePosition - tbStart;
                        if 
(ContainerController.tlf_internal::usesDiscretionaryHyphens)
                        {
-                               var textBlock:TextBlock = getTextBlock();
-                               var tl:TextLine = 
textBlock.getTextLineAtCharIndex(relativePosition);
-                               var currentAtomIndex:int = 
tl.getAtomIndexAtCharIndex(relativePosition);
+                               var tl:TextLine = 
tb.getTextLineAtCharIndex(textBlockPos);
+                               var currentAtomIndex:int = 
tl.getAtomIndexAtCharIndex(textBlockPos);
                 //trace("relpos", relativePosition, "atomIndex", 
currentAtomIndex);
                 var isRTL:Boolean = tl.getAtomBidiLevel(currentAtomIndex) == 1;
                 if (isRTL)
                 {
-                   var foo:int = 
getTextBlock().findPreviousAtomBoundary(relativePosition);
+                   var foo:int = tb.findPreviousAtomBoundary(textBlockPos);
                    if (currentAtomIndex == 0)
                    {
                        // when cursor is left of all characters (end of line)
                        // atomIndex is 0, so compensate
                        if (tl.atomCount > 0)
                        {
-                           while (--relativePosition)
+                           while (--textBlockPos)
                            {
-                               if 
(tl.getAtomIndexAtCharIndex(relativePosition) != currentAtomIndex)
+                                                          --relativePosition;
+                               if (tl.getAtomIndexAtCharIndex(textBlockPos) != 
currentAtomIndex)
                                    break;
                            }
                        }
                    }
                    else
                    {
-                       while (--relativePosition)
+                       while (--relativePosition && --textBlockPos)
                        {
-                           if (tl.getAtomIndexAtCharIndex(relativePosition) != 
currentAtomIndex)
+                           if (tl.getAtomIndexAtCharIndex(textBlockPos) != 
currentAtomIndex)
                                break;
                        }
                    }
                    if (CharacterUtil.isLowSurrogate(getText(relativePosition, 
relativePosition + 1).charCodeAt(0)))
-                       relativePosition--;
+                                  {
+                                          relativePosition--;
+                                          textBlockPos--;
+                                  }
+                                  
                    //trace("previous", relativePosition, foo);
                 }
                 else
@@ -521,21 +835,26 @@ package flashx.textLayout.elements
                                        if (!tl)
                                                return -1;
                                        // need this when 0x2028 line separator 
in use
-                                       if (tl.textBlockBeginIndex + 
tl.rawTextLength == relativePosition)
-                                               return tl.textBlockBeginIndex + 
tl.rawTextLength - 1;
-                                       return tl.textBlockBeginIndex + 
tl.rawTextLength;
+                                       if (tl.textBlockBeginIndex + 
tl.rawTextLength == textBlockPos)
+                                               return tl.textBlockBeginIndex + 
tl.rawTextLength - 1 + tbStart;
+                                       return tl.textBlockBeginIndex + 
tl.rawTextLength + tbStart;
                                }
-                               while (--relativePosition)
+                               while (--relativePosition && --textBlockPos)
                                {
-                                       if 
(tl.getAtomIndexAtCharIndex(relativePosition) < currentAtomIndex)
+                                       if 
(tl.getAtomIndexAtCharIndex(textBlockPos) < currentAtomIndex)
                                                break;
                                }
                     if (CharacterUtil.isLowSurrogate(getText(relativePosition, 
relativePosition + 1).charCodeAt(0)))
-                        relativePosition--;
+                                       {
+                                               relativePosition--;
+                                               textBlockPos--;
+                                       }
                 }
                                return relativePosition;
                        }
-            var pos:int = 
getTextBlock().findPreviousAtomBoundary(relativePosition);
+            var pos:int = tb.findPreviousAtomBoundary(textBlockPos);
+                       if(pos >= 0)
+                               pos += tbStart;
             //trace("previous", relativePosition, pos);
                        return pos;
                }
@@ -560,34 +879,41 @@ package flashx.textLayout.elements
                 
                public function findNextAtomBoundary(relativePosition:int):int
                {
+                       var tb:TextBlock = 
getTextBlockAtPosition(relativePosition);
+                       var tbStart:int = getTextBlockStart(tb);
+                       var textBlockPos:int = relativePosition - tbStart;
                        if 
(ContainerController.tlf_internal::usesDiscretionaryHyphens)
                        {
-                               var textBlock:TextBlock = getTextBlock();
-                               var tl:TextLine = 
textBlock.getTextLineAtCharIndex(relativePosition);
-                               var currentAtomIndex:int = 
tl.getAtomIndexAtCharIndex(relativePosition);
+                               var tl:TextLine = 
tb.getTextLineAtCharIndex(textBlockPos);
+                               var currentAtomIndex:int = 
tl.getAtomIndexAtCharIndex(textBlockPos);
                 //trace("relpos", relativePosition, "atomIndex", 
currentAtomIndex);
                 var isRTL:Boolean = tl.getAtomBidiLevel(currentAtomIndex) == 1;
                 if (isRTL)
                 {
-                    var foo:int = 
getTextBlock().findNextAtomBoundary(relativePosition);
+                    var foo:int = tb.findNextAtomBoundary(textBlockPos);
                     if (currentAtomIndex == 0)
                     {
-                        while (++relativePosition)
+                        while (++textBlockPos)
                         {
-                            if (tl.getAtomIndexAtCharIndex(relativePosition) 
!= currentAtomIndex)
+                                                       ++relativePosition;
+                            if (tl.getAtomIndexAtCharIndex(textBlockPos) != 
currentAtomIndex)
                                 break;
                         }
                     }
                     else
                     {
-                        while (++relativePosition)
+                        while (++textBlockPos)
                         {
-                            if (tl.getAtomIndexAtCharIndex(relativePosition) 
!= currentAtomIndex)
+                                                       ++relativePosition;
+                            if (tl.getAtomIndexAtCharIndex(textBlockPos) != 
currentAtomIndex)
                                 break;
                         }
                     }
                     if 
(CharacterUtil.isHighSurrogate(getText(relativePosition, relativePosition + 
1).charCodeAt(0)))
-                        relativePosition++;
+                                       {
+                                               relativePosition++;
+                                               textBlockPos++;
+                                       }
                     //trace("next", relativePosition, foo);
                 }
                 else
@@ -597,19 +923,25 @@ package flashx.textLayout.elements
                                        tl = tl.nextLine;
                                        if (!tl)
                                                return -1;
-                                       return tl.textBlockBeginIndex;
+                                       return tl.textBlockBeginIndex + tbStart;
                                }
-                               while (++relativePosition)
+                               while (++textBlockPos)
                                {
-                                       if 
(tl.getAtomIndexAtCharIndex(relativePosition) > currentAtomIndex)
+                                               ++relativePosition;
+                                       if 
(tl.getAtomIndexAtCharIndex(textBlockPos) > currentAtomIndex)
                                                break;
                                }
                     if 
(CharacterUtil.isHighSurrogate(getText(relativePosition, relativePosition + 
1).charCodeAt(0)))
-                        relativePosition++;
+                                       {
+                                               relativePosition++;
+                                               textBlockPos++;
+                                       }
                 }
                                return relativePosition;
                        }
-                       var pos:int = 
getTextBlock().findNextAtomBoundary(relativePosition);
+                       var pos:int = tb.findNextAtomBoundary(textBlockPos);
+                       if(pos >= 0)
+                               pos += tbStart;
             //trace("next", relativePosition, pos);
             return pos;
                }
@@ -617,7 +949,27 @@ package flashx.textLayout.elements
                /** @private */
                public override function 
getCharAtPosition(relativePosition:int):String
                {
-                       return 
getTextBlock().content.rawText.charAt(relativePosition);
+                       var foundTB:TextBlock = 
getTextBlockAtPosition(relativePosition);
+                       if(!foundTB)
+                               return "\u0016";
+                       var tables:Vector.<TableElement> = getTables();
+                       var pos:int = relativePosition;
+                       for each(var table:TableElement in tables)
+                       {
+                               if(table.getElementRelativeStart(this) < pos)
+                                       relativePosition--;
+                       }
+                       var tbs:Vector.<TextBlock> = getTextBlocks();
+                       for each(var tb:TextBlock in tbs)
+                       {
+                               if(foundTB == tb)
+                                       break;
+                               if(tb)
+                                       relativePosition -= 
tb.content.rawText.length;
+                               else
+                                       relativePosition -= 1;this.getText()
+                       }
+                       return foundTB.content.rawText.charAt(relativePosition);
                } 
 
                /** 
@@ -650,7 +1002,13 @@ package flashx.textLayout.elements
                                }
                                return relativePosition;
                        }
-                       return 
getTextBlock().findPreviousWordBoundary(relativePosition);
+                       var block:TextBlock = 
getTextBlockAtPosition(relativePosition);
+                       if(block == null)
+                               block = 
getTextBlockAtPosition(--relativePosition);
+                       var pos:int = getTextBlockStart(block);
+                       if(pos < 0)
+                               pos = 0;
+                       return relativePosition == pos ? pos : pos + 
block.findPreviousWordBoundary(relativePosition - pos);
                }
 
                /** 
@@ -683,7 +1041,13 @@ package flashx.textLayout.elements
                                }
                                return relativePosition;
                        }
-                       return 
getTextBlock().findNextWordBoundary(relativePosition);
+                       var block:TextBlock = 
getTextBlockAtPosition(relativePosition);
+                       if(block == null)
+                               block = 
getTextBlockAtPosition(--relativePosition);
+                       var pos:int = getTextBlockStart(block);
+                       if(pos < 0)
+                               pos = 0;
+                       return pos + 
block.findNextWordBoundary(relativePosition - pos);
                }
                
                static private var _defaultTabStops:Vector.<TabStop>;
@@ -697,8 +1061,10 @@ package flashx.textLayout.elements
                                _defaultTabStops[i] = new 
TabStop(TextAlign.START, defaultTabWidth * i);
                }
                
-               private function updateTextBlock():void
+               private function updateTextBlock(textBlock:TextBlock=null):void
                {
+                       if(!textBlock)
+                               textBlock = getTextBlock();
                        // find the ancestor with a container and use its 
format for various settings
                        var containerElement:ContainerFormattedElement = 
getAncestorWithContainer();
                        if (!containerElement)
@@ -746,10 +1112,10 @@ package flashx.textLayout.elements
                                }
 
                                CONFIG::debug { 
Debugging.traceFTECall(spaceJustifier,null,"new 
SpaceJustifier",_computedFormat.locale,lineJust,spaceJustifier.letterSpacing); }
-                               _textBlock.textJustifier = spaceJustifier;
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"textJustifier",spaceJustifier); }
-                               _textBlock.baselineZero = 
getLeadingBasis(this.getEffectiveLeadingModel());
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"baselineZero",_textBlock.baselineZero);  }
+                               textBlock.textJustifier = spaceJustifier;
+                               CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"textJustifier",spaceJustifier); }
+                               textBlock.baselineZero = 
getLeadingBasis(this.getEffectiveLeadingModel());
+                               CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"baselineZero",textBlock.baselineZero);  }
                        }
                        else
                        {
@@ -758,21 +1124,21 @@ package flashx.textLayout.elements
                                        
eastAsianJustifier.composeTrailingIdeographicSpaces = true;
                                }
                                CONFIG::debug { 
Debugging.traceFTECall(eastAsianJustifier,null,"new 
EastAsianJustifier",_computedFormat.locale,lineJust,makeJustRuleStyle); }
-                               _textBlock.textJustifier = eastAsianJustifier 
as EastAsianJustifier;
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"textJustifier",eastAsianJustifier);  }
-                               _textBlock.baselineZero = 
getLeadingBasis(this.getEffectiveLeadingModel());
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"baselineZero",_textBlock.baselineZero);  }
+                               textBlock.textJustifier = eastAsianJustifier as 
EastAsianJustifier;
+                               CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"textJustifier",eastAsianJustifier);  }
+                               textBlock.baselineZero = 
getLeadingBasis(this.getEffectiveLeadingModel());
+                               CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"baselineZero",textBlock.baselineZero);  }
                        }
                        
-                       _textBlock.bidiLevel = _computedFormat.direction == 
Direction.LTR ? 0 : 1;
-                       CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"bidiLevel",_textBlock.bidiLevel);  }
+                       textBlock.bidiLevel = _computedFormat.direction == 
Direction.LTR ? 0 : 1;
+                       CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"bidiLevel",textBlock.bidiLevel);  }
 
-                       _textBlock.lineRotation = 
containerElementFormat.blockProgression == BlockProgression.RL ? 
TextRotation.ROTATE_90 : TextRotation.ROTATE_0;
-                       CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"lineRotation",_textBlock.lineRotation);  }
+                       textBlock.lineRotation = 
containerElementFormat.blockProgression == BlockProgression.RL ? 
TextRotation.ROTATE_90 : TextRotation.ROTATE_0;
+                       CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"lineRotation",textBlock.lineRotation);  }
                        
                        if (_computedFormat.tabStops && 
_computedFormat.tabStops.length != 0)
                        {
-                               //create a vector of TabStops and assign it to 
tabStops in _textBlock
+                               //create a vector of TabStops and assign it to 
tabStops in textBlock
                                var tabStops:Vector.<TabStop> = new 
Vector.<TabStop>();
                                CONFIG::debug { 
Debugging.traceFTECall(tabStops,null,"new Vector.<TabStop>()"); }
                                for each(var tsa:TabStopFormat in 
_computedFormat.tabStops)
@@ -786,8 +1152,8 @@ package flashx.textLayout.elements
                                        tabStops.push(tabStop);
                                        CONFIG::debug { 
Debugging.traceFTECall(null,tabStops,"push",tabStop); }
                                }
-                               _textBlock.tabStops = tabStops;
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"tabStops",tabStops);  }
+                               textBlock.tabStops = tabStops;
+                               CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"tabStops",tabStops);  }
                        } 
                        else if (GlobalSettings.enableDefaultTabStops && 
!Configuration.playerEnablesArgoFeatures)
                        {
@@ -795,13 +1161,13 @@ package flashx.textLayout.elements
                                //      is true, TLF will set up default 
tabStops in the case where there are no tabs defined. 
                                if (_defaultTabStops == null)
                                        initializeDefaultTabStops();
-                               _textBlock.tabStops = _defaultTabStops;
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"tabStops",_defaultTabStops);  }
+                               textBlock.tabStops = _defaultTabStops;
+                               CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"tabStops",_defaultTabStops);  }
                        }
                        else
                        {
-                               _textBlock.tabStops = null;
-                               CONFIG::debug { 
Debugging.traceFTEAssign(_textBlock,"tabStops",null);  }
+                               textBlock.tabStops = null;
+                               CONFIG::debug { 
Debugging.traceFTEAssign(textBlock,"tabStops",null);  }
                        }                
                }
                
@@ -811,8 +1177,10 @@ package flashx.textLayout.elements
                        if (!_computedFormat)
                        {
                                super.computedFormat;
-                               if (_textBlock)
-                                       updateTextBlock();
+                               var tbs:Vector.<TextBlock> = getTextBlocks();
+                               for each(var tb:TextBlock in tbs)
+                                       updateTextBlock(tb);
+                                       
                        }
                        return _computedFormat;
                }
@@ -820,7 +1188,7 @@ package flashx.textLayout.elements
                /** @private */
                tlf_internal override function 
canOwnFlowElement(elem:FlowElement):Boolean
                {
-                       return elem is FlowLeafElement || elem is 
SubParagraphGroupElementBase;
+                       return elem is FlowLeafElement || elem is 
SubParagraphGroupElementBase || elem is TableElement;
                }
                
                /** @private */
@@ -884,32 +1252,6 @@ package flashx.textLayout.elements
                        }
                }
                
-               // mjzhang : new API for table feature, to discuss
-               public function isInTable():Boolean
-               {
-                       var parent:FlowElement = this.parent;
-                       while ( parent )
-                       {
-                               if ( (parent is TableDataCellElement) )
-                                       return true;
-                               parent = parent.parent;
-                       }
-                               
-                       return false;
-               }
-               
-               public function getTableDataCellElement():TableDataCellElement
-               {
-                       var parent:FlowElement = this.parent;
-                       while ( parent )
-                       {
-                               if ( (parent is TableDataCellElement) )
-                                       return parent as TableDataCellElement;
-                               parent = parent.parent;
-                       }
-                       
-                       return null;
-               }
                /** @private */
                tlf_internal function getEffectiveLeadingModel():String
                {
@@ -938,19 +1280,20 @@ package flashx.textLayout.elements
                /** @private */
                CONFIG::debug public override function 
debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
                {
-                       var rslt:int = super.debugCheckFlowElement(depth," 
fte:"+getDebugIdentity(_textBlock)+" "+extraData);
+                       var tb:TextBlock = getTextBlock();
+                       var rslt:int = super.debugCheckFlowElement(depth," 
fte:"+getDebugIdentity(tb)+" "+extraData);
                        
                        // now check the character count and then the last 
character 
                        
-                       if (_textBlock)
+                       if (tb)
                        {
-                               var contentLength:int = _textBlock.content && 
_textBlock.content.rawText ? _textBlock.content.rawText.length : 0;
+                               var contentLength:int = tb.content && 
tb.content.rawText ? tb.content.rawText.length : 0;
                                rslt += assert(contentLength == textLength,"Bad 
paragraph length mode:"+textLength.toString()+" _textBlock:" + 
contentLength.toString());
 
-                               var groupElement:GroupElement = 
_textBlock.content as GroupElement;
+                               var groupElement:GroupElement = tb.content as 
GroupElement;
                                if (groupElement)
                                        assert(groupElement.elementCount == 
numChildren,"Mismatched group and elementCount"); 
-                               else if (_textBlock.content)
+                               else if (tb.content)
                                        assert(1 == numChildren,"Mismatched 
group and elementCount"); 
                                else 
                                        assert(0 == numChildren,"Mismatched 
group and elementCount"); 
@@ -1013,5 +1356,11 @@ package flashx.textLayout.elements
                {
                        return _interactiveChildrenCount != 0 ;
                }
+
+               tlf_internal function get terminatorSpan():SpanElement
+               {
+                       return _terminatorSpan;
+               }
+
        }
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/SpanElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/SpanElement.as 
b/textLayout/src/flashx/textLayout/elements/SpanElement.as
index c16adff..9e37058 100644
--- a/textLayout/src/flashx/textLayout/elements/SpanElement.as
+++ b/textLayout/src/flashx/textLayout/elements/SpanElement.as
@@ -395,6 +395,8 @@ package flashx.textLayout.elements
                                        
assert(_blockElement.rawText.charAt(_blockElement.rawText.length-1) != 
SpanElement.kParagraphTerminator,"adding para terminator twice");
                        }
 
+                       if(_text && _text.substr(-1) == 
SpanElement.kParagraphTerminator)// terminator exists. Bail out.
+                               return;
                        
replaceTextInternal(textLength,textLength,SpanElement.kParagraphTerminator);
                        
                        CONFIG::debug 
@@ -414,6 +416,9 @@ package flashx.textLayout.elements
                                assert(_text && _text.length && 
_text.charAt(_text.length-1) == SpanElement.kParagraphTerminator,
                                        "attempting to remove para terminator 
when it doesn't exist");
                        }
+                       if(!_text || _text.substr(-1) != 
SpanElement.kParagraphTerminator)// no terminator exists. Bail out.
+                               return;
+
                        replaceTextInternal(textLength-1,textLength,"");
                        modelChanged(ModelChange.TEXT_DELETED,this,textLength > 
0 ? textLength-1 : 0,1);
                }
@@ -464,7 +469,7 @@ package flashx.textLayout.elements
                                {
                                        // optimized version leverages player 
APIs
                                        // TODO: Jeff to add split on 
TextElement so we don't have to go find a group every time
-                                       var group:GroupElement = 
parent.createContentAsGroup();
+                                       var group:GroupElement = 
parent.createContentAsGroup(getElementRelativeStart(parent));
                                        
                                        var elementIndex:int = 
group.getElementIndex(_blockElement);
                                        

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
----------------------------------------------------------------------
diff --git 
a/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as 
b/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
index c65e138..2affda3 100644
--- a/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
+++ b/textLayout/src/flashx/textLayout/elements/SubParagraphGroupElementBase.as
@@ -190,7 +190,7 @@ package flashx.textLayout.elements
                }
                
                /** @private */
-               tlf_internal override function 
createContentAsGroup():GroupElement
+               tlf_internal override function 
createContentAsGroup(pos:int=0):GroupElement
                { return groupElement; }
 
                /** @private */

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TableColElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableColElement.as 
b/textLayout/src/flashx/textLayout/elements/TableColElement.as
index 85a1d9e..342b9ce 100644
--- a/textLayout/src/flashx/textLayout/elements/TableColElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableColElement.as
@@ -18,6 +18,7 @@
 
////////////////////////////////////////////////////////////////////////////////
 package flashx.textLayout.elements
 {
+       import flashx.textLayout.formats.ITextLayoutFormat;
        import flashx.textLayout.tlf_internal;
        
        use namespace tlf_internal;
@@ -36,6 +37,15 @@ package flashx.textLayout.elements
        {               
                //public var height:Number;
                public var x:Number;
+               public var colIndex:int;
+               
+               public function TableColElement(format:ITextLayoutFormat=null)
+               {
+                       super();
+                       if(format)
+                               this.format = format;
+               }
+
                
                /** @private */
                override protected function get abstract():Boolean
@@ -56,6 +66,29 @@ package flashx.textLayout.elements
                {
                        
super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
                }
-
+               
+               /**
+                * Get a Vector of cells or null if the column contains no cells
+                **/
+               public function get cells():Vector.<TableCellElement> {
+                       
+                       if (!table) {
+                               return null;
+                       }
+                       
+                       return table.getCellsForColumn(this);
+               }
+               
+               /**
+                * Returns the number of cells in this column. 
+                **/
+               public function get numCells():int {
+                       
+                       if (!table) {
+                               return 0;
+                       }
+                       
+                       return table.getCellsForColumn(this).length;
+               }
        }
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TableElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableElement.as 
b/textLayout/src/flashx/textLayout/elements/TableElement.as
index 92cefcc..ed82a28 100644
--- a/textLayout/src/flashx/textLayout/elements/TableElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableElement.as
@@ -18,19 +18,17 @@
 
////////////////////////////////////////////////////////////////////////////////
 package flashx.textLayout.elements
 {
-       import flash.display.Graphics;
-       import flash.events.Event;
-       import flash.events.EventDispatcher;
-       import flash.events.IEventDispatcher;
-       import flash.events.MouseEvent;
-       import flash.geom.Point;
-       import flash.text.engine.TextBlock;
-       import flash.text.engine.TextLine;
+       import flash.display.Sprite;
+       import flash.text.engine.ContentElement;
+       import flash.text.engine.GraphicElement;
+       import flash.utils.Dictionary;
        
-       import flashx.textLayout.events.FlowElementEventDispatcher;
-       import flashx.textLayout.events.FlowElementMouseEventManager;
+       import flashx.textLayout.compose.TextFlowTableBlock;
+       import flashx.textLayout.edit.SelectionFormat;
        import flashx.textLayout.events.ModelChange;
-       import flashx.textLayout.formats.*;
+       import flashx.textLayout.formats.FormatValue;
+       import flashx.textLayout.formats.ITextLayoutFormat;
+       import flashx.textLayout.formats.TextLayoutFormat;
        import flashx.textLayout.tlf_internal;
        
        use namespace tlf_internal;
@@ -41,7 +39,6 @@ package flashx.textLayout.elements
         * A TableElement's children must be of type TableRowElement, 
TableColElement, TableColGroupElement, TableBodyElement.
         * 
         * 
-        * 
         * @playerversion Flash 10
         * @playerversion AIR 1.5
         * @langversion 3.0
@@ -49,41 +46,38 @@ package flashx.textLayout.elements
         */
        public class TableElement extends TableFormattedElement 
        {
-               private var _row:int;
-               private var _column:int;
                
-               private var _height:Array = []; // parcel-indexed
-               public var computedWidth:Number;
+               private var _computedWidth:Number;
                
                public var x:Number;
                public var y:Number;
                
-               //These attributes is from the original loop prototype. Maybe 
changed later
-               public var totalRowDepth:Number = undefined;
-               public var originParcelIndex:Number;
-               public var numAcrossParcels:int;
-        public var curRowIdx:int = 0; // this value should be only used while 
composing
-        public var outOfLastParcel:Boolean = false; 
-                       
-               private var arColumn:Array = [];
+               private var columns:Vector.<TableColElement> = new 
Vector.<TableColElement>();
+               private var rows:Vector.<TableRowElement> = new 
Vector.<TableRowElement>();
+               private var damagedColumns:Vector.<TableColElement> = new 
Vector.<TableColElement>();
+               private var damageRows:Vector.<TableRowElement> = new 
Vector.<TableRowElement>();
+               private var _hasCellDamage:Boolean = true;
+               
+               private var _headerRowCount:uint = 0;
+               private var _footerRowCount:uint = 0;
+               private var _tableRowsComputed:Boolean;
+               
+               private var _headerRows:Vector.< Vector.<TableCellElement> >;
+               private var _footerRows:Vector.< Vector.<TableCellElement> >;
+               private var _bodyRows:Vector.< Vector.<TableCellElement> >;
+               private var _composedRowIndex:uint = 0;
+               
+               private var _tableBlocks:Vector.<TextFlowTableBlock>;
+               private var _tableBlockIndex:uint = 0;
+               private var _tableBlockDict:Dictionary;
+               
+               private var _leaf:TableLeafElement;
                
                public function TableElement()
                {
                        super();
                }
                
-               public function initTableElement(row:Number, column:Number):void
-               {
-                       _row = row;
-                       _column = column;
-                       
-                       for ( var i:int = 0; i < column; i ++ )
-                       {
-                               var col:TableColElement = new 
TableColElement();        
-                               arColumn[i] = col;
-                       }
-               }
-               
                /** @private */
                override protected function get abstract():Boolean
                { return false; }
@@ -95,35 +89,714 @@ package flashx.textLayout.elements
                /** @private */
                tlf_internal override function 
canOwnFlowElement(elem:FlowElement):Boolean
                {
-                       return  (elem is TableBodyElement) || (elem is 
TableRowElement) || (elem is TableColElement) || (elem is TableColGroupElement);
+                       return (elem is TableCellElement) || (elem is 
TableRowElement) || (elem is TableColElement);// || (elem is TableBodyElement) 
|| (elem is TableColGroupElement);
                }
                
                /** @private if its in a numbered list expand the damage to all 
list items - causes the numbers to be regenerated */
                tlf_internal override function modelChanged(changeType:String, 
elem:FlowElement, changeStart:int, changeLen:int, needNormalize:Boolean = true, 
bumpGeneration:Boolean = true):void
                {
+                       if (changeType==ModelChange.ELEMENT_ADDED) {
+                               
+                       }
+                       else if (changeType==ModelChange.ELEMENT_REMOVAL) {
+                               if (headerRowCount > 0 || footerRowCount > 0) {
+                                       
+                               }
+                       }
+                       
                        
super.modelChanged(changeType,elem,changeStart,changeLen,needNormalize,bumpGeneration);
                }
                
-               public function get row():int
+               override public function set 
cellSpacing(cellSpacingValue:*):void
+               {
+                       
+                       markCellsDamaged();
+                       hasCellDamage = true;
+                       normalizeCells();
+                       
+                       super.cellSpacing = cellSpacingValue;
+               }
+               
+               public function get numRows():int
+               {
+                       return rows.length;
+               }
+               
+               public function get numColumns():int
+               {
+                       return columns.length;
+               }
+               
+               /**
+                * Total number of cells
+                **/
+               public function get numCells():int
                {
-                       return _row;
+                       return getCells().length;
                }
                
-               public function get column():int
+               /**
+                * Total number of rows in the table. If set to a value lower 
than
+                * the current number of rows the rows at the end of the table 
are removed. 
+                * If the set to a value greater than the current number of 
rows additional
+                * rows are added to the table. 
+                **/
+               public function set numRows(value:int):void
                {
-                       return _column;
+                       while(value < numRows){
+                               rows.pop();
+                       }
+                       var num:int = numRows;
+                       for(var i:int = num;i<value;i++) {
+                               var row:TableRowElement = createRowElement(i, 
defaultRowFormat);
+                               rows.push(row);
+                       }
                }
 
+               /**
+                * Total number of columns in the table. If set to a value 
lower than
+                * the current number of columns the columns at the end of the 
table are removed. 
+                * If the set to a value greater than the current number of 
columns additional
+                * columns are added to the table. 
+                **/
+               public function set numColumns(value:int):void
+               {
+                       while(value < numColumns){
+                               columns.pop();
+                       }
+                       var num:int = numColumns;
+                       for(var i:int = num;i<value;i++) {
+                               var column:TableColElement = 
createColumnElement(i, defaultColumnFormat);
+                               columns.push(column);
+                       }
+               }
+               private var _defaultRowFormat:ITextLayoutFormat;
+
+               /**
+                * Gets the row format for new rows. 
+                **/
+               public function get defaultRowFormat():ITextLayoutFormat
+               {
+                       if(!_defaultRowFormat)
+                               _defaultRowFormat = new 
TextLayoutFormat(computedFormat);
+                       return _defaultRowFormat;
+               }
+
+               public function set 
defaultRowFormat(value:ITextLayoutFormat):void
+               {
+                       _defaultRowFormat = value;
+               }
+               
+               private var _defaultColumnFormat:ITextLayoutFormat;
+
+               /**
+                * Gets the column format for new columns. 
+                **/
+               public function get defaultColumnFormat():ITextLayoutFormat
+               {
+                       if(!_defaultColumnFormat)
+                               _defaultColumnFormat = new 
TextLayoutFormat(computedFormat);
+                       return _defaultColumnFormat;
+               }
+
+               public function set 
defaultColumnFormat(value:ITextLayoutFormat):void
+               {
+                       _defaultColumnFormat = value;
+               }
+               
+               /**
+                * Adds a table cell element to the table. 
+                * @inheritDoc
+                **/
+               override public function addChild(child:FlowElement):FlowElement
+               {
+                       
+                       if (child is TableFormattedElement) {
+                               TableFormattedElement(child).table = this;
+                       }
+                       
+                       super.addChild(child);
+                       
+                       return child;
+               }
+               
+               /**
+                * Removes a table cell element from the table. 
+                * @inheritDoc
+                **/
+               override public function 
removeChild(child:FlowElement):FlowElement
+               {
+                       super.removeChild(child);
+                       
+                       if (child is TableFormattedElement) {
+                               TableFormattedElement(child).table = null;
+                       }
+                       
+                       return child;
+               }
+               
+               /**
+                * Add a row at the end of the table. You would use this if you 
want to add a row
+                * without changing the table cells. 
+                * @see addRowAt
+                * @see insertRow
+                * @see insertRowAt
+                **/
+               public function addRow(format:ITextLayoutFormat=null):void{
+                       addRowAt(rows.length,format);
+               }
+               
+               /**
+                * Add a row at the index specified. 
+                * @see addRow
+                * @see insertRow
+                * @see insertRowAt
+                **/
+               public function addRowAt(idx:int, 
format:ITextLayoutFormat=null):void{
+                       if(idx < 0 || idx > rows.length)
+                               throw 
RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+                       
+                       var row:TableRowElement = createRowElement(idx, format);
+                       rows.splice(idx, 0, row);
+                       row.composedHeight = row.computedFormat.minCellHeight;
+                       row.isMaxHeight = row.computedFormat.minCellHeight == 
row.computedFormat.maxCellHeight;
+                       row.setParentAndRelativeStartOnly(this, 1);
+               }
+
+               /**
+                * Adds a column. You would use this if you want to add a 
column without changing the table cells. 
+                * The cells would reflow, so a cell in row 2 might move up to 
row 1.
+                * @see addColumnAt
+                * @see insertColumn
+                * @see insertColumnAt
+                **/
+               public function addColumn(format:ITextLayoutFormat=null):void{
+                       addColumnAt(columns.length,format);
+               }
+               
+               /**
+                * Adds a column at the index specified. 
+                * @see addColumn
+                * @see insertColumn
+                * @see insertColumnAt
+                **/
+               public function addColumnAt(idx:int, 
format:ITextLayoutFormat=null):void{
+                       if(idx < 0 || idx > columns.length)
+                               throw 
RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+                       if(!format) {
+                               format = defaultColumnFormat;
+                       }
+                       var column:TableColElement = createColumnElement(idx, 
format);
+                       
+                       columns.splice(idx, 0, column);
+               }
+
+               /**
+                * Returns the column at the index specified or null if the 
index is out of range. 
+                **/
                public function getColumnAt(columnIndex:int):TableColElement
                {
-                       if ( columnIndex < 0 || columnIndex >= _column )
+                       if ( columnIndex < 0 || columnIndex >= numColumns )
+                               return null;
+                       return columns[columnIndex];
+               }
+               
+               /**
+                * Returns the row at the index specified or null if the index 
is out of range. 
+                **/
+               public function getRowAt(rowIndex:int):TableRowElement
+               {
+                       if ( rowIndex < 0 || rowIndex >= numRows )
+                               return null;
+                       return rows[rowIndex];
+               }
+               
+               /**
+                * Return the index of the row provided or -1 if the row is not 
found. 
+                **/
+               public function getRowIndex(row:TableRowElement):int
+               {
+                       for(var i:int=0;i<rows.length;i++)
+                       {
+                               if(rows[i] == row)
+                                       return i;
+                       }
+                       return -1;
+               }
+               
+               /**
+                * Returns a vector of the cells for the row specified. 
+                **/
+               public function 
getCellsForRow(row:TableRowElement):Vector.<TableCellElement>{
+                       
+                       return getCellsForRowAt(row.rowIndex);
+               }
+               
+               /**
+                * Returns a vector of the cells for the row specified. 
+                **/
+               public function getCellsForRowArray(row:TableRowElement):Array {
+                       
+                       return getCellsForRowAtArray(row.rowIndex);
+               }
+               
+               /**
+                * Returns a vector of the cells for the row at the specified 
index. 
+                **/
+               public function 
getCellsForRowAt(index:int):Vector.<TableCellElement>{
+                       var cells:Vector.<TableCellElement> = new 
Vector.<TableCellElement>();
+                       
+                       if (index < 0) {
+                               return cells;
+                       }
+                       
+                       for each(var cell:TableCellElement in mxmlChildren){
+                               if (cell.rowIndex == index) {
+                                       cells.push(cell);
+                               }
+                       }
+                       
+                       return cells;
+               }
+               
+               /**
+                * Returns an array of the cells for the row specified. 
+                **/
+               public function getCellsForRowAtArray(index:int):Array {
+                       var cells:Array = [];
+                       
+                       if (index < 0) {
+                               return cells;
+                       }
+                       
+                       for each(var cell:TableCellElement in mxmlChildren){
+                               if (cell.rowIndex == index) {
+                                       cells.push(cell);
+                               }
+                       }
+                       
+                       return cells;
+               }
+               
+               /**
+                * Returns a Vector of the TableCellElements for the column 
specified. 
+                **/
+               public function 
getCellsForColumn(column:TableColElement):Vector.<TableCellElement> {
+                       if(columns.indexOf(column) < 0)
+                               return null;
+                       
+                       return getCellsForColumnAt(column.colIndex);
+               }
+               
+               /**
+                * Returns a Vector of the TableCellElements for the column at 
the specified index. 
+                **/
+               public function 
getCellsForColumnAt(index:int):Vector.<TableCellElement> {
+                       var cells:Vector.<TableCellElement> = new 
Vector.<TableCellElement>();
+                       
+                       if (index < 0) {
+                               return cells;
+                       }
+                       
+                       for each(var cell:TableCellElement in mxmlChildren){
+                               if (cell.colIndex == index) {
+                                       cells.push(cell);
+                               }
+                       }
+                       
+                       return cells;
+               }
+               
+               /**
+                * Inserts a column at the end of the table. If a column is not 
provided one is created. 
+                * 
+                * @see addColumn
+                * @see addColumnAt
+                * @see insertColumnAt
+                **/
+               public function 
insertColumn(column:TableColElement=null,cells:Array = null):Boolean{
+                       return insertColumnAt(numColumns,column,cells);
+               }
+               
+               /**
+                * Inserts a column at the column specified. If the column is 
not provided it
+                * creates a new column containing the cells supplied or 
creates the cells
+                * based on the number of rows in the table. 
+                * @see addColumn
+                * @see addColumnAt
+                * @see insertColumn
+                **/
+               public function 
insertColumnAt(idx:int,column:TableColElement=null,cells:Array = null):Boolean{
+                       
+                       if (idx < 0 || idx > columns.length) {
+                               throw 
RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+                       }
+                       
+                       if (!column) {
+                               column = createColumnElement(idx, 
defaultColumnFormat);
+                       }
+                       
+                       columns.splice(idx,0,column);
+                       
+                       var blockedCoords:Vector.<CellCoords> = 
getBlockedCoords(-1,idx);
+                       var cellIdx:int = getCellIndex(0,idx);
+                       if(cellIdx < 0)
+                               cellIdx = numChildren;
+                       var rowIdx:int = 0;
+                       
+                       if (cells==null) cells = []; 
+                       
+                       while(cells.length < numRows){
+                               cells.push(new TableCellElement());
+                       }
+                       
+                       for each(var cell:TableCellElement in cells){
+                               while(blockedCoords.length && 
blockedCoords[0].row == rowIdx){
+                                       rowIdx++;
+                                       blockedCoords.shift();
+                               }
+                               cellIdx = getCellIndex(rowIdx,idx);
+                               if(cellIdx < 0)
+                                       cellIdx = numChildren;
+                               
+                               if(rowIdx < numRows){
+                                       addChildAt(cellIdx,cell);
+                               }
+                       }
+
+
+                       return true;
+               }
+               
+               /**
+                * Inserts a row at the end of the table. If a row is not 
provided one is created. 
+                * @see insertRowAt
+                **/
+               public function insertRow(row:TableRowElement=null,cells:Array 
= null):Boolean{
+                       return insertRowAt(numRows,row,cells);
+               }
+               
+               /**
+                * Inserts a row at the index specified. If the row is not 
provided it
+                * creates a new row containing the cells supplied or creates 
the cells
+                * based on the number of columns in the table. 
+                **/
+               public function 
insertRowAt(idx:int,row:TableRowElement=null,cells:Array = null):Boolean{
+                       if (idx < 0 || idx > rows.length) {
+                               throw 
RangeError(GlobalSettings.resourceStringFunction("badPropertyValue"));
+                       }
+                       
+                       if (!row) {
+                               row = createRowElement(idx, defaultRowFormat);
+                       }
+                       
+                       rows.splice(idx,0,row);
+                       row.composedHeight = row.computedFormat.minCellHeight;
+                       row.isMaxHeight = row.computedFormat.minCellHeight == 
row.computedFormat.maxCellHeight;
+
+                       var blockedCoords:Vector.<CellCoords> = 
getBlockedCoords(idx);
+                       var cellIdx:int = getCellIndex(idx,0);
+                       if(cellIdx < 0)
+                               cellIdx = numChildren;
+
+                       var colIdx:int = 0;
+                       
+                       if (cells==null) cells = [];
+                       
+                       // create more cells 
+                       while(cells.length < numColumns){
+                               cells.push(new TableCellElement());
+                       }
+                       
+                       for each(var cell:TableCellElement in cells){
+                               while(blockedCoords.length && 
blockedCoords[0].column == colIdx){
+                                       colIdx++;
+                                       blockedCoords.shift();
+                               }
+                               if(colIdx < numColumns){
+                                       addChildAt(cellIdx++,cell);
+                               }
+                       }
+                       return true;
+               }
+               
+               /**
+                * Removes the row
+                **/
+               public function removeRow(row:TableRowElement):TableRowElement {
+                       var i:int = rows.indexOf(row);
+                       if(i < 0)
+                               return null;
+                       return removeRowAt(i);
+               }
+               
+               /**
+                * Removes the row and the cells it contains.
+                **/
+               public function removeRowWithContent(row:TableRowElement):Array
+               {
+                       var i:int = rows.indexOf(row);
+                       if(i < 0)
                                return null;
-                       return arColumn[columnIndex];
+                       return removeRowWithContentAt(i);
+               }
+               
+               /**
+                * Removes the row at the index specified.
+                * @see removeRowWithContentAt
+                **/
+               public function removeRowAt(idx:int):TableRowElement {
+                       if(idx < 0 || idx > rows.length - 1)
+                               return null;
+                       
+                       var row:TableRowElement = 
TableRowElement(rows.splice(idx,1)[0]);
+                       normalizeCells();
+                       hasCellDamage = true;
+                       return row;
+                       
+               }
+               
+               /**
+                * Removes the row at the index specified and the cells it 
contains.
+                **/
+               public function removeRowWithContentAt(idx:int):Array
+               {
+
+                       var removedCells:Array = [];
+                       
+                       if(mxmlChildren){
+                               for (var i:int = 
mxmlChildren.length-1;i>=0;i--){
+                                       var child:* = mxmlChildren[i];
+                                       if(!(child is TableCellElement))
+                                               continue;
+                                       var cell:TableCellElement = child as 
TableCellElement;
+                                       if(cell.rowIndex == idx){
+                                               
removedCells.unshift(removeChild(cell));
+                                       }
+                               }
+                       }
+                       
+                       removeRowAt(idx);
+                       return removedCells;
+               }
+               
+               /**
+                * Removes all the rows and the cells.
+                **/
+               public function removeAllRowsWithContent():void
+               {
+                       var rowCount:int;
+                       var cellCount:int;
+                       
+                       if (numRows>-1) {
+                               rowCount = numRows-1;
+                               
+                               for (;rowCount>-1;) {
+                                       removeRowWithContentAt(rowCount--);
+                               }
+                               
+                       }
+               }
+               
+               /**
+                * Removes all the rows. Does not remove the cells.
+                * @see removeAllRowsWithContent
+                **/
+               public function removeAllRows():void
+               {
+                       var rowCount:int;
+                       var cellCount:int;
+                       
+                       if (numRows>-1) {
+                               rowCount = numRows;
+                               
+                               for (var i:int; i < rowCount; i++) {
+                                       removeRowAt(i);
+                               }
+                               
+                       }
+               }
+               
+               /**
+                * Removes the column
+                **/
+               public function 
removeColumn(column:TableColElement):TableColElement {
+                       var i:int = columns.indexOf(column);
+                       if(i < 0)
+                               return null;
+                       return removeColumnAt(i);
+               }
+               
+               /**
+                * Removes the column and the cells it contains.
+                **/
+               public function 
removeColumnWithContent(column:TableColElement):Array
+               {
+                       var i:int = columns.indexOf(column);
+                       if(i < 0)
+                               return null;
+                       return removeColumnWithContentAt(i);
+               }
+
+               /**
+                * Removes the column at the index specified
+                **/
+               public function removeColumnAt(idx:int):TableColElement {
+                       if(idx < 0 || idx > columns.length - 1)
+                               return null;
+                       
+                       var col:TableColElement = columns.splice(idx,1)[0];
+                       normalizeCells();
+                       hasCellDamage = true;
+                       return col;
+               }
+               
+               /**
+                * Removes the column at the index specified and the cells it 
contains. 
+                **/
+               public function removeColumnWithContentAt(idx:int):Array
+               {
+                       
+                       var removedCells:Array = [];
+                       if(mxmlChildren){
+                               for (var i:int = 
mxmlChildren.length-1;i>=0;i--){
+                                       var child:* = mxmlChildren[i];
+                                       if(!(child is TableCellElement))
+                                               continue;
+                                       var cell:TableCellElement = child as 
TableCellElement;
+                                       if(cell.colIndex == idx){
+                                               
removedCells.unshift(removeChild(cell));
+                                       }
+                               }
+                       }
+                       removeColumnAt(idx);
+
+                       return removedCells;
+               }
+               
+               /**
+                * Remove all cells
+                * @inheritDoc
+                **/
+               override tlf_internal function removed():void
+               {
+                       hasCellDamage = true;
+                       //removeAllRowsWithContent();
+               }
+               
+               /**
+                * @private
+                * Gets table coordinates which represents the space occupied 
by cells spanning rows or columns
+                **/
+               private function getBlockedCoords(inRow:int = -1, inColumn:int 
= -1):Vector.<CellCoords>{
+                       var coords:Vector.<CellCoords> = new 
Vector.<CellCoords>();
+                       
+                       if(mxmlChildren) {
+                               for each(var child:* in mxmlChildren){
+                                       var cell:TableCellElement = child as 
TableCellElement;
+                                       if (cell==null) continue;
+                                       if(cell.columnSpan == 1 && cell.rowSpan 
== 1)
+                                               continue;
+                                       var curRow:int = cell.rowIndex;
+                                       if(inRow >= 0 && curRow != inRow)
+                                               continue;
+                                       if(inColumn >= 0 && inColumn != 
curColumn)
+                                               continue;
+                                       var curColumn:int = cell.colIndex;
+                                       var endRow:int = curRow + cell.rowSpan 
- 1;
+                                       var endColumn:int = curColumn + 
cell.columnSpan -1;
+                                       for(var rowIdx:int = curRow;rowIdx <= 
endRow;rowIdx++){
+                                               for(var colIdx:int = 
curColumn;colIdx <=endColumn;colIdx++){
+                                                       if(rowIdx == curRow && 
colIdx == curColumn){
+                                                               continue;
+                                                       }
+                                                       coords.push( new 
CellCoords(colIdx, rowIdx) );
+                                               }
+                                       }
+
+                               }
+                       }
+                       return coords;
                }
                
+               /**
+                * Sets the row and column indices of the cells in the table to 
match their logical position as described by the table columns and rows
+                **/
+               public function normalizeCells():void
+               {
+                       this.numColumns;this.numRows;
+                       var i:int;
+                       var blockedCoords:Vector.<CellCoords> = new 
Vector.<CellCoords>();
+                       
+                       if (!mxmlChildren) {
+                               return;
+                       }
+                       
+                       var curRow:int = 0;
+                       var curColumn:int = 0;
+                       
+                       for each(var child:* in mxmlChildren) {
+                               
+                               if (!(child is TableCellElement)) {
+                                       continue;
+                               }
+                               
+                               var cell:TableCellElement = child as 
TableCellElement;
+                               
+                               if (cell.rowIndex != curRow || cell.colIndex != 
curColumn) {
+                                       cell.rowIndex = curRow;
+                                       cell.colIndex = curColumn;
+                                       cell.damage();
+                               }
+                               
+                               // add blocked coords if the cell spans rows or 
columns
+                               var endRow:int = curRow + cell.rowSpan - 1;
+                               var endColumn:int = curColumn + cell.columnSpan 
-1;
+                               
+                               for(var rowIdx:int = curRow;rowIdx <= 
endRow;rowIdx++){
+                                       for(var colIdx:int = curColumn;colIdx 
<=endColumn;colIdx++){
+                                               if(rowIdx == curRow && colIdx 
== curColumn){
+                                                       continue;
+                                               }
+                                               blockedCoords.push(new 
CellCoords(colIdx,rowIdx) );
+                                       }
+                               }
+                               
+                               // advance coordinates while checking blocked 
ones from spans
+                               do {
+                                       curColumn++;
+                                       
+                                       if (curColumn >= numColumns){
+                                               curColumn = 0;
+                                               curRow++;
+                                       }
+                                       
+                                       var advanced:Boolean = true;
+                                       
+                                       for (i=0;i<blockedCoords.length;i++){
+                                               if(blockedCoords[i].column == 
curColumn && blockedCoords[i].row == curRow){
+                                                       advanced = false;
+                                                       
blockedCoords.splice(i,1);
+                                               }
+                                       }
+                                       
+                                       if (advanced) {
+                                               break;
+                                       }
+                                       
+                               } while(1);
+                               
+                       }
+                       
+               }
+               
+               /**
+                * Set the width of the specified column. The value can be a 
number or percent. 
+                **/
                public function setColumnWidth(columnIndex:int, value:*):Boolean
                {
-                       var tableColElement:TableColElement = 
getColumnAt(columnIndex) as TableColElement;
+                       //TODO: changing the column width probably requires a 
recompose of all cells in that column. Mark the cells in that row damaged.
+                       var tableColElement:TableColElement = 
getColumnAt(columnIndex);
                        if ( ! tableColElement )
                                return false;
                        
@@ -131,6 +804,22 @@ package flashx.textLayout.elements
                        return true;
                }
                
+               /**
+                * Set the height of the specified row. The value can be a 
number or percent. 
+                **/
+               public function setRowHeight(rowIdx:int, value:*):Boolean{
+                       //TODO: setting the row height might change the 
composition height of the cells. We'll need to do some housekeeping here.
+                       // I'm not sure this function makes sense. We need to 
handle both min and max values to allow for expanding cells.
+                       var row:TableRowElement = getRowAt(rowIdx);
+                       if(!row)
+                               return false;
+                       
+                       return true;
+               }
+               
+               /**
+                * Get the width of the column. 
+                **/
                public function getColumnWidth(columnIndex:int):*
                {
                        var tableColElement:TableColElement = 
getColumnAt(columnIndex) as TableColElement;
@@ -138,26 +827,712 @@ package flashx.textLayout.elements
                                return tableColElement.tableColumnWidth;
                        return 0;
         }
-        
-        public function get height():Number
-        {
-            return _height[numAcrossParcels];
-        }
-        
-        public function set height(val:*):void
-        {
-            _height[numAcrossParcels] = val;
-        }
-        
-        public function get heightArray():Array
-        {
-            return _height;
-        }
-        
-        public function set heightArray(newArray:Array):void
-        {
-            _height = newArray;
-        }
                
+               /**
+                * Sizes and positions the cells in the table. 
+                **/
+               public function composeCells():void{
+                       normalizeCells();
+                       _composedRowIndex = 0;
+                       
+                       // make sure the height that defines the row height did 
not change. If it did we might need to change the row height.
+                       if(!hasCellDamage)
+                               return;
+                       var damagedCells:Vector.<TableCellElement> = 
getDamagedCells();
+                       var cell:TableCellElement;
+                       
+                       for each(cell in damagedCells){
+                               // recompose the cells while tracking row 
height if necessary
+                               cell.compose();
+                       }
+                       
+                       // set row heights to minimum
+                       for each (var row:TableRowElement in rows){
+                               var minH:Number = 
row.computedFormat.minCellHeight;
+                               var maxH:Number = 
row.computedFormat.maxCellHeight;
+                               row.totalHeight = row.composedHeight = minH;
+                               if(maxH > minH)
+                                       row.isMaxHeight = false;
+                               else
+                                       row.isMaxHeight = true;
+                               
+                       }
+                       
+                       // set column positions...
+                       var xPos:Number = 0;
+                       for each (var col:TableColElement in columns){
+                               col.x = xPos;
+                               xPos += col.columnWidth;
+                       }
+                       
+                       if (mxmlChildren) {
+                               for(var i:int=0;i<mxmlChildren.length;i++){
+                                       if( !(mxmlChildren[i] is 
TableCellElement) )
+                                               continue;
+                                       cell = mxmlChildren[i] as 
TableCellElement;
+                                       while(rows.length < cell.rowIndex+1){
+                                               addRow(defaultRowFormat);
+                                       }
+                                       row = getRowAt(cell.rowIndex);
+                                       if(!row)
+                                               throw new Error("this should 
not happen...");
+                                       if(row.isMaxHeight) {
+                                               continue;
+                                       }
+                                       
+                                       var cellHeight:Number = 
cell.getComposedHeight();
+                                       if(cell.rowSpan > 1)
+                                       {
+                                               // figure out the total height 
taking into account fixed height rows and the total span.
+                                               
+                                               // for now, we're taking the 
easy way out assuming the rows are not fixed...
+                                               row.totalHeight = 
Math.max(row.totalHeight, cellHeight);
+                                               
+                                       }
+                                       else
+                                       {
+                                               row.composedHeight = 
Math.max(row.composedHeight, cellHeight);
+                                               row.composedHeight = 
Math.min(row.composedHeight, row.computedFormat.maxCellHeight);
+                                               row.totalHeight = 
Math.max(row.composedHeight, row.totalHeight);
+                                       }
+                                       if(row.composedHeight == 
row.computedFormat.maxCellHeight)
+                                               row.isMaxHeight = true;
+                               }
+                       }
+                       
+                       
+                       if(!_tableRowsComputed)
+                       {
+                               // create arrays or rows to make table 
composition simpler
+                               // For now we're assuming all cells have the 
correct row and column indices.
+                               // For this assumption to remain valid, the 
interaction manager will have to update all indices when inserting rows and 
columns.
+                               // actually, it probably makes sense for 
TableElement to handle that when adding rows and columns.
+                               // we need to think this through.
+                               _bodyRows = new Vector.< 
Vector.<TableCellElement> >();
+                               
+                               if (mxmlChildren) {
+                                       for(i=0;i<mxmlChildren.length;i++){
+                                               
+                                               if ( !(mxmlChildren[i] is 
TableCellElement) ) {
+                                                       continue;
+                                               }
+                                               
+                                               cell = mxmlChildren[i] as 
TableCellElement;
+                                               
+                                               while(cell.rowIndex >= 
_bodyRows.length)
+                                                       _bodyRows.push(new 
Vector.<TableCellElement>());
+                                                       
+                                               var 
rowVec:Vector.<TableCellElement> = _bodyRows[cell.rowIndex] as 
Vector.<TableCellElement>;
+                                               
+                                               if(!rowVec){
+                                                       rowVec = new 
Vector.<TableCellElement>();
+                                                       
_bodyRows[cell.rowIndex] = rowVec;
+                                               }
+                                               
+                                               if(rowVec.length > 
cell.colIndex && rowVec[cell.colIndex]) {
+                                                       throw new Error("Two 
cells cannot have the same coordinates");
+                                               }
+                                               
+                                               rowVec.push(cell);
+                                       }
+                               }
+                               
+                               if(headerRowCount > 0){
+                                       _headerRows = 
_bodyRows.splice(0,headerRowCount);
+                               } else {
+                                       _headerRows = null;
+                               }
+                               
+                               if(footerRowCount > 0){
+                                       _footerRows = 
_bodyRows.splice(-footerRowCount,Number.MAX_VALUE);
+                               } else {
+                                       _footerRows = null;
+                               }
+                       }
+               }
+               
+               /**
+                * returns the header rows for composition
+                **/
+               public function getHeaderRows():Vector.< 
Vector.<TableCellElement> >{
+                       return _headerRows;
+               }
+               
+               /**
+                * returns the footer rows for composition
+                **/
+               public function getFooterRows():Vector.< 
Vector.<TableCellElement> >{
+                       return _footerRows;
+               }
+               
+               /**
+                * returns the body rows (sans header and footer cells) for 
composition
+                **/
+               public function getBodyRows():Vector.< 
Vector.<TableCellElement> >{
+                       return _bodyRows;
+               }
+               
+               /**
+                * returns a vector of table cells in the next row during 
composition
+                **/
+               public function getNextRow():Vector.<TableCellElement>{
+                       if(_composedRowIndex >= _bodyRows.length)
+                               return null;
+                       return _bodyRows[_composedRowIndex++];
+               }
+               
+               /**
+                * Returns the next table cell after the supplied table cell
+                **/
+               public function 
getNextCell(tableCell:TableCellElement):TableCellElement {
+                       var cell:TableCellElement;
+                       
+                       for each (var element:FlowElement in mxmlChildren) {
+                               cell = element as TableCellElement;
+                               
+                               if (cell) {
+                                       
+                                       // get next cell in same row 
+                                       if (cell.rowIndex==tableCell.rowIndex 
&& cell.colIndex-1==tableCell.colIndex) {
+                                               return cell;
+                                       }
+                                       
+                                       // get first cell in next row
+                                       if (cell.rowIndex-1==tableCell.rowIndex 
&& cell.colIndex==0) {
+                                               return cell;
+                                       }
+                                       
+                               }
+                       }
+                       
+                       return null;
+               }
+               
+               /**
+                * Returns the previous table cell after the supplied table cell
+                **/
+               public function 
getPreviousCell(tableCell:TableCellElement):TableCellElement {
+                       var cell:TableCellElement;
+                       var highestCellIndex:int = -1;
+                       var rowIndex:int = -1;
+                       
+                       for each (var element:FlowElement in mxmlChildren) {
+                               cell = element as TableCellElement;
+                               
+                               if (cell) {
+                                       
+                                       // get previous cell in same row 
+                                       if (cell.rowIndex==tableCell.rowIndex 
&& cell.colIndex+1==tableCell.colIndex) {
+                                               return cell;
+                                       }
+                                       
+                                       // get last cell in previous row
+                                       if 
(cell.rowIndex+1==tableCell.rowIndex) {
+                                               rowIndex = cell.rowIndex;
+                                               
+                                               if 
(highestCellIndex<cell.colIndex) {
+                                                       highestCellIndex = 
cell.colIndex;
+                                               }
+                                       }
+                                       
+                               }
+                       }
+                       
+                       if (rowIndex>-1 && highestCellIndex>-1) {
+                               return getCellAt(rowIndex, highestCellIndex);
+                       }
+                       
+                       return null;
+               }
+               
+               /**
+                * Returns the table cell at the row and column specified.
+                **/
+               public function getCellAt(rowIndex:int, 
columnIndex:int):TableCellElement {
+                       var cell:TableCellElement;
+                       
+                       for each (var element:FlowElement in mxmlChildren) {
+                               cell = element as TableCellElement;
+                               
+                               if (cell && cell.rowIndex==rowIndex && 
cell.colIndex==columnIndex) {
+                                       return cell;
+                               }
+                       }
+                       
+                       return null;
+               }
+               
+               /**
+                * Computed height of the header cells
+                **/
+               public function getHeaderHeight():Number{
+                       //TODO: compute the header height from the header cells
+                       return 0;
+               }
+               
+               /**
+                * Computed height of the footer cells
+                **/
+               public function getFooterHeight():Number{
+                       //TODO: compute the footer height from the footer cells
+                       return 0;
+                       
+               }
+               
+               /**
+                * Accepts a suggested table width and calculates the column 
widths. 
+                **/
+               public function normalizeColumnWidths(suggestedWidth:Number = 
600):void{
+                       //TODO: before composition make sure all column widths 
are rational numbers
+                       // We feed in a width to use if there's no width 
otherwise specified.
+                       
+                       // quick and dirty...
+                       var setCount:* = computedFormat.columnCount;
+                       if(!setCount){
+                               // we need to figure this out...
+                       } else if(setCount == FormatValue.AUTO){
+                               // figure out...
+                       } else {
+                               var cCount:Number = computedFormat.columnCount;
+                       }
+                       
+                       while (cCount > columns.length){
+                               addColumn();
+                       }
+                       
+                       var w:Number;
+                       switch(typeof(computedFormat.tableWidth)){
+                               case "number":
+                                       w = suggestedWidth;
+                                       break;
+                               case "string":
+                                       
if(computedFormat.tableWidth.indexOf("%") > 0){
+                                               w = suggestedWidth / 
(parseFloat(computedFormat.tableWidth)/100);
+                                               break;
+                                       }
+                               default:
+                                       w = suggestedWidth;
+                                       break;
+                       }
+                       if(isNaN(w))
+                               w = 600;
+                       if(w > 20000)
+                               w = 600;
+                       
+                       _computedWidth = w;
+
+                       var numNonsetColumns:int = numColumns;
+                       var col:TableColElement;
+                       for each(col in columns){
+                               // simply stomp on the settings. (need to 
finesse this...)
+                               if(typeof(col.columnWidth) == "number")
+                               {
+                                       w-= col.columnWidth;
+                                       numNonsetColumns--;
+                               }
+                       }
+
+                       for each(col in columns)
+                       {
+                               // simply stomp on the settings. (need to 
finesse this...)
+                               if(typeof(col.columnWidth) == "number")
+                                       continue;
+                               col.columnWidth = w / numNonsetColumns;
+                       }
+               }
+               
+               /**
+                * Returns a vector of all the damaged cells in the table.
+                **/
+               private function getDamagedCells():Vector.<TableCellElement>{
+                       var cells:Vector.<TableCellElement> = new 
Vector.<TableCellElement>();
+                       for each (var cell:* in this.mxmlChildren){
+                               if((cell is TableCellElement) && 
cell.isDamaged())
+                                       cells.push(cell as TableCellElement);
+                       }
+                       return cells;
+               }
+               
+               /**
+                * Marks all of the cells in the table as damaged.
+                **/
+               private function markCellsDamaged():void {
+                       if (!mxmlChildren) return;
+                       
+                       for each (var cell:* in this.mxmlChildren){
+                               if (cell is TableCellElement) {
+                                       cell.damage();
+                               }
+                       }
+               }
+               
+               /**
+                * Returns a vector of all the table cell elements in the table.
+                **/
+               public function getCells():Vector.<TableCellElement> {
+                       var cells:Vector.<TableCellElement> = new 
Vector.<TableCellElement>();
+                       
+                       for each (var cell:* in mxmlChildren){
+                               if (cell is TableCellElement) {
+                                       cells.push(cell as TableCellElement);
+                               }
+                       }
+                       
+                       return cells;
+               }
+               
+               /**
+                * Returns an array of all the table cells.
+                **/
+               public function getCellsArray():Array {
+                       var cells:Array = [];
+                       
+                       for each (var cell:* in mxmlChildren){
+                               if (cell is TableCellElement) {
+                                       cells.push(cell as TableCellElement);
+                               }
+                       }
+                       
+                       return cells;
+               }
+               
+               /**
+                * Returns the table width
+                **/
+               public function get width():Number
+               {
+                       return _computedWidth;
+               }
+               
+               /**
+                * Sets the table width
+                **/
+               public function set width(value:*):void
+               {
+                       normalizeColumnWidths(value);
+               }
+               
+               
+               /**
+                * Indicates elements in the table have been modified and the 
table must be recomposed.
+                **/
+               public function get hasCellDamage():Boolean
+               {
+                       return _hasCellDamage;
+               }
+
+               public function set hasCellDamage(value:Boolean):void
+               {
+                       _hasCellDamage = value;
+               }
+
+               /**
+                * Returns the number of header rows in the table
+                **/
+               public function get headerRowCount():uint
+               {
+                       return _headerRowCount;
+               }
+
+               /**
+                * Sets the number of header rows in the table
+                **/
+               public function set headerRowCount(value:uint):void
+               {
+                       if(value != _headerRowCount)
+                               _tableRowsComputed = false;
+                       _headerRowCount = value;
+               }
+
+               /**
+                * Returns the number of footer rows in the table
+                **/
+               public function get footerRowCount():uint
+               {
+                       return _footerRowCount;
+               }
+
+               /**
+                * Sets the number of footer rows in the table
+                **/
+               public function set footerRowCount(value:uint):void
+               {
+                       if(value != _footerRowCount)
+                               _tableRowsComputed = false;
+                       _footerRowCount = value;
+               }
+               
+               /**
+                * Gets the first TextFlowTableBlock in the table. 
+                **/
+               public function getFirstBlock():TextFlowTableBlock{
+                       if(_tableBlocks == null)
+                               _tableBlocks = new 
Vector.<TextFlowTableBlock>();
+                       if(_tableBlocks.length == 0)
+                               _tableBlocks.push(new TextFlowTableBlock(0));
+                       _tableBlockIndex = 0;
+                       _tableBlocks[0].parentTable = this;
+                       
+                       return _tableBlocks[0];
+               }
+               
+               /**
+                * Gets the next TextFlowTableBlock. 
+                **/
+               public function getNextBlock():TextFlowTableBlock{
+                       if(_tableBlocks == null)
+                               _tableBlocks = new 
Vector.<TextFlowTableBlock>();
+                       _tableBlockIndex++;
+                       while(_tableBlocks.length <= _tableBlockIndex){
+                               _tableBlocks.push( new 
TextFlowTableBlock(_tableBlocks.length) );
+                       }
+                       _tableBlocks[_tableBlockIndex].parentTable = this;
+                       
+                       return _tableBlocks[_tableBlockIndex];
+               }
+               
+               /**
+                * Gets the total atom length of this flow element in the text 
flow.  
+                * 
+                * @inheritDoc
+                **/
+               override public function get textLength():int{
+                       return 1;
+               }
+               
+               /**
+                * Returns the cell at the specified row and column. 
+                **/
+               private function getCellIndex(rowIdx:int,columnIdx:int):int{
+                       if(rowIdx == 0 && columnIdx == 0)
+                               return 0;
+                       for (var i:int=0;i<mxmlChildren.length;i++){
+                               var item:* = mxmlChildren[i];
+                               if(!(item is TableCellElement))
+                                       continue;
+                               var cell:TableCellElement = item as 
TableCellElement;
+                               if(cell.rowIndex == rowIdx && cell.colIndex == 
columnIdx)
+                                       return i;
+                       }
+                       return -1;
+                       
+               }
+               
+               /**
+                * Returns a vector of table cell elements in the given cell 
range. 
+                **/
+               public function getCellsInRange(anchorCoords:CellCoordinates, 
activeCoords:CellCoordinates, 
block:TextFlowTableBlock=null):Vector.<TableCellElement>
+               {
+                       var firstCoords:CellCoordinates = anchorCoords.clone();
+                       var lastCoords:CellCoordinates = activeCoords.clone();
+                       if(
+                               lastCoords.row < firstCoords.row ||
+                               (lastCoords.row == firstCoords.row && 
lastCoords.column < firstCoords.column)
+                       )
+                       {
+                               firstCoords = activeCoords.clone();
+                               lastCoords = anchorCoords.clone();
+                       }
+                       
+                       // make sure the rectangle is not inversed
+                       if(lastCoords.column < firstCoords.column)
+                       {
+                               var col:int = firstCoords.column;
+                               firstCoords.column = lastCoords.column;
+                               lastCoords.column = col;
+                       }
+                       var firstCell:TableCellElement = findCell(firstCoords);
+                       var cells:Vector.<TableCellElement> = new 
Vector.<TableCellElement>();
+                       if(!block || getCellBlock(firstCell) == block)
+                               cells.push(firstCell);
+                       var idx:int = mxmlChildren.indexOf(firstCell);
+                       while(++idx < mxmlChildren.length)
+                       {
+                               var nextCell:TableCellElement = 
mxmlChildren[idx];
+                               if(nextCell.rowIndex > lastCoords.row || 
(nextCell.rowIndex == lastCoords.row && nextCell.colIndex > lastCoords.column))
+                                       break;
+                               // skip cells outside rectangle
+                               if(nextCell.colIndex > lastCoords.column || 
nextCell.colIndex < firstCoords.column)
+                                       continue;
+                               if(!block || getCellBlock(nextCell) == block)
+                                       cells.push(nextCell);
+                       }
+                       return cells;
+               }
+               
+               /**
+                * Finds the cell at the specified cell coordinates or null if 
no cell is found. 
+                **/
+               public function 
findCell(coords:CellCoordinates):TableCellElement
+               {
+                       // get a guess of the cell location. If there's no 
holes (such as spans), it should theoretically pinpoint the index.
+                       var idx:int = (coords.row+1) * (coords.column+1) -1;
+                       if(idx >= numChildren)
+                               idx = numChildren-1;
+                       
+                       var cell:TableCellElement = mxmlChildren[idx];
+                       // look ahead to see if we're short (not sure if this 
is needed).
+                       do
+                       {
+                               if(idx == numChildren-1)
+                                       break;
+                               var nextCell:TableCellElement = 
mxmlChildren[idx+1];
+                               if(nextCell.rowIndex > coords.row || 
(nextCell.rowIndex == coords.row && nextCell.colIndex > coords.column))
+                                       break;
+                               
+                               cell = nextCell;
+                               idx++;
+                               
+                       }while(true);
+                       // look behind accounting for spans
+                       do
+                       {
+                               //check if the coords fall within the row and 
column span
+                               if(
+                                       cell.colIndex <= coords.column && 
cell.colIndex + cell.columnSpan - 1 >= coords.column &&
+                                       cell.rowIndex <= coords.row && 
cell.rowIndex + cell.rowSpan - 1 >= coords.row
+                               )
+                                       break;
+                               //oops we hit the first cell without finding 
anything. At least return that...
+                               if(cell.colIndex == 0 && cell.rowIndex == 0)
+                                       break;
+                               if(idx == 0)
+                                       break;
+                               var prevCell:TableCellElement = 
mxmlChildren[idx-1];
+                               cell = prevCell;
+                               idx--;
+                       }while(true);
+                       
+                       return cell;
+               }
+               
+               /**
+                * Adds the table cell container to the table block specified. 
+                **/
+               public function addCellToBlock(cell:TableCellElement, 
block:TextFlowTableBlock):void
+               {
+                       block.addCell(cell.container);
+                       tableBlockDict[cell] = block;
+               }
+               
+               /**
+                * Returns the table block for the given table cell. 
+                **/
+               public function 
getCellBlock(cell:TableCellElement):TextFlowTableBlock
+               {
+                       return tableBlockDict[cell];
+               }
+
+               /**
+                * Keeps a reference to all the table blocks belonging to this 
table. 
+                **/
+               private function get tableBlockDict():Dictionary
+               {
+                       if(_tableBlockDict == null)
+                               _tableBlockDict = new Dictionary();
+                       return _tableBlockDict;
+               }
+               
+               /**
+                * Returns a vector of the table blocks.
+                **/
+               public function get tableBlocks():Vector.<TextFlowTableBlock>
+               {
+                       return _tableBlocks;
+               }
+               
+               public function 
getTableBlocksInRange(start:CellCoordinates,end:CellCoordinates):Vector.<TextFlowTableBlock>
+               {
+                       var coords:CellCoordinates = start.clone();
+                       if(end.column < start.column)
+                       {
+                               coords = end.clone();
+                               end = start.clone();
+                       }
+                       var blocks:Vector.<TextFlowTableBlock> = new 
Vector.<TextFlowTableBlock>();
+                       var block:TextFlowTableBlock = 
getCellBlock(findCell(coords));
+                       if(block)
+                               blocks.push(block);
+                       while(block)
+                       {
+                               coords.row++;
+                               if(coords.row > end.row)
+                                       break;
+                               if(getCellBlock(findCell(coords)) == block)
+                                       continue;
+                               block = getCellBlock(findCell(coords));
+                               if(block)
+                                       blocks.push(block);
+                       }
+                       return blocks;
+               }
+
+               /** @private */
+               tlf_internal override function 
getNextLeafHelper(limitElement:FlowGroupElement,child:FlowElement):FlowLeafElement
+               {
+                       return parent.getNextLeafHelper(limitElement,this);
+               }
+               
+               /** @private */
+               tlf_internal override function 
getPreviousLeafHelper(limitElement:FlowGroupElement,child:FlowElement):FlowLeafElement
+               {
+                       return parent.getPreviousLeafHelper(limitElement,this);
+               }
+
+               private function getLeaf():TableLeafElement
+               {
+                       if(_leaf == null)
+                               _leaf = new TableLeafElement(this);
+                       return _leaf;
+               }
+               
+               public override function 
findLeaf(relativePosition:int):FlowLeafElement
+               {
+                       return getLeaf();
+               }
+               public override function getLastLeaf(): FlowLeafElement
+               {
+                       return getLeaf();
+               }
+               public override function getFirstLeaf():FlowLeafElement
+               {
+                       return getLeaf();
+               }
+
+               tlf_internal override function createContentElement():void{}
+               /** @private 
+                * Release the FTE data structure that corresponds to the 
FlowElement, so it can be gc'ed
+                */
+               tlf_internal override function releaseContentElement():void{}
+
+               /**
+                * Creates and returns a default row 
+                **/
+               tlf_internal function createRowElement(index:int, 
defaultRowFormat:ITextLayoutFormat):TableRowElement {
+                       var row:TableRowElement = new 
TableRowElement(defaultRowFormat);
+                       row.rowIndex = index;
+                       row.table = this;
+                       return row;
+               }
+
+               /**
+                * Creates and returns a default column 
+                **/
+               tlf_internal function createColumnElement(index:int, 
defaultColumnFormat:ITextLayoutFormat):TableColElement {
+                       var column:TableColElement = new 
TableColElement(defaultColumnFormat);
+                       column.colIndex = index;
+                       column.table = this;
+                       return column;
+               }
+       }
+}
+class CellCoords
+{
+       public var column:int;
+       public var row:int;
+       public function CellCoords(colIdx:int,rowIdx:int)
+       {
+               column = colIdx;
+               row = rowIdx;
        }
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as 
b/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
index 4b5bd0f..edad5e3 100644
--- a/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
+++ b/textLayout/src/flashx/textLayout/elements/TableFormattedElement.as
@@ -25,6 +25,9 @@ package flashx.textLayout.elements
                        super();
                }
                
+               /**
+                * Get a reference to the table. We could refactor this since 
it's accessed multiple times.
+                **/
                public function getTable():TableElement
                {
                        // find the root element entry and either return null 
or the containing textFlow
@@ -32,6 +35,37 @@ package flashx.textLayout.elements
                        while ((elem.parent) != null && !( elem.parent is 
TableElement))
                                elem = elem.parent;
                        return elem.parent as TableElement;             
-               }       
+               }
+               
+               
+               private var _table:TableElement;
+               
+               /**
+                * Returns a reference to the table. For this to work we need 
to set the 
+                * table to null when it's removed. 
+                **/
+               public function get table():TableElement {
+                       
+                       if (_table) return _table;
+                       
+                       // find the root element entry and either return null 
or the containing textFlow
+                       var elem:FlowGroupElement = this;
+                       
+                       while ((elem.parent) != null && !(elem.parent is 
TableElement)) {
+                               elem = elem.parent;
+                       }
+                       
+                       _table = elem.parent as TableElement;
+                       
+                       return _table;
+               }
+               
+               /**
+                * @private
+                **/
+               public function set table(element:TableElement):void {
+                       _table = element;
+               }
        }
-}
\ No newline at end of file
+}
+

Reply via email to