You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ha...@apache.org on 2014/10/05 21:40:40 UTC

[3/5] Commit of table work

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/SelectionManager.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/SelectionManager.as b/textLayout/src/flashx/textLayout/edit/SelectionManager.as
index dd6f117..6de1c2b 100644
--- a/textLayout/src/flashx/textLayout/edit/SelectionManager.as
+++ b/textLayout/src/flashx/textLayout/edit/SelectionManager.as
@@ -20,8 +20,10 @@ package flashx.textLayout.edit
 {
     import flash.desktop.Clipboard;
     import flash.desktop.ClipboardFormats;
+    import flash.display.BitmapData;
     import flash.display.DisplayObject;
     import flash.display.InteractiveObject;
+    import flash.display.Shape;
     import flash.display.Stage;
     import flash.errors.IllegalOperationError;
     import flash.events.ContextMenuEvent;
@@ -31,8 +33,10 @@ package flashx.textLayout.edit
     import flash.events.KeyboardEvent;
     import flash.events.MouseEvent;
     import flash.events.TextEvent;
+    import flash.geom.Matrix;
     import flash.geom.Point;
     import flash.geom.Rectangle;
+    import flash.text.engine.TextBlock;
     import flash.text.engine.TextLine;
     import flash.text.engine.TextLineValidity;
     import flash.text.engine.TextRotation;
@@ -40,14 +44,20 @@ package flashx.textLayout.edit
     import flash.ui.Keyboard;
     import flash.ui.Mouse;
     import flash.ui.MouseCursor;
+    import flash.ui.MouseCursorData;
+    import flash.utils.Dictionary;
     import flash.utils.getQualifiedClassName;
     
     import flashx.textLayout.compose.IFlowComposer;
     import flashx.textLayout.compose.TextFlowLine;
+    import flashx.textLayout.compose.TextFlowTableBlock;
     import flashx.textLayout.container.ColumnState;
     import flashx.textLayout.container.ContainerController;
     import flashx.textLayout.debug.Debugging;
     import flashx.textLayout.debug.assert;
+    import flashx.textLayout.elements.CellContainer;
+    import flashx.textLayout.elements.CellCoordinates;
+    import flashx.textLayout.elements.CellRange;
     import flashx.textLayout.elements.Configuration;
     import flashx.textLayout.elements.FlowElement;
     import flashx.textLayout.elements.FlowLeafElement;
@@ -55,7 +65,9 @@ package flashx.textLayout.edit
     import flashx.textLayout.elements.IConfiguration;
     import flashx.textLayout.elements.InlineGraphicElement;
     import flashx.textLayout.elements.ParagraphElement;
-    import flashx.textLayout.elements.TableDataCellElement;
+    import flashx.textLayout.elements.TableBlockContainer;
+    import flashx.textLayout.elements.TableCellElement;
+    import flashx.textLayout.elements.TableColElement;
     import flashx.textLayout.elements.TableElement;
     import flashx.textLayout.elements.TableRowElement;
     import flashx.textLayout.elements.TextFlow;
@@ -122,23 +134,325 @@ package flashx.textLayout.edit
      * @langversion 3.0
      */
     public class SelectionManager implements ISelectionManager
-    {       
+    {
+		static tlf_internal var useTableSelectionCursors:Boolean = false;
+		/**
+		 * Cursor for selection of table
+		 **/
+		public static var SelectTable:String = "selectTable";
+		
+		/**
+		 * Cursor for selection of table row
+		 **/
+		public static var SelectTableRow:String = "selectTableRow";
+		
+		/**
+		 * Cursor for selection of table column
+		 **/
+		public static var SelectTableColumn:String = "selectTableColumn";
+		
         private var _focusedSelectionFormat:SelectionFormat;
         private var _unfocusedSelectionFormat:SelectionFormat;
         private var _inactiveSelectionFormat:SelectionFormat;
+		private var _focusedCellSelectionFormat:SelectionFormat;
+		private var _unfocusedCellSelectionFormat:SelectionFormat;
+		private var _inactiveCellSelectionFormat:SelectionFormat;
         private var _selFormatState:String = SelectionFormatState.UNFOCUSED;
         private var _isActive:Boolean;
         
         /** The TextFlow of the selection. */
         private var _textFlow:TextFlow;
+		
+		protected var _subManager:ISelectionManager;
+		protected var _superManager:ISelectionManager;
+		
+		private var _currentTable:TableElement;
+		
+		// this should probably be produced dynamically rather than keep a reference.
+		private var _cellRange:CellRange;
+		
+		//TODO the following functions need proper comments and should be moved to a logical location within the class.
+		
+		public function get currentTable():TableElement
+		{
+			return _currentTable;
+		}
+		public function set currentTable(table:TableElement):void
+		{
+			_currentTable = table;
+		}
+		
+		public function hasCellRangeSelection():Boolean
+		{
+			if (!_currentTable) {
+				return false;
+			}
+			
+			//we should really check the anchorCellPosition and activeCellPosition instead
+			if (!_cellRange) {
+				return false;
+			}
+			
+			return true;
+		}
+		
+		/**
+		 * Select a table cell text flow
+		 **/
+		public function selectCellTextFlow(cell:TableCellElement):void {
+			
+			if (cell && cell.table) {
+				var selectionManager:SelectionManager = cell.textFlow.interactionManager as SelectionManager;
+				
+				clear();
+				
+				if (selectionManager) {
+					selectionManager.currentTable = cell.table;
+					selectionManager.selectAll();
+					
+					// this seems to be required to work but it should not be
+					selectionManager.setFocus(); 
+				}
+			}
+		}
+		
+		/**
+		 * Select a table cell. 
+		 **/
+		public function selectCell(cell:TableCellElement):void {
+			var beginCoordinates:CellCoordinates;
+			var endCoordinates:CellCoordinates;
+			
+			if (cell) {
+				beginCoordinates = new CellCoordinates(cell.rowIndex, cell.colIndex);
+				endCoordinates = new CellCoordinates(cell.rowIndex, cell.colIndex);
+				
+				if (beginCoordinates.isValid()) {
+					selectCellRange(beginCoordinates, endCoordinates);
+				}
+			}
+		}
+		
+		/**
+		 * Select table cells at the specified index.
+		 **/
+		public function selectCellAt(table:TableElement, rowIndex:int, colIndex:int):void {
+			var cell:TableCellElement = table.getCellAt(rowIndex, colIndex);
+			
+			if (cell) {
+				selectCell(cell);
+			}
+		}
+		
+		/**
+		 * Select table cells at the specified index
+		 **/
+		public function selectCells(cells:Vector.<TableCellElement>):void {
+			var startX:int = int.MAX_VALUE;
+			var startY:int = int.MAX_VALUE;
+			var endX:int = int.MIN_VALUE;
+			var endY:int = int.MIN_VALUE;
+			var cell:TableCellElement;
+			var table:TableElement;
+			for each(cell in cells)
+			{
+				if(cell)
+				{
+					if(table == null)
+						table = cell.getTable();
+					
+					var col:int = cell.colIndex;
+					var row:int = cell.rowIndex;
+					if(col < startX)
+						startX = col;
+					if(col > endX)
+						endX = col;
+					if(row < startY)
+						startY = row;
+					if(row > endY)
+						endY = row;
+				}
+			}
+			if(startX <= endX && startY <= endY)
+				selectCellRange(
+					new CellCoordinates(startY,startX,table),
+					new CellCoordinates(endY,endX,table)
+				);
+		}
+		
+		/**
+		 * Select the specified table row. 
+		 **/
+		public function selectRow(row:TableRowElement):void {
+			var beginCoordinates:CellCoordinates;
+			var endCoordinates:CellCoordinates;
+			
+			if (row) {
+				beginCoordinates = new CellCoordinates(row.rowIndex, 0);
+				endCoordinates = new CellCoordinates(row.rowIndex, row.numCells);
+				
+				if (beginCoordinates.isValid() && endCoordinates.isValid()) {
+					selectCellRange(beginCoordinates, endCoordinates);
+				}
+			}
+		}
+		
+		/**
+		 * Select a table row at the specified index
+		 **/
+		public function selectRowAt(table:TableElement, index:int):void {
+			var row:TableRowElement = table ? table.getRowAt(index) : null;
+			
+			if (row) {
+				selectRow(row);
+			}
+		}
+		
+		/**
+		 * Selects the table rows provided
+		 **/
+		public function selectRows(rows:Array):void {
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			var table:TableElement;
+			var cell:TableCellElement;
+			
+			if (rows && rows.length) {
+				
+				for (var i:int;i<rows.length;i++) 
+				{
+					var row:TableRowElement = rows[i] as TableRowElement;
+					
+					if (row)
+					{
+						for each(cell in row.cells)
+						cells.push(cell);
+					}
+				}
+				
+				selectCells(cells);
+			}
+		}
+		
+		/**
+		 * Select a table column. 
+		 **/
+		public function selectColumn(column:TableColElement):void {
+			var table:TableElement = column.table;
+			
+			if (column && table) {
+				selectCells(table.getCellsForColumn(column));
+			}
+		}
+		
+		/**
+		 * Select a table column at the specified index 
+		 **/
+		public function selectColumnAt(table:TableElement, index:int):void {
+			var column:TableColElement = table.getColumnAt(index);
+			
+			if (column && table) {
+				return selectColumn(column);
+			}
+		}
+		
+		/**
+		 * Selects the table columns provided
+		 **/
+		public function selectColumns(columns:Array):void {
+			var cells:Vector.<TableCellElement> = new Vector.<TableCellElement>();
+			var cell:TableCellElement;
+			
+			if (columns && columns.length) {
+				
+				for (var i:int;i<columns.length;i++) 
+				{
+					var column:TableColElement = columns[i] as TableColElement;
+					
+					if (column)
+					{
+						for each(cell in column.cells)
+							cells.push(cell);
+					}
+					
+				}
+				
+				selectCells(cells);
+			}
+		}
+		
+		/**
+		 * Select all cells in a table. 
+		 **/
+		public function selectTable(table:TableElement):void {
+			
+			if (table)
+			{
+				var startCoords:CellCoordinates = new CellCoordinates(0,0,table);
+				var endCoords:CellCoordinates = new CellCoordinates(table.numRows-1,table.numColumns-1,table);
+				selectCellRange(startCoords,endCoords);
+			}
+			
+		}
+		
+		/**
+		 * Select a range of table cells. 
+		 **/
+		public function selectCellRange(anchorCoords:CellCoordinates, activeCoords:CellCoordinates):void
+		{
+			var blocks:Vector.<TextFlowTableBlock>;
+			var block:TextFlowTableBlock;
+			var controller:ContainerController;
+			
+			if (selectionType == SelectionType.TEXT) {
+				clear();
+			}
+			clearCellSelections();
+			
+			if (anchorCoords && activeCoords) {
+				_cellRange = new CellRange(_currentTable, anchorCoords, activeCoords);
+				activeCellPosition = activeCoords;
+				blocks = _currentTable.getTableBlocksInRange(anchorCoords, activeCoords);
+				
+				for each(block in blocks) {
+					block.controller.clearSelectionShapes();
+					block.controller.addCellSelectionShapes(currentCellSelectionFormat.rangeColor, block, anchorCoords, activeCoords);
+				}
+				if(subManager)
+				{
+					subManager.selectRange(-1,-1);
+					subManager = null;
+				}
+			}
+			else
+			{
+				_cellRange = null;
+				activeCellPosition.column = -1;
+				activeCellPosition.row = -1;
+			}
+			selectionChanged();
+		}
+		
+		public function getCellRange():CellRange
+		{
+			// not really a good implementation. We'll fix this later
+			return _cellRange;
+		}
+		public function setCellRange(range:CellRange):void
+		{
+			selectCellRange(range.anchorCoordinates,range.activeCoordinates);
+			//_cellRange = range;
+			// do something about actually drawing the selection.
+		}
         
         // current range of selection
         /** Anchor point of the current selection, as an index into the TextFlow. */
         private var anchorMark:Mark;
         /** Active end of the current selection, as an index into the TextFlow. */
         private var activeMark:Mark;
-        
-        // used to save pending attributes at a point selection
+        private var _anchorCellPosition:CellCoordinates;
+		private var _activeCellPosition:CellCoordinates;
+
+		// used to save pending attributes at a point selection
         private var _pointFormat:ITextLayoutFormat;
         /** 
          * The format that will be applied to inserted text. 
@@ -190,6 +504,8 @@ package flashx.textLayout.edit
             _textFlow = null;
             anchorMark = createMark();
             activeMark = createMark();
+			anchorCellPosition = createCellMark();
+			activeCellPosition = createCellMark();
             _pointFormat = null;
             _isActive = false;
             CONFIG::debug 
@@ -197,7 +513,12 @@ package flashx.textLayout.edit
                 this.id = smCount.toString();
                 smCount++;
             }
+			
+			Mouse.registerCursor(SelectTable, createSelectTableCursor());
+			Mouse.registerCursor(SelectTableRow, createSelectTableRowCursor());
+			Mouse.registerCursor(SelectTableColumn, createSelectTableColumnCursor());
         }
+		
         /**
          * @copy ISelectionManager#getSelectionState()
          * 
@@ -211,7 +532,10 @@ package flashx.textLayout.edit
          */
         public function getSelectionState():SelectionState
         {
-            return new SelectionState(_textFlow, anchorMark.position, activeMark.position, pointFormat);
+			if(subManager)
+				return subManager.getSelectionState();
+			
+            return new SelectionState(_textFlow, anchorMark.position, activeMark.position, pointFormat, _cellRange);
         }
                 
         /**
@@ -238,8 +562,45 @@ package flashx.textLayout.edit
          * @langversion 3.0
          */
         public function hasSelection():Boolean
-        { return anchorMark.position != -1; }
+        {
+			return selectionType == SelectionType.TEXT;
+		}
+
+		/**
+		 *  @copy ISelectionManager#hasAnySelection()
+		 * 
+		 * @includeExample examples\SelectionManager_hasSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function hasAnySelection():Boolean
+		{
+			return selectionType != SelectionType.NONE;
+		}
 
+		/**
+		 * Indicates the type of selection. 
+		 * 
+		 * <p>The <code>selectionType</code> describes the kind of selection. 
+		 * It can either be <code>SelectionType.TEXT</code> or <code>SelectionType.CELLS</code>
+		 * 
+		 * @see flashx.textLayout.edit.SelectionType
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get selectionType() : String
+		{
+			if(anchorMark.position != -1)
+				return SelectionType.TEXT;
+			else if(anchorCellPosition.isValid())
+				return SelectionType.CELLS;
+			
+			return SelectionType.NONE;
+		}
         /** 
          *  @copy ISelectionManager#isRangeSelection()
          * 
@@ -277,6 +638,8 @@ package flashx.textLayout.edit
                     flushPendingOperations();
                 
                 clear();
+				clearCellSelections();
+				_cellRange = null;
                 
                 // If we switch into read-only mode, make sure the cursor isn't showing a text selection IBeam
                 if (!value) // see Watson 2637162
@@ -348,7 +711,29 @@ package flashx.textLayout.edit
             }
             return focusedSelectionFormat;
          }
-         
+
+		 /**
+		  *  @copy ISelectionManager#currentCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function get currentCellSelectionFormat():SelectionFormat
+		 { 
+			 if (_selFormatState == SelectionFormatState.UNFOCUSED)
+			 {
+				 return unfocusedCellSelectionFormat;
+			 }
+			 else if (_selFormatState == SelectionFormatState.INACTIVE)
+			 {
+				 return inactiveCellSelectionFormat;
+			 }
+			 return focusedCellSelectionFormat;
+		 }
+
         /**
          *  @copy ISelectionManager#focusedSelectionFormat
          * 
@@ -420,7 +805,79 @@ package flashx.textLayout.edit
          { 
             return _inactiveSelectionFormat ? _inactiveSelectionFormat : (_textFlow ? _textFlow.configuration.inactiveSelectionFormat : null);
          }       
-         
+
+		 /**
+		  *  @copy ISelectionManager#focusedCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function set focusedCellSelectionFormat(val:SelectionFormat):void
+		 { 
+			 _focusedCellSelectionFormat = val;
+			 if (this._selFormatState == SelectionFormatState.FOCUSED)
+				 refreshSelection();
+		 }
+		 
+		 /**
+		  * @private - docs on setter
+		  */
+		 public function get focusedCellSelectionFormat():SelectionFormat
+		 { 
+			 return _focusedCellSelectionFormat ? _focusedCellSelectionFormat : (_textFlow ? _textFlow.configuration.focusedSelectionFormat : null);
+		 }       
+		 
+		 /**
+		  *  @copy ISelectionManager#unfocusedCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function set unfocusedCellSelectionFormat(val:SelectionFormat):void
+		 { 
+			 _unfocusedCellSelectionFormat = val;
+			 if (this._selFormatState == SelectionFormatState.UNFOCUSED)
+				 refreshSelection();
+		 }          
+		 
+		 /**
+		  *  @private - docs on setter
+		  */
+		 public function get unfocusedCellSelectionFormat():SelectionFormat
+		 { 
+			 return _unfocusedCellSelectionFormat ? _unfocusedCellSelectionFormat : (_textFlow ? _textFlow.configuration.unfocusedSelectionFormat : null);
+		 }
+		 
+		 /**
+		  *  @copy ISelectionManager#inactiveCellSelectionFormat
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  * 
+		  * @see flashx.textLayout.edit.SelectionFormat
+		  */
+		 public function set inactiveCellSelectionFormat(val:SelectionFormat):void
+		 { 
+			 _inactiveCellSelectionFormat = val;
+			 if (this._selFormatState == SelectionFormatState.INACTIVE)
+				 refreshSelection();
+		 }          
+		 
+		 /**
+		  * @private - docs on setter
+		  */
+		 public function get inactiveCellSelectionFormat():SelectionFormat
+		 { 
+			 return _inactiveCellSelectionFormat ? _inactiveCellSelectionFormat : (_textFlow ? _textFlow.configuration.inactiveSelectionFormat : null);
+		 }       
+		 
          /** @private - returns the selectionFormatState.  @see flashx.textLayout.edit.SelectionFormatState */
          tlf_internal function get selectionFormatState():String
          { return _selFormatState; }
@@ -584,11 +1041,17 @@ package flashx.textLayout.edit
          */
         public function selectAll() : void
         {
-            selectRange(0, int.MAX_VALUE);
+			if(subManager)
+				subManager.selectAll();
+			else
+			{
+				var lastSelectablePos:int = (_textFlow.textLength > 0) ? _textFlow.textLength - 1 : 0;
+				selectRange(0, lastSelectablePos);
+			}
         }
         
         /** 
-         *  @copy ISelectionManager#selectRange
+         * @copy ISelectionManager#selectRange
          * 
          * @includeExample examples\SelectionManager_selectRange.as -noswf
          * 
@@ -601,22 +1064,76 @@ package flashx.textLayout.edit
         public function selectRange(anchorPosition:int, activePosition:int) : void
         {
             flushPendingOperations();
+			
+			if(subManager)
+				subManager.selectRange(-1,-1);
             
             // anchor and active can be in any order
             // TODO: range check and clamp anchor,active
             if (anchorPosition != anchorMark.position || activePosition != activeMark.position)
             {   
                 clearSelectionShapes();
+				clearCellSelections();
+				_cellRange = null;
                     
-                internalSetSelection(_textFlow, anchorPosition, activePosition);
+                internalSetSelection(_textFlow, anchorPosition, activePosition, _pointFormat);
                 
                 // selection changed
-                selectionChanged();     
+                selectionChanged();
                 
                 allowOperationMerge = false;
             }
         }
-        
+		
+		/** 
+		 * @copy ISelectionManager#selectFirstPosition
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function selectFirstPosition():void
+		{
+			selectRange(0, 0);
+		}
+		
+		/** 
+		 * @copy ISelectionManager#selectLastPosition
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function selectLastPosition():void
+		{
+			selectRange(int.MAX_VALUE, int.MAX_VALUE);
+		}
+
+		/** 
+		 * @copy ISelectionManager#deselect
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function deselect():void
+		{
+			if (hasAnySelection())
+			{
+				clearSelectionShapes();
+				clearCellSelections();
+				addSelectionShapes();
+			}
+			selectRange(-1,-1);
+			_cellRange = null;
+		}
+
         private function internalSetSelection(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null) : void
         {
             _textFlow = root;
@@ -627,6 +1144,8 @@ package flashx.textLayout.edit
                 anchorPosition = -1;
                 activePosition = -1;
             }
+			else if(subManager)
+				subManager = null;
             
             var lastSelectablePos:int = (_textFlow.textLength > 0) ? _textFlow.textLength - 1 : 0;
             
@@ -645,7 +1164,8 @@ package flashx.textLayout.edit
         //  trace("Selection ", anchorMark, "to", activeMark.position);
         }       
         
-        /** Clear any active selections.
+        /** 
+		 * Clear any active selections.
          */
         private function clear(): void
         {
@@ -659,7 +1179,32 @@ package flashx.textLayout.edit
                 allowOperationMerge = false;
             }
         }
-        
+        /**
+		 * Clear any cell selections
+		 * */
+		private function clearCellSelections():void
+		{
+			var blocks:Vector.<TextFlowTableBlock>;
+			var block:TextFlowTableBlock;
+			var controller:ContainerController;
+			
+			if (_cellRange) {
+				blocks = _cellRange.table.getTableBlocksInRange(_cellRange.anchorCoordinates, _cellRange.activeCoordinates);
+				
+				for each (block in blocks) {
+					if (controller != block.controller) {
+						block.controller.clearSelectionShapes();
+					}
+					
+					controller = block.controller;
+				}
+				
+			}
+			if(block)
+				block.controller.clearSelectionShapes();
+			
+			//_cellRange = null;
+		}
         private function addSelectionShapes():void
         {
             if (_textFlow.flowComposer)
@@ -677,7 +1222,7 @@ package flashx.textLayout.edit
                     {
                         _textFlow.flowComposer.getControllerAt(containerIter++).addSelectionShapes(currentSelectionFormat, absoluteStart, absoluteEnd);
                     }
-                } 
+                }
             }
         }
         
@@ -693,22 +1238,39 @@ package flashx.textLayout.edit
                 }
             }
         }
-        
-        /** 
-         *  @copy ISelectionManager#refreshSelection()
-         * 
-         * @playerversion Flash 10
-         * @playerversion AIR 1.5
-         * @langversion 3.0
-        */
-        public function refreshSelection(): void
-        {
-            if (hasSelection())
-            {
-                clearSelectionShapes();
-                addSelectionShapes();
-            }
-        }
+		
+		/** 
+		 *  @copy ISelectionManager#refreshSelection()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function refreshSelection(): void
+		{
+			if (hasAnySelection())
+			{
+				clearSelectionShapes();
+				clearCellSelections();
+				addSelectionShapes();
+			}
+		}
+		
+		/** 
+		 *  @copy ISelectionManager#clearSelection()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function clearSelection(): void
+		{
+			if (hasAnySelection())
+			{
+				clearSelectionShapes();
+				clearCellSelections();
+			}
+		}
         
         /** Verifies that the selection is in a legal state. @private */
         CONFIG::debug public function debugCheckSelectionManager():int
@@ -745,7 +1307,12 @@ package flashx.textLayout.edit
                 _pointFormat = null;
             
             if (doDispatchEvent && _textFlow)
-                textFlow.dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
+			{
+				if(textFlow.parentElement && textFlow.parentElement.getTextFlow())
+					textFlow.parentElement.getTextFlow().dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
+				else
+					textFlow.dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
+			}
         }
 
         // TODO: this routine could be much more efficient - instead of iterating over all lines in the TextFlow it should iterate over 
@@ -771,11 +1338,14 @@ package flashx.textLayout.edit
             //get the nearest column so we can ignore lines which aren't in the column we're looking for.
             //if we don't do this, we won't be able to select across column boundaries.
             var nearestColIdx:int = locateNearestColumn(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
+
+			var prevLineBounds:Rectangle = null;
+			var previousLineIndex:int = -1;
+
+			/*
 			//For the table feature, we are trying to make sure if the current point is in the table and which cell it is in
-			var nearestCell:TableDataCellElement = locateNearestCell(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
+			var nearestCell:TableCellElement = locateNearestCell(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
             
-            var prevLineBounds:Rectangle = null;
-            var previousLineIndex:int = -1;
 			
 			if(nearestCell)
 			{
@@ -790,7 +1360,7 @@ package flashx.textLayout.edit
 					return cellPara.getAbsoluteStart() + cellPara.textLength - 1;
 				}
 			}
-            
+            */
             var lastLineIndexInColumn:int = -1;
             
             // Matching TextFlowLine and TextLine - they are not necessarily valid
@@ -845,6 +1415,7 @@ package flashx.textLayout.edit
                     //current line,. Otherwise, if the click's perpendicular coordinate is below the mid point between the current
                     //line or below it, then we want to use the line below (ie the previous line, but logically the one after the current)
                     var inPrevLine:Boolean = midPerpCoor != -1 && (isTTB ? perpCoor < midPerpCoor : perpCoor > midPerpCoor);
+					/*
 					if(rtline.paragraph.isInTable())
 					{
 						//if rtline is the last line of the cell and the isPrevLine is true, find the cell of the column in next row
@@ -852,10 +1423,10 @@ package flashx.textLayout.edit
 						if ( inPrevLine && testIndex != lastLineIndexInColumn )
 						{
 							var rtPara:ParagraphElement = rtline.paragraph;
-							var rtCell:TableDataCellElement = rtPara.getTableDataCellElement();
+							var rtCell:TableCellElement = rtPara.getParentCellElement();
 							//get the last element of the cell
 							var lastElement:FlowElement = rtCell.getLastLeaf();
-							var rtLastTbLine:TextFlowLine = lastElement.getParagraph().getTextBlock().lastLine.userData;
+							var rtLastTbLine:TextFlowLine = lastElement ? lastElement.getParagraph().getTextBlock().lastLine.userData : null;
 							if( rtline == rtLastTbLine )
 							{
 								//temproray codes, need to be updated when the column apis are ready
@@ -864,7 +1435,7 @@ package flashx.textLayout.edit
 								var nextRow:TableRowElement = rtRow.getNextSibling() as TableRowElement;
 								if ( nextRow && rtCell )
 								{
-									var nextCell:TableDataCellElement = nextRow.getChildAt(rtCell.colIndex) as TableDataCellElement;
+									var nextCell:TableCellElement = nextRow.getChildAt(rtCell.colIndex) as TableCellElement;
 									lineIndex = textFlow.flowComposer.findLineIndexAtPosition(nextCell.getFirstLeaf().getParagraph().getAbsoluteStart());
 								}
 							}
@@ -875,6 +1446,7 @@ package flashx.textLayout.edit
 							lineIndex = testIndex;
 					}
 					else
+					*/
                     	lineIndex = inPrevLine && testIndex != lastLineIndexInColumn ? testIndex+1 : testIndex;
 					break;
                 }
@@ -895,79 +1467,87 @@ package flashx.textLayout.edit
                 
             //Get a valid textLine -- check to make sure line is valid, regenerate if necessary, make sure it has correct container relative coordinates
             var textFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(lineIndex);
-            var textLine:TextLine = textFlowLine.getTextLine(true);
-            
-            // adjust localX,localY to be relative to the textLine.  
-            // Can't use localToGlobal/globalToLocal because textLine may not be on the display list due to virtualization
-            // we may need to bring this back if textline's can be rotated or placed by any mechanism other than a translation
-            // but then we'll need to provisionally place a virtualized TextLine in its parent container
-            localX -= textLine.x;
-            localY -= textLine.y;
-            /* var localPoint:Point = DisplayObject(controller.container).localToGlobal(new Point(localX,localY));
-            localPoint = textLine.globalToLocal(localPoint);
-            localX = localPoint.x;
-            localY = localPoint.y; */
-            
-            
-            var startOnNextLineIfNecessary:Boolean = false;
-            
-            var lastAtom:int = -1;
-            if (isDirectionRTL) {
-                lastAtom = textLine.atomCount - 1;
-            } else {
-                if ((textFlowLine.absoluteStart + textFlowLine.textLength) >= textFlowLine.paragraph.getAbsoluteStart() + textFlowLine.paragraph.textLength) {
-                    if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
-                } else {
-                    var lastLinePosInPar:int = textFlowLine.absoluteStart + textFlowLine.textLength - 1;
-                    var lastChar:String = textLine.textBlock.content.rawText.charAt(lastLinePosInPar);
-                    if (lastChar == " ") {
-                        if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
-                    } else {
-                        startOnNextLineIfNecessary = true;
-                        if (textLine.atomCount > 0) lastAtom = textLine.atomCount - 1;
-                    }
-                }
-            }
-            var lastAtomRect:Rectangle = (lastAtom > 0) ? textLine.getAtomBounds(lastAtom) : new Rectangle(0, 0, 0, 0);
-                        
-            if (!isTTB)
-            {
-                if (localX < 0)
-                    localX = 0;
-                else if (localX > (lastAtomRect.x + lastAtomRect.width))
-                {
-                    if (startOnNextLineIfNecessary) 
-                        return textFlowLine.absoluteStart + textFlowLine.textLength - 1;
-                    if (lastAtomRect.x + lastAtomRect.width > 0)
-                        localX = lastAtomRect.x + lastAtomRect.width;
-                }
-            }
-            else
-            {   
-                if (localY < 0) 
-                    localY = 0;
-                else if (localY > (lastAtomRect.y + lastAtomRect.height))
-                {
-                    if (startOnNextLineIfNecessary) 
-                        return textFlowLine.absoluteStart + textFlowLine.textLength - 1;    
-                    if (lastAtomRect.y + lastAtomRect.height > 0)
-                        localY = lastAtomRect.y + lastAtomRect.height;
-                }
-            }
-            
-			result = computeSelectionIndexInLine(textFlow, textLine, localX, localY);
+			if(textFlowLine is TextFlowTableBlock)
+			{
+				result = TextFlowTableBlock(textFlowLine).absoluteStart;
+			}
+			else
+			{
+				var textLine:TextLine = textFlowLine.getTextLine(true);
+				
+				// adjust localX,localY to be relative to the textLine.  
+				// Can't use localToGlobal/globalToLocal because textLine may not be on the display list due to virtualization
+				// we may need to bring this back if textline's can be rotated or placed by any mechanism other than a translation
+				// but then we'll need to provisionally place a virtualized TextLine in its parent container
+				localX -= textLine.x;
+				localY -= textLine.y;
+				/* var localPoint:Point = DisplayObject(controller.container).localToGlobal(new Point(localX,localY));
+				localPoint = textLine.globalToLocal(localPoint);
+				localX = localPoint.x;
+				localY = localPoint.y; */
+				
+				
+				var startOnNextLineIfNecessary:Boolean = false;
+				
+				var lastAtom:int = -1;
+				if (isDirectionRTL) {
+					lastAtom = textLine.atomCount - 1;
+				} else {
+					if ((textFlowLine.absoluteStart + textFlowLine.textLength) >= textFlowLine.paragraph.getAbsoluteStart() + textFlowLine.paragraph.textLength) {
+						if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
+					} else {
+						var lastLinePosInPar:int = textFlowLine.absoluteStart + textFlowLine.textLength - 1;
+						var lastChar:String = textLine.textBlock.content.rawText.charAt(lastLinePosInPar);
+						if (lastChar == " ") {
+							if (textLine.atomCount > 1) lastAtom = textLine.atomCount - 2;
+						} else {
+							startOnNextLineIfNecessary = true;
+							if (textLine.atomCount > 0) lastAtom = textLine.atomCount - 1;
+						}
+					}
+				}
+				var lastAtomRect:Rectangle = (lastAtom > 0) ? textLine.getAtomBounds(lastAtom) : new Rectangle(0, 0, 0, 0);
+				
+				if (!isTTB)
+				{
+					if (localX < 0)
+						localX = 0;
+					else if (localX > (lastAtomRect.x + lastAtomRect.width))
+					{
+						if (startOnNextLineIfNecessary) 
+							return textFlowLine.absoluteStart + textFlowLine.textLength - 1;
+						if (lastAtomRect.x + lastAtomRect.width > 0)
+							localX = lastAtomRect.x + lastAtomRect.width;
+					}
+				}
+				else
+				{   
+					if (localY < 0) 
+						localY = 0;
+					else if (localY > (lastAtomRect.y + lastAtomRect.height))
+					{
+						if (startOnNextLineIfNecessary) 
+							return textFlowLine.absoluteStart + textFlowLine.textLength - 1;    
+						if (lastAtomRect.y + lastAtomRect.height > 0)
+							localY = lastAtomRect.y + lastAtomRect.height;
+					}
+				}
+				
+				result = computeSelectionIndexInLine(textFlow, textLine, localX, localY);
+			}
+
             // trace("computeSelectionIndexInContainer:(",origX,origY,")",textFlow.flowComposer.getControllerIndex(controller).toString(),lineIndex.toString(),result.toString());
             return result != -1 ? result : firstCharVisible + length;   
         }
-		
-		static private function locateNearestCell(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):TableDataCellElement
+		/*
+		static private function locateNearestCell(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):TableCellElement
 		{
 			var cellIdx:int = 0;
 			//if we only have 1 column, no need to perform calculation...
 			var columnState:ColumnState = container.columnState;
 			
 			var isFound:Boolean = false;
-			var curCell:TableDataCellElement = null;
+			var curCell:TableCellElement = null;
 			
 			//we need to compare the current column to the nextColmn
 			while(cellIdx < columnState.cellCount - 1)
@@ -984,7 +1564,7 @@ package flashx.textLayout.edit
 			}
 			return isFound? curCell : null;
 		}
-        
+        */
         static private function locateNearestColumn(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):int
         {
             var colIdx:int = 0;
@@ -1141,9 +1721,8 @@ package flashx.textLayout.edit
             else  // Left to right case, right is "end" unicode
                 paraSelectionIdx = leanRight ? textLine.getAtomTextBlockEndIndex(elemIdx) : textLine.getAtomTextBlockBeginIndex(elemIdx);
 
-            //we again need to do some fixup here.  Unfortunately, we don't have the index into the paragraph until
-            
-            return rtline.paragraph.getAbsoluteStart() + paraSelectionIdx;
+			//we again need to do some fixup here.  Unfortunately, we don't have the index into the paragraph until
+            return rtline.paragraph.getTextBlockAbsoluteStart(textLine.textBlock) + paraSelectionIdx;
         }
         
         static private function checkForDisplayed(container:DisplayObject):Boolean
@@ -1164,6 +1743,142 @@ package flashx.textLayout.edit
             return false;   // not on the stage
 
         }
+		/** @private - find a controller and adjusts the x and y values of localPoint if necessary */
+		private static function findController(textFlow:TextFlow, target:Object, currentTarget:Object, localPoint:Point):ContainerController
+		{
+			var localX:Number = localPoint.x;
+			var localY:Number = localPoint.y;
+			var controller:ContainerController;
+			var containerPoint:Point; // scratch
+			
+			var globalPoint:Point = DisplayObject(target).localToGlobal(new Point(localX, localY));
+
+			for (var idx:int = 0; idx < textFlow.flowComposer.numControllers; idx++)
+			{
+				var testController:ContainerController = textFlow.flowComposer.getControllerAt(idx); 
+				if (testController.container == target || testController.container == currentTarget)
+				{
+					controller = testController;
+					break;
+				}
+			}
+			if (controller)
+			{   
+				if (target != controller.container)
+				{
+					containerPoint = DisplayObject(controller.container).globalToLocal(globalPoint);
+					localPoint.x = containerPoint.x;
+					localPoint.y = containerPoint.y;
+				}
+				return controller;         
+			} 
+			
+			//the point is someplace else on stage.  Map the target 
+			//to the textFlow.container.
+			CONFIG::debug { assert(textFlow.flowComposer && textFlow.flowComposer.numControllers,"findController: invalid textFlow"); }
+			
+			
+			
+			// result of the search
+			var controllerCandidate:ContainerController = null;
+			var candidateLocalX:Number;
+			var candidateLocalY:Number;
+			var relDistance:Number = Number.MAX_VALUE;
+			
+			for (var containerIndex:int = 0; containerIndex < textFlow.flowComposer.numControllers; containerIndex++)
+			{
+				var curContainerController:ContainerController = textFlow.flowComposer.getControllerAt(containerIndex);
+				
+				// displayed??
+				if (!checkForDisplayed(curContainerController.container as DisplayObject))
+					continue;
+				
+				// handle measured containers??
+				var bounds:Rectangle = curContainerController.getContentBounds();
+				var containerWidth:Number = isNaN(curContainerController.compositionWidth) ? curContainerController.getTotalPaddingLeft()+bounds.width : curContainerController.compositionWidth;
+				var containerHeight:Number = isNaN(curContainerController.compositionHeight) ? curContainerController.getTotalPaddingTop()+bounds.height : curContainerController.compositionHeight;
+				
+				containerPoint = DisplayObject(curContainerController.container).globalToLocal(globalPoint);
+				
+				// remove scrollRect effects for the distance test but add it back in for the result
+				var adjustX:Number = 0;
+				var adjustY:Number = 0;
+				
+				if (curContainerController.hasScrollRect)
+				{
+					containerPoint.x -= (adjustX = curContainerController.container.scrollRect.x);
+					containerPoint.y -= (adjustY = curContainerController.container.scrollRect.y);
+				}
+				
+				if ((containerPoint.x >= 0) && (containerPoint.x <= containerWidth) &&
+					(containerPoint.y >= 0) && (containerPoint.y <= containerHeight))
+				{
+					controllerCandidate = curContainerController;
+					candidateLocalX = containerPoint.x+adjustX;
+					candidateLocalY = containerPoint.y+adjustY;
+					break;
+				}
+				
+				// figure minimum distance of containerPoint to curContainerController - 8 cases
+				var relDistanceX:Number = 0;
+				var relDistanceY:Number = 0;
+				
+				if (containerPoint.x < 0)
+				{
+					relDistanceX = containerPoint.x;
+					if (containerPoint.y < 0)
+						relDistanceY = containerPoint.y;
+					else if (containerPoint.y > containerHeight)
+						relDistanceY = containerPoint.y-containerHeight;
+				}
+				else if (containerPoint.x > containerWidth)
+				{
+					relDistanceX = containerPoint.x-containerWidth;
+					if (containerPoint.y < 0)
+						relDistanceY = containerPoint.y;
+					else if (containerPoint.y > containerHeight)
+						relDistanceY = containerPoint.y-containerHeight;
+				}
+				else if (containerPoint.y < 0)
+					relDistanceY = -containerPoint.y;
+				else
+					relDistanceY = containerPoint.y-containerHeight;
+				var tempDist:Number = relDistanceX*relDistanceX + relDistanceY*relDistanceY;    // could do sqrt but why bother - there is no Math.hypot function
+				if (tempDist <= relDistance)
+				{
+					relDistance = tempDist;
+					controllerCandidate = curContainerController;
+					candidateLocalX = containerPoint.x+adjustX;
+					candidateLocalY = containerPoint.y+adjustY;
+				}
+			}
+			localPoint.x = candidateLocalX;
+			localPoint.y = candidateLocalY;
+			return controllerCandidate;
+
+		}
+		/** @private - given a target and location compute the CellCoordinates */
+		static tlf_internal function computeCellCoordinates(textFlow:TextFlow, target:Object, currentTarget:Object, localX:Number, localY:Number):CellCoordinates
+		{
+			var rslt:CellCoordinates;
+			var containerPoint:Point; // scratch
+			
+
+			if (target is TextLine)
+				return null;
+			if(target is CellContainer)
+			{
+				var cell:TableCellElement = (target as CellContainer).element;
+				return new CellCoordinates(cell.rowIndex, cell.colIndex, cell.getTable());
+			}
+			var localPoint:Point = new Point(localX, localY);
+			var controller:ContainerController = findController(textFlow, target, currentTarget, localPoint);
+			if(!controller)
+				return null;
+			
+			return controller.findCellAtPosition(localPoint);
+		}
+
         /** @private - given a target and location compute the selectionIndex */
         static tlf_internal function computeSelectionIndex(textFlow:TextFlow, target:Object, currentTarget:Object, localX:Number,localY:Number):int
         {           
@@ -1196,112 +1911,9 @@ package flashx.textLayout.edit
                 rslt = computeSelectionIndexInLine(textFlow, TextLine(target), localX, localY);
             else
             {
-                var controller:ContainerController;
-                for (var idx:int = 0; idx < textFlow.flowComposer.numControllers; idx++)
-                {
-                    var testController:ContainerController = textFlow.flowComposer.getControllerAt(idx); 
-                    if (testController.container == target || testController.container == currentTarget)
-                    {
-                        controller = testController;
-                        break;
-                    }
-                }
-                if (controller)
-                {   
-                    if (target != controller.container)
-                    {
-                        containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
-                        containerPoint = DisplayObject(controller.container).globalToLocal(containerPoint);
-                        localX = containerPoint.x;
-                        localY = containerPoint.y;
-                    }
-                    rslt = computeSelectionIndexInContainer(textFlow, controller, localX, localY);          
-                } 
-                else 
-                {
-                    //the point is someplace else on stage.  Map the target 
-                    //to the textFlow.container.
-                    CONFIG::debug { assert(textFlow.flowComposer && textFlow.flowComposer.numControllers,"computeSelectionIndex: invalid textFlow"); }
-                    
-                    
-                    // result of the search
-                    var controllerCandidate:ContainerController = null;
-                    var candidateLocalX:Number;
-                    var candidateLocalY:Number;
-                    var relDistance:Number = Number.MAX_VALUE;
-                    
-                    for (var containerIndex:int = 0; containerIndex < textFlow.flowComposer.numControllers; containerIndex++)
-                    {
-                        var curContainerController:ContainerController = textFlow.flowComposer.getControllerAt(containerIndex);
-                        
-                        // displayed??
-                        if (!checkForDisplayed(curContainerController.container as DisplayObject))
-                            continue;
-
-                        // handle measured containers??
-                        var bounds:Rectangle = curContainerController.getContentBounds();
-                        var containerWidth:Number = isNaN(curContainerController.compositionWidth) ? curContainerController.getTotalPaddingLeft()+bounds.width : curContainerController.compositionWidth;
-                        var containerHeight:Number = isNaN(curContainerController.compositionHeight) ? curContainerController.getTotalPaddingTop()+bounds.height : curContainerController.compositionHeight;
-                        
-                        containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
-                        containerPoint = DisplayObject(curContainerController.container).globalToLocal(containerPoint);
-                        
-                        // remove scrollRect effects for the distance test but add it back in for the result
-                        var adjustX:Number = 0;
-                        var adjustY:Number = 0;
-                        
-                        if (curContainerController.hasScrollRect)
-                        {
-                            containerPoint.x -= (adjustX = curContainerController.container.scrollRect.x);
-                            containerPoint.y -= (adjustY = curContainerController.container.scrollRect.y);
-                        }
-                        
-                        if ((containerPoint.x >= 0) && (containerPoint.x <= containerWidth) &&
-                            (containerPoint.y >= 0) && (containerPoint.y <= containerHeight))
-                        {
-                            controllerCandidate = curContainerController;
-                            candidateLocalX = containerPoint.x+adjustX;
-                            candidateLocalY = containerPoint.y+adjustY;
-                            break;
-                        }
-                        
-                        // figure minimum distance of containerPoint to curContainerController - 8 cases
-                        var relDistanceX:Number = 0;
-                        var relDistanceY:Number = 0;
-
-                        if (containerPoint.x < 0)
-                        {
-                            relDistanceX = containerPoint.x;
-                            if (containerPoint.y < 0)
-                                relDistanceY = containerPoint.y;
-                            else if (containerPoint.y > containerHeight)
-                                relDistanceY = containerPoint.y-containerHeight;
-                        }
-                        else if (containerPoint.x > containerWidth)
-                        {
-                            relDistanceX = containerPoint.x-containerWidth;
-                            if (containerPoint.y < 0)
-                                relDistanceY = containerPoint.y;
-                            else if (containerPoint.y > containerHeight)
-                                relDistanceY = containerPoint.y-containerHeight;
-                        }
-                        else if (containerPoint.y < 0)
-                            relDistanceY = -containerPoint.y;
-                        else
-                            relDistanceY = containerPoint.y-containerHeight;
-                        var tempDist:Number = relDistanceX*relDistanceX + relDistanceY*relDistanceY;    // could do sqrt but why bother - there is no Math.hypot function
-                        if (tempDist <= relDistance)
-                        {
-                            relDistance = tempDist;
-                            controllerCandidate = curContainerController;
-                            candidateLocalX = containerPoint.x+adjustX;
-                            candidateLocalY = containerPoint.y+adjustY;
-                        }
-                    }
-
-
-                    rslt = controllerCandidate ? computeSelectionIndexInContainer(textFlow, controllerCandidate, candidateLocalX, candidateLocalY) : -1;
-                }
+				var localPoint:Point = new Point(localX,localY);
+                var controller:ContainerController = findController(textFlow, target, currentTarget, localPoint);
+				rslt = controller ? computeSelectionIndexInContainer(textFlow, controller, localPoint.x, localPoint.y) : -1;
             }
             
             if (rslt >= textFlow.textLength)
@@ -1339,7 +1951,50 @@ package flashx.textLayout.edit
          */ 
         public function mouseDownHandler(event:MouseEvent):void
         {
-            handleMouseEventForSelection(event, event.shiftKey);
+			if(subManager)
+				subManager.selectRange(-1,-1);
+			
+			var cell:TableCellElement = _textFlow.parentElement as TableCellElement;
+			var coords:CellCoordinates;
+			if(!cell)
+				coords = computeCellCoordinates(textFlow,event.target,event.currentTarget,event.localX, event.localY);
+			if(cell || coords)
+			{
+				if(coords)
+					cell = currentTable.findCell(coords);
+				
+				superManager = cell.getTextFlow().interactionManager;
+				if(event.shiftKey && cell.getTable() == superManager.currentTable)
+				{
+					// expand cell selection if applicable
+					coords = new CellCoordinates(cell.rowIndex,cell.colIndex);
+					if(
+						!CellCoordinates.areEqual(coords,superManager.anchorCellPosition) ||
+						superManager.activeCellPosition.isValid()
+					){
+						superManager.selectCellRange(superManager.anchorCellPosition,coords);
+						superManager.subManager = null;
+						allowOperationMerge = false;
+						event.stopPropagation();
+						return;
+					}
+				}
+				if(superManager == this)
+				{
+					if(cell.textFlow.interactionManager)
+					{
+						cell.textFlow.interactionManager.mouseDownHandler(event);
+					}
+					return;
+				}
+				superManager.currentTable = cell.getTable();
+				superManager.deselect();
+				//superManager.setSelectionState(new SelectionState(superManager.textFlow,-1,-1) );
+				superManager.anchorCellPosition.column = cell.colIndex;
+				superManager.anchorCellPosition.row = cell.rowIndex;
+				superManager.subManager = this;
+			}
+            handleMouseEventForSelection(event, event.shiftKey, cell != null);
         }
         
         /**
@@ -1348,17 +2003,56 @@ package flashx.textLayout.edit
          * @playerversion AIR 1.5
          * @langversion 3.0
          */ 
-        public function mouseMoveHandler(event:MouseEvent):void
-        {
+        public function mouseMoveHandler(event:MouseEvent):void {
             var wmode:String = textFlow.computedFormat.blockProgression;            
-            if (wmode != BlockProgression.RL) 
-                setMouseCursor(MouseCursor.IBEAM);          
+			
+			if (wmode != BlockProgression.RL) {
+                setMouseCursor(MouseCursor.IBEAM);
+			}
+			
+			
             if (event.buttonDown)
-                handleMouseEventForSelection(event, true);
+			{
+				var cell:TableCellElement = _textFlow.parentElement as TableCellElement;
+				
+				// if the event is owned by a cell, we need to check if the mouse is now above another cell to select a cell range.
+				if (cell) {
+					
+					do {
+						var cellCoords:CellCoordinates = new CellCoordinates(cell.rowIndex, cell.colIndex, cell.getTable());
+						var coords:CellCoordinates = computeCellCoordinates(cell.getTextFlow(), event.target, event.currentTarget, event.localX, event.localY);
+						if(!coords)
+							break;
+						if(CellCoordinates.areEqual(cellCoords, coords) &&
+							(!superManager.activeCellPosition.isValid() || CellCoordinates.areEqual(coords, superManager.activeCellPosition))
+						)
+							break;
+						if(coords.table != cellCoords.table)
+							break;
+						
+						superManager = cell.getTextFlow().interactionManager;
+						if(
+							!CellCoordinates.areEqual(coords, superManager.activeCellPosition)
+						){
+							allowOperationMerge = false;
+							superManager.selectCellRange(superManager.anchorCellPosition, coords);
+							event.stopPropagation();
+							return;
+						}
+
+						
+					}while(0);
+				}
+				if(superManager && superManager.getCellRange())
+					return;
+				
+				handleMouseEventForSelection(event, true, _textFlow.parentElement != null);
+
+			}
         }
         
         /** @private */
-        tlf_internal function handleMouseEventForSelection(event:MouseEvent, allowExtend:Boolean):void
+        tlf_internal function handleMouseEventForSelection(event:MouseEvent, allowExtend:Boolean,stopPropogate:Boolean=false):void
         {
             var startSelectionActive:Boolean = hasSelection();
             
@@ -1371,6 +2065,8 @@ package flashx.textLayout.edit
                     addSelectionShapes();
             }       
             allowOperationMerge = false;
+			if(stopPropogate)
+				event.stopPropagation();
         }
         
         /** 
@@ -1479,10 +2175,60 @@ package flashx.textLayout.edit
         {
             _mouseOverSelectionArea = true;
             var wmode:String = textFlow.computedFormat.blockProgression;
-            if (wmode != BlockProgression.RL) 
-                setMouseCursor(MouseCursor.IBEAM);  
-            else 
-                setMouseCursor(MouseCursor.AUTO);                               
+			
+            if (wmode != BlockProgression.RL) {
+				var cell:TableCellElement = _textFlow.parentElement as TableCellElement;
+				
+				// set the cursor if around the edge of the table
+				if (cell) {
+					var leftEdge:int = 5;
+					var topEdge:int = 5;
+					var globalPoint:Point = new Point(event.stageX, event.stageY);
+					var cellContainer:CellContainer = event.currentTarget as CellContainer;
+					var point:Point;
+					
+					if (cellContainer) {
+						var cellContainerPoint:Point = cellContainer.localToGlobal(new Point);
+						point = globalPoint.subtract(cellContainerPoint);
+					}
+					if(useTableSelectionCursors)
+					{
+						// set cursor for row, table or column
+						if (cell.colIndex==0 && point.x<leftEdge && point.y>topEdge)
+						{
+							event.stopPropagation();
+							event.stopImmediatePropagation();
+							setMouseCursor(SelectTableRow);
+						}
+						else if (cell.rowIndex==0 && cell.colIndex==0 &&
+							point.x<leftEdge && point.y<topEdge)
+						{
+							event.stopPropagation();
+							event.stopImmediatePropagation();
+							setMouseCursor(SelectTable);
+						}
+						else if (cell.rowIndex==0 && point.x>leftEdge && point.y<topEdge)
+						{
+							event.stopPropagation();
+							event.stopImmediatePropagation();
+							setMouseCursor(SelectTableColumn);
+						}
+						else {
+							setMouseCursor(MouseCursor.IBEAM);
+						}
+						
+					}
+					else {
+						setMouseCursor(MouseCursor.IBEAM);
+					}
+				}
+				else {
+                	setMouseCursor(MouseCursor.IBEAM);
+				}
+			}
+            else {
+                setMouseCursor(MouseCursor.AUTO);
+			}
         }
 
         /** 
@@ -1873,6 +2619,9 @@ package flashx.textLayout.edit
             }
             else if (event.keyCode == Keyboard.ESCAPE)
                 handleKeyEvent(event);
+			if(_textFlow.parentElement)
+				event.stopPropagation();
+			
         }
 
         /** 
@@ -2098,9 +2847,26 @@ package flashx.textLayout.edit
         {
             var idx:int = marks.indexOf(mark);
             if (idx != -1)
-                marks.splice(idx,idx+1);
+                marks.splice(idx,1);
         }
-        
+
+		private var cellMarks:Array = [];
+		
+		/** @private */
+		tlf_internal function createCellMark():CellCoordinates
+		{
+			var mark:CellCoordinates = new CellCoordinates(-1,-1);
+			cellMarks.push(mark);
+			return mark;
+		}
+		/** @private */
+		tlf_internal function removeCellMark(mark:CellCoordinates):void
+		{
+			var idx:int = cellMarks.indexOf(mark);
+			if (idx != -1)
+				marks.splice(idx,1);
+		}
+
         /** 
          * @copy ISelectionManager#notifyInsertOrDelete()
          * 
@@ -2126,5 +2892,138 @@ package flashx.textLayout.edit
                 }
             }
         }
+
+		/**
+		 * The ISelectionManager object used to for cell selections nested within the TextFlow managed by this ISelectionManager.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 
+		public function get subManager():ISelectionManager
+		{
+			return _subManager;
+		}
+		public function set subManager(value:ISelectionManager):void
+		{
+			if(_subManager)
+				_subManager.selectRange(-1,-1);
+			_subManager = value;
+		}
+		/**
+		 * The ISelectionManager object used to manage the parent TextFlow of this ISelectionManager (i.e. for cell ISelectionManagers).
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 
+
+		public function get superManager():ISelectionManager
+		{
+			return _superManager;
+		}
+
+		public function set superManager(value:ISelectionManager):void
+		{
+			_superManager = value;
+		}
+
+		/** Anchor point of the current cell selection, as coordinates within the table. */
+		public function get anchorCellPosition():CellCoordinates
+		{
+			return _anchorCellPosition;
+		}
+		public function set anchorCellPosition(value:CellCoordinates):void
+		{
+			_anchorCellPosition = value;
+		}
+
+		/** Active end of the current cell selection, as coordinates within the table. */
+		public function get activeCellPosition():CellCoordinates
+		{
+			return _activeCellPosition;
+		}
+		public function set activeCellPosition(value:CellCoordinates):void
+		{
+			_activeCellPosition = value;
+		}
+		
+		public var selectTableCursorPoints:Vector.<Number> = new <Number>[1,3, 11,3, 11,0, 12,0, 16,4, 12,8, 11,8, 11,5, 1,5, 1,3];
+		public var selectTableCursorDrawCommands:Vector.<int> = new <int>[1,2,2,2,2,2,2,2,2,2];
+		
+		
+		/**
+		 * Create a select table cursor
+		 */
+		public function createSelectTableCursor():MouseCursorData {
+			var cursorData:Vector.<BitmapData> = new Vector.<BitmapData>();
+			var cursorShape:Shape = new Shape();
+			cursorShape.graphics.beginFill(0x0, 1);
+			cursorShape.graphics.lineStyle(0, 0xFFFFFF, 1, true);
+			cursorShape.graphics.drawPath( selectTableCursorDrawCommands, selectTableCursorPoints);
+			cursorShape.graphics.endFill();
+			var transformer:Matrix = new Matrix();
+			var cursorFrame:BitmapData = new BitmapData(32, 32, true, 0);
+			var angle:int = 8;
+			var rotation:Number = 0.785398163;
+			transformer.translate(-angle,-angle);
+			transformer.rotate(rotation);
+			transformer.translate(angle, angle);
+			cursorFrame.draw(cursorShape, transformer);
+			cursorData.push(cursorFrame);
+			var mouseCursorData:MouseCursorData = new MouseCursorData();
+			mouseCursorData.data = cursorData;
+			mouseCursorData.hotSpot = new Point(16, 10);
+			mouseCursorData.frameRate = 1;
+			return mouseCursorData;
+		}
+		
+		/**
+		 * Create a select row cursor
+		 */
+		public function createSelectTableRowCursor():MouseCursorData {
+			var cursorData:Vector.<BitmapData> = new Vector.<BitmapData>();
+			var cursorShape:Shape = new Shape();
+			cursorShape.graphics.beginFill(0x0, 1);
+			cursorShape.graphics.lineStyle(0, 0xFFFFFF, 1, true);
+			cursorShape.graphics.drawPath(selectTableCursorDrawCommands, selectTableCursorPoints);
+			cursorShape.graphics.endFill();
+			var transformer:Matrix = new Matrix();
+			var cursorFrame:BitmapData = new BitmapData(32, 32, true, 0);
+			cursorFrame.draw(cursorShape, transformer);
+			cursorData.push(cursorFrame);
+			var mouseCursorData:MouseCursorData = new MouseCursorData();
+			mouseCursorData.data = cursorData;
+			mouseCursorData.hotSpot = new Point(16, 4);
+			mouseCursorData.frameRate = 1;
+			return mouseCursorData;
+		}
+		
+		/**
+		 * Create a select table column cursor
+		 */
+		public function createSelectTableColumnCursor():MouseCursorData {
+			var cursorData:Vector.<BitmapData> = new Vector.<BitmapData>();
+			var cursorShape:Shape = new Shape();
+			cursorShape.graphics.beginFill(0x0, 1 );
+			cursorShape.graphics.lineStyle(0, 0xFFFFFF, 1, true );
+			cursorShape.graphics.drawPath(selectTableCursorDrawCommands, selectTableCursorPoints);
+			cursorShape.graphics.endFill();
+			var transformer:Matrix = new Matrix();
+			var cursorFrame:BitmapData = new BitmapData(32, 32, true, 0);
+			var angle:int = 16;
+			var rotation:Number = 0.785398163;
+			transformer.translate(-angle,-angle);
+			transformer.rotate(rotation * 2);
+			transformer.translate(angle, angle);
+			cursorFrame.draw(cursorShape, transformer);
+			cursorData.push(cursorFrame);
+			var mouseCursorData:MouseCursorData = new MouseCursorData();
+			mouseCursorData.data = cursorData;
+			mouseCursorData.hotSpot = new Point(28, 16);
+			mouseCursorData.frameRate = 1;
+			return mouseCursorData;
+		}
+
     }
 }

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/SelectionState.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/SelectionState.as b/textLayout/src/flashx/textLayout/edit/SelectionState.as
index 4d500e4..379f023 100644
--- a/textLayout/src/flashx/textLayout/edit/SelectionState.as
+++ b/textLayout/src/flashx/textLayout/edit/SelectionState.as
@@ -27,6 +27,8 @@ package flashx.textLayout.edit
 	use namespace tlf_internal;
 	
 	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.elements.CellRange;
+
 	use namespace tlf_internal;
 	/**
 	 * The SelectionState class represents a selection in a text flow.  
@@ -49,6 +51,8 @@ package flashx.textLayout.edit
 		/** Format that are associated with the caret position & will be applied to inserted text */
 		private var _pointFormat:ITextLayoutFormat;
 		
+		private var _cellRange:CellRange;
+		
 		private var _selectionManagerOperationState:Boolean;
 
 		/** 
@@ -72,11 +76,12 @@ package flashx.textLayout.edit
 		 * @playerversion AIR 1.5
  	 	 * @langversion 3.0
 		 */		
-		public function SelectionState(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null)
+		public function SelectionState(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null,cellRange:CellRange = null)
 		{
 			super(root, anchorPosition, activePosition);
 			if (format)
 				_pointFormat = format;
+			_cellRange = cellRange;
 		}
 		
 		/** 
@@ -126,5 +131,20 @@ package flashx.textLayout.edit
 		/** @private */
 		tlf_internal function clone():SelectionState
 		{ return new SelectionState(textFlow,anchorPosition,activePosition,pointFormat); }
+
+		/** Range of table cells in selection (null if no cells selected)*/
+		public function get cellRange():CellRange
+		{
+			return _cellRange;
+		}
+
+		/**
+		 * @private
+		 */
+		public function set cellRange(value:CellRange):void
+		{
+			_cellRange = value;
+		}
+
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as b/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
index 347aa53..235cd08 100644
--- a/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
+++ b/textLayout/src/flashx/textLayout/edit/TextFlowEdit.as
@@ -1114,10 +1114,14 @@ package flashx.textLayout.edit
 		/** if parent is a singleton element, deletes it, then repeats deletion of singletons up the parent chain.  Used after paragraph merge. */
 		tlf_internal static function removeEmptyParentChain(parent:FlowGroupElement):IMemento
 		{
+			if(parent is ParagraphElement)
+				ParagraphElement(parent).removeEmptyTerminator();
 			var mementoList:MementoList = new MementoList(parent.getTextFlow());
 			while(parent && (parent.numChildren == 0))
 			{
 				var grandParent:FlowGroupElement = parent.parent;
+				if(grandParent is ParagraphElement)
+					ParagraphElement(grandParent).removeEmptyTerminator();
 				if(grandParent)
 				{
 					var parentIdx:int = grandParent.getChildIndex(parent);

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/BackgroundManager.as b/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
index adee363..b29accf 100644
--- a/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
+++ b/textLayout/src/flashx/textLayout/elements/BackgroundManager.as
@@ -32,6 +32,7 @@ package flashx.textLayout.elements
 	import flashx.textLayout.compose.ParcelList;
 	import flashx.textLayout.compose.StandardFlowComposer;
 	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.compose.TextFlowTableBlock;
 	import flashx.textLayout.container.ContainerController;
 	import flashx.textLayout.container.TextContainerManager;
 	import flashx.textLayout.debug.assert;
@@ -45,7 +46,6 @@ package flashx.textLayout.elements
 	
 	use namespace tlf_internal;
 	
-	[ExcludeClass]
 	/** @private Manages bounds calculation and rendering of backgroundColor character format. */
 	public class BackgroundManager
 	{
@@ -109,6 +109,34 @@ package flashx.textLayout.elements
 			}
 		}
 		
+		public static function collectTableBlock(_textFlow:TextFlow,block:TextFlowTableBlock,controller:ContainerController):void
+		{
+			// add block rect for each cell in table block
+			
+			var bb:BackgroundManager;
+			var r:Rectangle;
+			var composer:IFlowComposer;
+
+			var cells:Vector.<TableCellElement> = block.getTableCells();
+			for each(var cell:TableCellElement in cells){
+				if(BackgroundManager.hasBorderOrBackground(cell))
+				{
+					if(!_textFlow.backgroundManager)
+						_textFlow.getBackgroundManager();
+					bb = _textFlow.backgroundManager;
+
+					bb.addBlockElement(cell);
+
+					var row:TableRowElement = cell.getRow();
+					r = new Rectangle(cell.x, cell.y + block.y, cell.width, row.composedHeight);
+					bb.addBlockRect(cell, r, controller);
+
+				}
+			}
+			block.y;
+			
+		}
+		
 		public static function collectBlock(_textFlow:TextFlow, elem:FlowGroupElement, _parcelList:ParcelList = null, tableComposeNotFromBeginning:Boolean = false, tableOutOfView:Boolean = false):void
 		{
 			var bb:BackgroundManager;
@@ -118,61 +146,8 @@ package flashx.textLayout.elements
 
 			if(elem)
 			{
-				//The height of TableDataCellElement can only be identified after all the cells in the row are composed.
-				//So, pick it out of the common process 
-				if(elem is TableRowElement)
-				{
-					var tabRow:TableRowElement = elem as TableRowElement;
-					//for table cells
-					var cell:TableDataCellElement;
-					var cellParcel:Parcel;
-					for(var cIdx:Number = 0; cIdx < elem.numChildren; cIdx++)
-					{
-						cell = elem.getChildAt(cIdx) as TableDataCellElement;
-						if(BackgroundManager.hasBorderOrBackground(cell) || BackgroundManager.hasBorderOrBackground(elem))
-						{
-							//mark the paragraph that has border or background
-							if(!_textFlow.backgroundManager)
-								_textFlow.getBackgroundManager();
-							bb = _textFlow.backgroundManager;
-							
-							//BackgroundManager should not be null here
-							CONFIG::debug { assert(_textFlow.backgroundManager != null ,"BackgroundManager should not be null"); }
-							
-							bb.addBlockElement(cell);
-							
-							cellParcel = _parcelList.getParcelAt(cell.parcelIndex);
-							if(cellParcel)
-							{
-								r = new Rectangle(cell.x, cell.y, cell.width, tabRow.height);
-								bb.addBlockRect(cell, r, cellParcel.controller);
-							}
-						}
-					}
-					
-					//for table rows
-					/*if(BackgroundManager.hasBorderOrBackground(elem))
-					{
-						//mark the paragraph that has border or background
-						if(!_textFlow.backgroundManager)
-							_textFlow.getBackgroundManager();
-						bb = _textFlow.backgroundManager;
-						
-						//BackgroundManager should not be null here
-						CONFIG::debug { assert(_textFlow.backgroundManager != null ,"BackgroundManager should not be null"); }
-						
-						bb.addBlockElement(elem);
-						
-						var parentTable:TableElement = elem.parent as TableElement;
-						var rowParcel:Parcel = _parcelList.getParcelAt(tabRow.parcelIndex);
-						if(parentTable && rowParcel){
-							r = new Rectangle(parentTable.x + rowParcel.x, tabRow.y + rowParcel.y, parentTable.computedWidth, tabRow.height);
-							bb.addBlockRect(elem, r, rowParcel.controller);
-						}
-					}*/
-				}
-				//for the other elements
-				else if(BackgroundManager.hasBorderOrBackground(elem))
+
+				if(BackgroundManager.hasBorderOrBackground(elem))
 				{
 					//mark the paragraph that has border or background
 					if(!_textFlow.backgroundManager)
@@ -189,61 +164,9 @@ package flashx.textLayout.elements
 					{
 						if(elem is TableElement)
 						{
+							// Do we need to do anything for table elements? Not sure...
 							var tab:TableElement = elem as TableElement;
-							var parcel:Parcel;
-							if(tab.numAcrossParcels == 0)
-							{
-								r = new Rectangle();
-								parcel = _parcelList.getParcelAt(tab.originParcelIndex);
-								if(parcel)
-								{
-									if(tableComposeNotFromBeginning)
-									{
-										r.x = parcel.x;
-										r.y = parcel.y;
-									}
-									else
-									{
-										r.x = tab.x;
-										r.y = tab.y;
-									}
-									r.width = tab.computedWidth;
-									r.height = tab.height;
-									bb.addBlockRect(elem, r, parcel.controller);
-								}
-							}else
-							{
-								for(var tIdx:Number = 0; tIdx <= tab.numAcrossParcels; tIdx++)
-								{
-									r = new Rectangle();
-									parcel = _parcelList.getParcelAt(tab.originParcelIndex + tIdx);
-									if(parcel)
-									{
-										if(tIdx == 0 && !tableComposeNotFromBeginning)
-										{
-											r.x = tab.x;
-											r.y = tab.y;
-											r.width = tab.computedWidth;
-											r.height = tab.heightArray[tIdx];
-											bb.addBlockRect(elem, r, parcel.controller, BackgroundManager.BOTTOM_EXCLUDED);
-										}else if (tIdx == tab.numAcrossParcels && !tableOutOfView)
-										{
-											r.x = parcel.x + tab.computedFormat.marginLeft;
-											r.y = parcel.y;
-											r.width = tab.computedWidth;
-											r.height = tab.totalRowDepth;
-											bb.addBlockRect(elem, r, parcel.controller, BackgroundManager.TOP_EXCLUDED);
-										}else
-										{
-											r.x = parcel.x + tab.computedFormat.marginLeft;
-											r.y = parcel.y;
-											r.width = tab.computedWidth;
-											r.height = tab.heightArray[tIdx];
-											bb.addBlockRect(elem, r, parcel.controller, BackgroundManager.TOP_AND_BOTTOM_EXCLUDED);
-										}
-									}
-								}
-							}
+
 						}
 						else //for elements like ParagraphElement, DivElement, ListItemElement, ListElement, TextFlow
 						{	
@@ -461,8 +384,9 @@ package flashx.textLayout.elements
 					//draw background
 					if(style.backgroundColor != BackgroundColor.TRANSPARENT)
 					{
-						g.lineStyle(0, style.backgroundColor, style.backgroundAlpha, true);
-						g.beginFill(style.backgroundColor);
+						// The value 0 indicates hairline thickness; 
+						g.lineStyle(NaN, style.backgroundColor, style.backgroundAlpha, true);
+						g.beginFill(style.backgroundColor, style.backgroundAlpha);
 						g.drawRect(rec.x, rec.y, rec.width, rec.height);
 						g.endFill();
 					}
@@ -577,8 +501,9 @@ package flashx.textLayout.elements
 							//draw background
 							if(style.backgroundColor != BackgroundColor.TRANSPARENT)
 							{
-								g.lineStyle(0, style.backgroundColor, style.backgroundAlpha, true);
-								g.beginFill(style.backgroundColor);
+								// The value 0 indicates hairline thickness; NaN removes line
+								g.lineStyle(NaN, style.backgroundColor, style.backgroundAlpha, true);
+								g.beginFill(style.backgroundColor, style.backgroundAlpha);
 								g.drawRect(rec.x, rec.y, rec.width, rec.height);
 								g.endFill();
 							}
@@ -618,7 +543,11 @@ package flashx.textLayout.elements
 				//draw background for span	
 				for(var childIdx:int = 0; childIdx<controller.textLines.length; ++childIdx)
 				{
-					var tl:TextLine = controller.textLines[childIdx];
+					var line:* = controller.textLines[childIdx];
+					// skip TextFlowTableBlocks
+					if(!(line is TextLine))
+						continue;
+					var tl:TextLine = line;
 					var entry:Array = _lineDict[tl];
 		
 					if (entry)

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/CellContainer.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/CellContainer.as b/textLayout/src/flashx/textLayout/elements/CellContainer.as
index 336da5a..256c495 100644
--- a/textLayout/src/flashx/textLayout/elements/CellContainer.as
+++ b/textLayout/src/flashx/textLayout/elements/CellContainer.as
@@ -20,13 +20,37 @@ package flashx.textLayout.elements
 {
 	import flash.display.Sprite;
 	
-	public class CellContainer extends Sprite
+	//import mx.core.IIMESupport;
+	
+	public class CellContainer extends Sprite// implements IIMESupport
 	{
-		public var userData:Object=null;
+		private var _imeMode:String;
+		private var _enableIME:Boolean;
+		public var element:TableCellElement;
+
+		public function CellContainer(imeEnabled:Boolean = true)
+		{
+			_enableIME = imeEnabled;
+		}
+		
+		public function get enableIME():Boolean
+		{
+			return false;
+		}
+		
+		public function set enableIME(value:Boolean):void
+		{
+			_enableIME = value;
+		}
+		
+		public function get imeMode():String
+		{
+			return _imeMode;
+		}
 		
-		public function CellContainer()
+		public function set imeMode(value:String):void
 		{
-			super();
+			_imeMode = value;
 		}
 	}
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/FlowElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/FlowElement.as b/textLayout/src/flashx/textLayout/elements/FlowElement.as
index 6ef5053..12ba288 100644
--- a/textLayout/src/flashx/textLayout/elements/FlowElement.as
+++ b/textLayout/src/flashx/textLayout/elements/FlowElement.as
@@ -805,6 +805,14 @@ package flashx.textLayout.elements
 		{ setStyle(styleProp,undefined); }
 		
 		/**
+		 * Called when an element is removed. Used for container elements to run any clean up code. 
+		 **/
+		tlf_internal function removed():void
+		{
+			// override in sub classes
+		}
+		
+		/**
 		 * Called whenever the model is modified.  Updates the TextFlow and notifies the selection manager - if it is set.
 		 * This method has to be called while the element is still in the flow
 		 * @param changeType - type of change
@@ -1024,6 +1032,24 @@ package flashx.textLayout.elements
 		}
 		
 		
+		public function isInTable():Boolean
+		{
+			var tf:TextFlow = getTextFlow();
+			return tf && tf.parentElement && tf.parentElement is TableCellElement;
+		}
+		
+		public function getParentCellElement():TableCellElement
+		{
+			var tf:TextFlow = getTextFlow();
+			
+			if(!tf)
+				return null;
+			if(tf.parentElement && tf.parentElement is TableCellElement)
+				return tf.parentElement as TableCellElement;
+			return null;
+		}
+
+		
 		/** 
 		 * Returns the FlowElement object that contains this FlowElement object, if this element is contained within 
 		 * an element of a particular type. 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as b/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
index b02a22d..62567dd 100644
--- a/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
+++ b/textLayout/src/flashx/textLayout/elements/FlowGroupElement.as
@@ -582,7 +582,7 @@ package flashx.textLayout.elements
 		}
 		
 		/** @private */
-		tlf_internal function createContentAsGroup():GroupElement
+		tlf_internal function createContentAsGroup(pos:int=0):GroupElement
 		{
 			CONFIG::debug { assert(false,"invalid call to createContentAsGroup"); }
 			return null;
@@ -626,7 +626,7 @@ package flashx.textLayout.elements
 		 */
 		tlf_internal function canOwnFlowElement(elem:FlowElement):Boolean
 		{
-			return !(elem is TextFlow) && !(elem is FlowLeafElement) && !(elem is SubParagraphGroupElementBase) && !(elem is ListItemElement);
+			return !(elem is TextFlow) && !(elem is FlowLeafElement) && !(elem is SubParagraphGroupElementBase) && !(elem is ListItemElement) && !(elem is TableElement);
 		}
 		
 		/** @private */	
@@ -687,6 +687,7 @@ package flashx.textLayout.elements
 				{
 					child = this.getChildAt(beginChildIndex);
 					this.modelChanged(ModelChange.ELEMENT_REMOVAL, child, child.parentRelativeStart, child.textLength);
+					child.removed();
 					len += child.textLength;
 					
 					child.setParentAndRelativeStart(null,0);
@@ -770,8 +771,10 @@ package flashx.textLayout.elements
 								relStartIdx = beginChildIndex == _numChildren ? textLength : getChildAt(beginChildIndex).parentRelativeStart;
 							}
 						}
-						if (!canOwnFlowElement(newChild))
-							throw ArgumentError(GlobalSettings.resourceStringFunction("invalidChildType"));
+						
+						if (!canOwnFlowElement(newChild)) {
+							throw ArgumentError(GlobalSettings.resourceStringFunction("invalidChildType") + ". " + defaultTypeName + " cannot own " + newChild.defaultTypeName);
+						}
 						
 						// manage as an array or a single child
 						if (childrenToAdd == 0)
@@ -988,6 +991,7 @@ package flashx.textLayout.elements
 				parent.replaceChildren(myidx+1,myidx+1,newSibling);
 			}
 
+			newSibling.normalizeRange(0,newSibling.textLength);
 			return newSibling;
 		}
 

http://git-wip-us.apache.org/repos/asf/flex-tlf/blob/33df98ab/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
----------------------------------------------------------------------
diff --git a/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as b/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
index 22bfe40..894a362 100644
--- a/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
+++ b/textLayout/src/flashx/textLayout/elements/FlowLeafElement.as
@@ -337,6 +337,8 @@ package flashx.textLayout.elements
 		{
 			if (!_blockElement)
 				createContentElement();
+			if(!_blockElement)
+				return null;
 			var ef:ElementFormat = _blockElement.elementFormat;
 			if (!ef)
 				return null;