Index: /FCKeditor/branches/developers/martinkou/editor/_source/classes/fckspecialcombo.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/classes/fckspecialcombo.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/classes/fckspecialcombo.js	(revision 439)
@@ -139,4 +139,5 @@
 	for ( var i in this.Items )
 	{
+		if ( !this.Items[i] ) continue;
 		this.Items[i].className = this.Items[i].originalClass = 'SC_Item' ;
 		this.Items[i].Selected = false ;
@@ -176,4 +177,15 @@
 
 	this._OuterTable.className = isEnabled ? '' : 'SC_FieldDisabled' ;
+}
+
+FCKSpecialCombo.prototype.ClearItems = function ()
+{
+	if ( this.Items )
+	{
+		for ( var key in this.Items )
+			this.Items[key] = null ;
+	}
+	while (this._ItemsHolderEl.firstChild)
+		this._ItemsHolderEl.removeChild(this._ItemsHolderEl.firstChild);
 }
 
Index: /FCKeditor/branches/developers/martinkou/editor/_source/commandclasses/fck_othercommands.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/commandclasses/fck_othercommands.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/commandclasses/fck_othercommands.js	(revision 439)
@@ -99,8 +99,21 @@
 	if ( typeof( fontSize ) == 'string' ) fontSize = parseInt(fontSize, 10) ;
 
-	if ( fontSize == null || fontSize == '' )
-	{
-		// TODO: Remove font size attribute (Now it works with size 3. Will it work forever?)
-		FCK.ExecuteNamedCommand( 'FontSize', 3 ) ;
+	// If user wants the font size cleared, we have to find
+	// where the font size tag is and go clear it (if there's one)
+	if ( !fontSize || fontSize == null || fontSize == '' )
+	{
+		var oFont = FCK.Selection.MoveToAncestorNode('FONT');
+		if ( oFont && oFont.getAttribute("size") )
+		{
+			//if the only thing here is SIZE, collapse the whole tag
+			if (oFont.attributes.length == 1 ||
+				(oFont.outerHTML && oFont.outerHTML.search(/<FONT size=["]*\d["]*>/i)))
+			{
+				FCKTools.RemoveOuterTags(oFont);
+			}
+			else
+				oFont.removeAttribute("size");
+		}	
+
 	}
 	else
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_contextmenu.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_contextmenu.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_contextmenu.js	(revision 439)
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_gecko.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_gecko.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_gecko.js	(revision 439)
@@ -39,4 +39,19 @@
 	}
 
+	//allow the table handler to handle mouse messages for dynamic table sizing
+	this._ExecMouseDown = function(e)
+	{
+		FCK.Events.FireEvent( "OnMouseDown",e ) ;
+	}
+
+	this._ExecMouseMove = function(e)
+	{
+		FCK.Events.FireEvent( "OnMouseMove",e ) ;
+	}
+
+	this._ExecMouseUp = function(e)
+	{
+		FCK.Events.FireEvent( "OnMouseUp",e ) ;
+	}
 	this.ExecOnSelectionChangeTimer = function()
 	{
@@ -62,4 +77,10 @@
 	// Record changes for the undo system when there are key down events.
 	this.EditorDocument.addEventListener( 'keydown', this._KeyDownListener, false ) ;
+
+	
+	//Hooks for table sizing
+	this.EditorDocument.addEventListener( 'mousedown', this._ExecMouseDown, true ) ;
+	this.EditorDocument.addEventListener( 'mouseup', this._ExecMouseUp, true ) ;
+	this.EditorDocument.addEventListener( 'mousemove', this._ExecMouseMove, true ) ;
 
 	// Reset the context menu.
@@ -99,4 +120,5 @@
 	Print	: true,
 	Paste	: true,
+
 	Cut	: true,
 	Copy	: true
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_ie.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_ie.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fck_ie.js	(revision 439)
@@ -70,4 +70,15 @@
 		FCK.EditorWindow.event.returnValue	= false ;
 	}
+	FCK.Events.FireEvent( "OnMouseUp",FCK.EditorWindow.event) ;
+}
+
+function Doc_OnMouseDown()
+{
+	FCK.Events.FireEvent( "OnMouseDown",FCK.EditorWindow.event ) ;
+}
+
+function Doc_OnMouseMove()
+{
+	FCK.Events.FireEvent( "OnMouseMove",FCK.EditorWindow.event) ;
 }
 
@@ -103,4 +114,8 @@
 
 	this.EditorDocument.attachEvent("ondblclick", Doc_OnDblClick ) ;
+	
+	//additions for table sizing
+	this.EditorDocument.attachEvent( 'onmousedown', Doc_OnMouseDown ) ;
+	this.EditorDocument.attachEvent( 'onmousemove', Doc_OnMouseMove ) ;
 
 	// Catch cursor selection changes.
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckcommands.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckcommands.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckcommands.js	(revision 439)
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection.js	(revision 439)
@@ -23,2 +23,16 @@
 
 var FCKSelection = FCK.Selection = new Object() ;
+
+//Return the nearest ancestor to the current position of the caret.
+FCKSelection.GetCaretAncestor = function(strTag)
+{
+	var e = FCKSelection.GetParentElement();
+	var tn = e ?	FCKTools.GetElementAscensor(e,strTag) :
+					FCKSelection.MoveToAncestorNode(strTag);
+	return tn;
+}
+
+FCKSelection.SelectedText = function()
+{
+	return FCKTools.HTMLToText( this.SelectedHTML() );
+}
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection_gecko.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection_gecko.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection_gecko.js	(revision 439)
@@ -150,2 +150,48 @@
 	return oSel ;
 }
+
+// If FCKSelection is inside a table, return <td>'s so we can work on each
+// one as a separate element
+FCKSelection.TableNodes = function()
+{
+	var oSel = FCK.EditorWindow.getSelection();
+	var aNodes = new Array();
+	if (this.HasAncestorNode("TABLE"))
+	{
+		var oTable = this.MoveToAncestorNode("TABLE");
+		for (var r = 0; r < oTable.rows.length; r++)
+		{
+			for (var c = 0; c < oTable.rows[r].cells.length; c++)
+			{
+				if (oSel.containsNode(oTable.rows[r].cells[c],true))
+				{
+					aNodes[aNodes.length] = oTable.rows[r].cells[c];
+				}
+			}
+		}
+	}
+	return aNodes;
+}
+
+FCKSelection.SelectedHTML = function()
+{
+	var oSel = FCK.EditorWindow.getSelection();
+	var strHTML = "";
+	//convert to a text range and walk the elements
+	for ( var i = 0 ; i < oSel.rangeCount ; i++ )
+	{
+		var df = oSel.getRangeAt(i).cloneContents();
+		
+		for (var j = 0; j < df.childNodes.length; j++)
+		{
+			if (df.childNodes[j].nodeName == "#text")
+				{if (df.childNodes[j].textContent) strHTML += df.childNodes[j].textContent;}
+			else
+				strHTML += '<' + df.childNodes[j].nodeName + '>'
+						+ df.childNodes[j].innerHTML
+						+ '</' + df.childNodes[j].nodeName + '>';
+		}
+	}
+	return strHTML;
+}
+
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection_ie.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection_ie.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fckselection_ie.js	(revision 439)
@@ -47,4 +47,5 @@
 	{
 		case 'Control' :
+			if (!FCKSelection.GetSelectedElement()) return;
 			return FCKSelection.GetSelectedElement().parentElement ;
 		case 'None' :
@@ -110,4 +111,25 @@
 	return false ;
 } ;
+// If FCKSelection is inside a table, return <td>'s so we can work on each
+// one as a separate element
+FCKSelection.TableNodes = function()
+{
+	var oRange = FCK.EditorDocument.selection.createRange() ;
+	if (!oRange.htmlText.search(/<TD /)) return;
+	var oCellRange = oRange.duplicate();
+	var oTable = this.MoveToAncestorNode("TABLE");
+	if (!oTable) return;
+	var aNodes = new Array();
+	for (var i = 0; i < oTable.cells.length; i++)
+	{
+		oCellRange.moveToElementText(oTable.cells[i]);
+		if (oRange.inRange(oCellRange))
+		{
+			aNodes[aNodes.length] = oTable.cells[i];
+		}
+	}
+	return aNodes;
+}
+
 
 // The "nodeTagName" parameter must be UPPER CASE.
@@ -157,3 +179,7 @@
 } ;
 
+FCKSelection.SelectedHTML = function()
+{
+	return FCK.EditorDocument.selection.createRange().htmlText;
+}
 
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fcktablehandler.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fcktablehandler.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fcktablehandler.js	(revision 439)
@@ -1,24 +1,24 @@
 ﻿/*
- * FCKeditor - The text editor for Internet - http://www.fckeditor.net
- * Copyright (C) 2003-2007 Frederico Caldeira Knabben
- *
- * == BEGIN LICENSE ==
- *
- * Licensed under the terms of any of the following licenses at your
- * choice:
- *
- *  - GNU General Public License Version 2 or later (the "GPL")
- *    http://www.gnu.org/licenses/gpl.html
- *
- *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
- *    http://www.gnu.org/licenses/lgpl.html
- *
- *  - Mozilla Public License Version 1.1 or later (the "MPL")
- *    http://www.mozilla.org/MPL/MPL-1.1.html
- *
- * == END LICENSE ==
- *
- * Manage table operations.
- */
+       * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+       * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+       *
+       * == BEGIN LICENSE ==
+       *
+       * Licensed under the terms of any of the following licenses at your
+       * choice:
+       *
+       *  - GNU General Public License Version 2 or later (the "GPL")
+       *    http://www.gnu.org/licenses/gpl.html
+       *
+       *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+       *    http://www.gnu.org/licenses/lgpl.html
+       *
+       *  - Mozilla Public License Version 1.1 or later (the "MPL")
+       *    http://www.mozilla.org/MPL/MPL-1.1.html
+       *
+       * == END LICENSE ==
+       *
+       * Manage table operations.
+       */
 
 var FCKTableHandler = new Object() ;
@@ -42,9 +42,25 @@
 FCKTableHandler.DeleteRows = function( row )
 {
-	// If no row has been passed as a parameter,
-	// then get the row where the selection is placed in.
-	if ( !row )
-		row = FCKSelection.MoveToAncestorNode( 'TR' ) ;
-	if ( !row ) return ;
+	// If no row has been passed as a parameer,
+	// then get the row( s ) containing the cells where the selection is placed in.	
+	// If user selected multiple rows ( by selecting multiple cells ), walk
+	// the selected cell list and delete the rows containing the selected cells
+	if ( ! row )
+	{
+		var aCells = FCKTableHandler.GetSelectedCells() ;
+		var aRowsToDelete = new Array() ;
+		//queue up the rows -- it's possible ( and likely ) that we may get duplicates
+		for ( var i = 0; i < aCells.length; i++ )
+		{
+			var oRow = FCKTools.GetElementAscensor( aCells[i],'TR' ) ;
+			aRowsToDelete[oRow.rowIndex] = oRow ;
+		}
+		for ( var i = aRowsToDelete.length; i >= 0; i-- )
+		{
+			if ( aRowsToDelete[i] )
+				FCKTableHandler.DeleteRows( aRowsToDelete[i] );
+		}
+		return ;
+	}
 
 	// Get the row's table.
@@ -77,5 +93,11 @@
 	FCKSelection.SelectNode( table ) ;
 	FCKSelection.Collapse();
-	table.parentNode.removeChild( table ) ;
+
+	// if the table is wrapped with a singleton <p> ( or something similar ), remove
+	// the surrounding tag -- which likely won't show after deletion anyway
+	if ( table.parentNode.childNodes.length == 1 )
+		table.parentNode.parentNode.removeChild( table.parentNode );
+	else
+		table.parentNode.removeChild( table  ) ;
 }
 
@@ -83,21 +105,10 @@
 {
 	// Get the cell where the selection is placed in.
-	var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ;
-
-	if ( !oCell ) 
-	{
-		// oCell not fouund could be due to multiple selection ranges on tables in Gecko.
-		// We have another function to find the table cell for this special case.
-		if ( ! FCKBrowserInfo.IsIE )
-		{
-			var node = this._GetSelectedCellFromGecko( true ) ;
-			if ( node )
-				oCell = node ;
-			else
-				return null ;
-		}
-		else
-			return null ;
-	}
+	var oCell = null ;
+	var nodes = this.GetSelectedCells() ;
+	if ( nodes && nodes.length )
+		oCell = nodes[ insertBefore ? 0 : ( nodes.length - 1 ) ] ;
+	if ( ! oCell )
+		return null ;
 
 	// Get the cell's table.
@@ -133,8 +144,18 @@
 }
 
-FCKTableHandler.DeleteColumns = function()
-{
-	// Get the cell where the selection is placed in.
-	var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ;
+FCKTableHandler.DeleteColumns = function( oCell )
+{
+	// if user selected multiple cols ( by selecting multiple cells ), walk
+	// the selected cell list and delete the rows containing the selected cells
+	if ( !oCell  )
+	{
+		var aColsToDelete = FCKTableHandler.GetSelectedCells();
+		for ( var i = aColsToDelete.length; i >= 0; i--  )
+		{
+			if ( aColsToDelete[i]  )
+				FCKTableHandler.DeleteColumns( aColsToDelete[i]  );
+		}
+		return;
+	}
 
 	if ( !oCell ) return ;
@@ -170,20 +191,10 @@
 {
 	// Get the cell where the selection is placed in.
-	var oCell = cell ? cell : FCKSelection.MoveToAncestorNode( 'TD' ) ;
-	if ( !oCell ) 
-	{
-		// oCell not fouund could be due to multiple selection ranges on tables in Gecko.
-		// We have another function to find the table cell for this special case.
-		if ( ! FCKBrowserInfo.IsIE )
-		{
-			var node = this._GetSelectedCellFromGecko( true ) ;
-			if ( node )
-				oCell = node ;
-			else
-				return null ;
-		}
-		else
-			return null ;
-	}
+	var oCell = null ;
+	var nodes = this.GetSelectedCells() ;
+	if ( nodes && nodes.length )
+		oCell = nodes[ insertBefore ? 0 : ( nodes.length - 1 ) ] ;
+	if ( ! oCell )
+		return null ;
 
 	// Create the new cell element to be added.
@@ -191,5 +202,5 @@
 	if ( FCKBrowserInfo.IsGecko )
 		oNewCell.innerHTML = GECKO_BOGUS ;
-//	oNewCell.innerHTML = "&nbsp;" ;
+	//	oNewCell.innerHTML = "&nbsp;" ;
 
 	if ( !insertBefore && oCell.cellIndex == oCell.parentNode.cells.length - 1 )
@@ -256,5 +267,5 @@
 				continue ;
 
-				oCellsContents.insertBefore( eChild, oCellsContents.firstChild ) ;
+			oCellsContents.insertBefore( eChild, oCellsContents.firstChild ) ;
 		}
 
@@ -288,5 +299,5 @@
 	var iCellIndex = FCKTableHandler._GetCellIndexSpan( aMap, aCells[0].parentNode.rowIndex , aCells[0] ) ;
 
-	var aCollCells = this._GetCollumnCells( aMap, iCellIndex ) ;
+	var aCollCells = this._GetColumnCells( aMap, iCellIndex ) ;
 
 	for ( var i = 0 ; i < aCollCells.length ; i++ )
@@ -325,6 +336,19 @@
 }
 
-// Get the cells available in a collumn of a TableMap.
-FCKTableHandler._GetCollumnCells = function( tableMap, collumnIndex )
+// Get the cell location from a TableMap. Returns an array with an [x,y] location
+FCKTableHandler._GetCellLocation = function( tableMap, cell  )
+{
+	for ( var i = 0 ; i < tableMap.length; i++ )
+	{
+		for ( var c = 0 ; c < tableMap[i].length ; c++  )
+		{
+			if ( tableMap[i][c] == cell  ) return [i,c];
+		}
+	}
+	return null ;
+}
+
+// Get the cells available in a column of a TableMap.
+FCKTableHandler._GetColumnCells = function( tableMap, columnIndex )
 {
 	var aCollCells = new Array() ;
@@ -332,5 +356,5 @@
 	for ( var r = 0 ; r < tableMap.length ; r++ )
 	{
-		var oCell = tableMap[r][collumnIndex] ;
+		var oCell = tableMap[r][columnIndex] ;
 		if ( oCell && ( aCollCells.length == 0 || aCollCells[ aCollCells.length - 1 ] != oCell ) )
 			aCollCells[ aCollCells.length ] = oCell ;
@@ -391,4 +415,377 @@
 }
 
+//Returns TRUE if any cell has width set
+FCKTableHandler.HasCellWidths = function( table )
+{
+	for ( var r = 0; r < table.rows.length; r++ )
+	{
+		for ( var c = 0; c < table.rows[r].cells.length; c++ )
+		{
+			if ( table.rows[r].cells[c].width ) return true;
+		}
+	}
+	return false;
+}
+
+//Clears all cell widths/heights ( letting the browser size everything )
+FCKTableHandler.ClearCellWidths = function( table )
+{
+	for ( var r = 0; r < table.rows.length; r++ )
+	{
+		for ( var c = 0; c < table.rows[r].cells.length; c++ )
+		{
+			table.rows[r].cells[c].width = "";
+			table.rows[r].cells[c].height = "";
+			table.rows[r].cells[c].removeAttribute( "WIDTH" );
+			table.rows[r].cells[c].removeAttribute( "HEIGHT" );
+		}
+	}
+}
+
+//Cleanup table widths. If bPercent, recalculates table widths in %. If bClear,
+//moves all table widths as early as possible
+
+FCKTableHandler.CleanupTableWidths = function( table, bPercent, bClear, aMapIn )
+{
+	var aMap = aMapIn ? aMapIn : this._CreateTableMap( table ) ;
+	var nCols = aMap[0].length;
+	var nRows = aMap.length;
+	var nTotalWidth = 0;
+	var aSizeCells = new Array();
+	var aSizes = new Array();
+	//work the table column-by-column
+	for ( var nCol = 0; nCol < nCols; nCol++ )
+	{
+		var nMax = 0;
+		var oCell = null;
+		//walk the rows for a specific column -- find the topmost non-colspan'd item
+		//and the maximum pixel width ( according to the browser )
+		for ( var nRow = 0; nRow < nRows; nRow++ )
+		{
+			if ( aMap[nRow][nCol].colSpan > 1 ) continue;
+			//use topmost non-colspan'd cell to put the width in
+			if ( !oCell ) oCell = aMap[nRow][nCol];
+			if ( aMap[nRow][nCol].offsetWidth > nMax ) nMax = aMap[nRow][nCol].offsetWidth;
+		}
+		aSizes[nCol] = nMax;
+		nTotalWidth += nMax;
+		aSizeCells[nCol] = oCell;
+	}
+	//if we were asked for percentage width, go through and convert the sizes to %. note
+	//that we do this based on the calculated width of all the cells; this is more
+	//reliable because offsetWidth, et al., includes table borders, padding, etc.
+	for ( var nCol = 0; nCol < aSizeCells.length; nCol++ )
+	{
+		if ( bPercent )
+		{
+			var nWidth = Math.round( 100 * (aSizeCells[nCol].offsetWidth/nTotalWidth ));
+			if ( nWidth == 0 ) nWidth = 1;
+			strWidth =  nWidth + "%";
+		}
+		else
+		{
+			strWidth =  aSizes[nCol];
+		}
+
+		//set all width attributes
+		for ( var nRow = 0; nRow < nRows; nRow++ )
+		{
+			if ( aMap[nRow][nCol].colSpan == 1 )
+			{
+				aMap[nRow][nCol].width = bClear ? '' : strWidth;
+				if ( bClear ) aMap[nRow][nCol].removeAttribute( "width" );
+				aSizeCells[nCol].width = strWidth;
+			}
+		}
+	}
+}
+
+// Move the cursor into the next ( or previous ) cell
+FCKTableHandler.MoveToNextCell = function( bRev )
+{
+	var aCells = FCKTableHandler.GetSelectedCells();
+	if ( aCells.length == 0 ) return;
+	var oCell = aCells[0];
+	var oNextCell = bRev ? oCell.previousSibling: oCell.nextSibling;
+	if ( !oNextCell )
+	{
+		var oNext;
+		var oRow = FCKTools.GetElementAscensor( oCell,"TR" );
+		if ( bRev )
+		{
+			if ( !(oNext = oRow.previousSibling )) return;
+			oNextCell=oNext.cells[oNext.cells.length - 1];
+		}
+		else
+		{
+			if ( !(oNext = oRow.nextSibling )) return;
+			oNextCell=oNext.cells[0];
+		}
+	}
+	FCKSelection.SelectNode( oNextCell );
+	FCKSelection.Collapse();
+}
+//////////////////////////////////////////////////////////////////
+// Table Sizer
+//
+
+
+// Returns the closest sizeable cell to point (or the left of the specified point
+// if between cells). Generally, this will be a heading cell (i.e. a cell in
+// the first row). If *all* the candidate cells are colspan'd (heaven forbid),
+// don't allow sizing. x and y are in client coordinates
+
+FCKTableHandler.SizableCellFromPoint = function( table, ncx, ncy )
+{
+	var aRows = table.rows ;
+	var x = ncx - this._CalcPosition( table )[0];
+	for ( var i = 0 ; i < aRows.length ; i++  )
+	{
+		for ( var j = 0; j < aRows[i].cells.length - 1; j++ )
+		{
+			if ( aRows[i].cells[j + 1].offsetLeft > x )
+			{
+				if ( aRows[i].cells[j].colSpan < 2 )
+				{
+					return aRows[i].cells[j];
+				}
+				else
+				{
+					break;
+				}
+			}	
+		}
+	}
+	return null;
+}
+
+// Creates the table resize bar. If a table resize bar is present, uses it. You
+// must explicitly destroy the table resize bar with DestroyResizeBar after use.
+FCKTableHandler.CreateResizeBar = function()
+{
+	if ( this.ResizeBar ) return this.ResizeBar;
+	var oBar;	
+	oBar = FCK.EditorDocument.createElement( "SPAN" );
+
+	// setup the bar
+	oBar.id = '__FCKResizeBar';
+	oBar.style.position = "absolute";
+	oBar.style.top = "0px";
+	oBar.style.left = "0px";
+	oBar.style.height = "0px";
+	oBar.style.width = "2px";
+	oBar.style.borderLeft = "1px solid #0033FF";
+	oBar.style.display = "none";
+	oBar.style.cursor = "e-resize";
+
+	FCK.EditorDocument.body.appendChild( oBar );
+	this.ResizeBar = oBar;
+	return oBar;
+}
+
+// Destroys the table resize bar
+FCKTableHandler.DestroyResizeBar = function()
+{
+	if ( !this.ResizeBar ) return;
+	this.ResizeBar.parentNode.removeChild( FCKTableHandler.ResizeBar );
+	this.ResizeBar = null;
+}
+
+// Figures out whether we want to size or let the browser do its thing. We can
+// size if the table is the target and we're between cells, OR if we're on
+// a table cell and on the far right edge of the cell within 3px of the edge
+// ( allows us to easily size tables with thin borders )
+
+FCKTableHandler.CanSizeHere = function( ev, cell, tbl )
+{
+	var elem = ev.srcElement || ev.originalTarget;
+	var aCellLoc = this._CalcPosition( cell );
+	var aTableLoc = this._CalcPosition( tbl );
+	//in the td client area, but not on the edge
+	if ( elem != tbl ) return ( (aCellLoc[0] + cell.offsetWidth - ev.clientX ) < 3);
+	//on the table edge
+	if ( (aTableLoc[0] + tbl.offsetWidth - ev.clientX ) < 3 ||
+			( aTableLoc[0] - ev.clientX ) < 3 ||
+			( aTableLoc[1] + tbl.offsetHeight - ev.clientY < 3 ) ||
+			( aTableLoc[1] - ev.clientY < 3 )) return false;
+	return true;
+}
+
+
+// Sets up table sizing
+FCKTableHandler.StartTableSizing = function( ev, cell, tbl )
+{
+	if ( !cell ) return null;
+	this.tableMap = this._CreateTableMap( tbl ) ;
+	var aCellLoc = this._GetCellLocation( this.tableMap, cell );				//returns [row,col]
+	if ( !aCellLoc ) return null;
+	//we're in the last column, so we can't size
+	if ( aCellLoc[1] == this.tableMap[aCellLoc[0]].length - 1 ) return null;
+	var nTarget = aCellLoc[1] + 1;
+	this.adjacentCell = null;
+	for ( var i=0; i < this.tableMap.length; i++ )
+	{
+		if ( this.tableMap[i][nTarget].colSpan < 2 )
+		{
+			this.adjacentCell = this.tableMap[i][nTarget];
+			break;
+		}
+	}
+	if ( this.adjacentCell == null ) return null;	//can't size, no adjacent col
+	this.targetCell = cell;
+	//ok. we have everything we need. off we go.
+
+	//create the resize bar
+	this.pixWidths = !( this.targetCell.width.search('%' ) == -1 || !this.targetCell.width);
+	var oVBar = this.CreateResizeBar();
+	//oVBar.style.left = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( cell ) + cell.offsetWidth;
+	//this.origPos = FCK.EditorDocument.body.scrollLeft + ev.clientX;
+	this.origPos = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( cell )[0] + cell.offsetWidth;
+	oVBar.style.left = this.origPos;
+	oVBar.style.cursor = "e-resize";
+	oVBar.setAttribute( "UNSELECTABLE","on" );
+	tbl.setAttribute( "UNSELECTABLE","on" );
+	this.sizeOffset = ev.clientX - this.origPos;
+	//minimum size is always the left edge of the cell + some safety margin.
+	//max size is always the right edge of the next cell - some safety margin
+	this.minSize = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( cell )[0] + 10;
+	this.maxSize = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( this.adjacentCell )[0] + this.adjacentCell.offsetWidth - 10;
+	oVBar.style.top = this._CalcPosition( tbl )[1];
+	oVBar.style.height = tbl.clientHeight + ( tbl.border*2 );
+	oVBar.style.display = "inline";
+	this.CleanupTableWidths( tbl,false, true,this.tableMap );
+	return true;
+}
+
+FCKTableHandler.FinishTableSizing = function()
+{
+	var tbl = FCKTools.GetElementAscensor( this.targetCell,"TABLE" );
+	var nTargetDiff = this.ResizeBar.offsetLeft - this.origPos;
+	//widths are in pixels after StartTableSizing, so this is safe
+	tbl.style.cursor = '';
+	if ( tbl.runtimeStyle ) tbl.runtimeStyle.cursor = '';
+	this.targetCell.width = parseInt( this.targetCell.width ) + nTargetDiff;
+	this.adjacentCell.width = parseInt( this.adjacentCell.width ) - nTargetDiff;
+	this.DestroyResizeBar();
+	this.CleanupTableWidths( tbl,this.pixWidths,true,this.tableMap );
+	this.targetCell = null;
+	this.origPos = null;
+	tbl.removeAttribute( "UNSELECTABLE" );
+	if ( FCKBrowserInfo.IsGecko  ) tbl.style.MozUserSelect = "";
+}
+
+// Sizes the table to the given mouse position
+FCKTableHandler.SizeTo = function( x )
+{
+	var nPos = x - this.sizeOffset;
+	if ( nPos > this.maxSize ) nPos = this.maxSize;
+	if ( nPos < this.minSize ) nPos = this.minSize;
+	//runtimeStyle is way faster under IE
+	if ( this.ResizeBar.runtimeStyle )
+		this.ResizeBar.runtimeStyle.left = nPos;
+	else
+		this.ResizeBar.style.left = nPos;
+	if ( FCKBrowserInfo.IsIE && FCK.EditorDocument.selection.type != 'None' ) 
+		FCK.EditorDocument.selection.collapse();
+}
+
+// returns TRUE if we are actively sizing a table
+FCKTableHandler.IsTableSizing = function()
+{
+	return ( this.targetCell != null );
+}
+
+// figure out where ( with respect to the edge of the parent ) a given table/cell is
+FCKTableHandler._CalcPosition = function( ob )
+{
+	var oParent=ob;
+	var nY = 0;
+	var nX = 0;
+	while ( oParent && oParent.tagName != "BODY" )
+	{
+		nX += oParent.offsetLeft;
+		nY += oParent.offsetTop;
+		oParent = oParent.offsetParent;
+	}
+	return [nX,nY];
+}
+
+FCKTableHandler.tbl_MouseDown = function ( FCK, e )
+{
+	var elem = e.srcElement || e.originalTarget;
+	var strTag = elem ? elem.tagName.toUpperCase() : null;
+	//find the table we're part of, if we are
+	if ( elem && (strTag == 'TABLE' || strTag == 'TD' || strTag == 'TH' ) )
+	{
+		FCKTableHandler.targetCell = null;
+		var oTable = FCKTools.GetElementAscensor( elem, "TABLE" );
+		//figure out if there's a cell we can size
+		var oCell = FCKTableHandler.SizableCellFromPoint( oTable, e.clientX, e.clientY );
+		if ( !oCell ) return true;
+		if ( FCKTableHandler.CanSizeHere( e,oCell,oTable ) )
+		{
+			if ( FCKTableHandler.StartTableSizing( e,oCell, oTable ) )
+			{
+				if ( oTable.runtimeStyle ) oTable.runtimeStyle.cursor = "e-resize";
+				if ( FCKBrowserInfo.IsGecko  ) oTable.style.MozUserSelect = "none";
+				e.cancelBubble	= true ;
+				e.returnValue	= false ;
+				return false;
+			}
+		}
+	}
+	return true;
+}
+
+FCKTableHandler.tbl_MouseUp = function ( FCK, e )
+{
+	if ( FCKTableHandler.IsTableSizing( )) FCKTableHandler.FinishTableSizing();
+}
+
+FCKTableHandler.tbl_MouseMove = function ( FCK, e )
+{
+	var elem = e.srcElement || e.originalTarget;
+	if ( FCKTableHandler.IsTableSizing() )
+	{
+		FCKTableHandler.SizeTo( e.clientX );
+		e.cancelBubble	= true ;
+		e.returnValue	= false ;
+		return false;
+	}
+
+	if ( elem.tagName.toUpperCase() == 'TABLE' )
+	{
+		//let the browser handle global sizing and move if the user is on
+		//the RH edge of a table
+		if ( elem.clientWidth - e.offsetX < 3 ||
+				elem.clientHeight - e.offsetY < 3 ||
+				e.offsetX < 2 || e.offsetY < 2 )
+		{
+			elem.style.cursor = "";	
+			return true;
+		}
+		//block browser sizing -- we're going to do it ourselves, thanks
+		if ( elem.runtimeStyle ) elem.runtimeStyle.cursor = "e-resize";
+		e.cancelBubble	= true ;
+		e.returnValue	= false ;
+		return false;
+	}
+	else if ( elem.tagName.toUpperCase() == 'TD' )
+	{
+		var tbl = FCKTools.GetElementAscensor( elem, "TABLE" );
+		if ( e.offsetX >= (elem.offsetWidth - 4 ))
+		{
+			e.cancelBubble	= true ;
+			e.returnValue	= false ;
+			return false;
+		}
+	}
+	return true;
+}
+
+FCK.Events.AttachEvent( "OnMouseMove", FCKTableHandler.tbl_MouseMove );
+FCK.Events.AttachEvent( "OnMouseDown", FCKTableHandler.tbl_MouseDown );
+FCK.Events.AttachEvent( "OnMouseUp", FCKTableHandler.tbl_MouseUp );
+
 FCKTableHandler.ClearRow = function( tr )
 {
@@ -405,39 +802,2 @@
 	}
 }
-
-FCKTableHandler._GetSelectedCellFromGecko = function( getLastCell )
-{
-	var sel = FCK.EditorWindow.getSelection() ;
-	if ( sel.rangeCount < 1 )
-		return null ;
-	var range = getLastCell ? sel.getRangeAt( sel.rangeCount - 1 ) : sel.getRangeAt( 0 ) ;
-	var node = getLastCell ? range.endContainer : range.startContainer ;
-
-	// Gecko returns a <TR> as startContainer and endContainer when cells are selected.
-	// We need to find back the final <TD|TH> that's being selected.
-	if ( node.nodeType == 1 && node.tagName.toLowerCase() == 'tr' )
-	{
-		for ( var i = range.startOffset ; i <= range.endOffset ; i++ )
-		{
-			var candidate = node.childNodes[i] ;
-			var tag = candidate.tagName.toLowerCase() ;
-			if ( candidate.nodeType == 1 && ( tag == 'td' || tag == 'th' ) )
-			{
-				node = node.childNodes[i] ;
-				break ;
-			}
-		}
-	}
-	// For safety, we have to be ready for the 'usual' case as well.
-	else
-	{
-		while ( node && node.tagName.toLowerCase() != 'td' && node.tagName.toLowerCase() != 'th' )
-			node = node.parentNode ;
-	}
-
-	// Have we found the <TD|TH> node we wanted, finally? If yes, return the found node. If not, abort.
-	if ( node.tagName.toLowerCase() != 'td' && node.tagName.toLowerCase() != 'th' )
-		return null ;
-	else
-		return node ;
-}
Index: /FCKeditor/branches/developers/martinkou/editor/_source/internals/fcktools.js
===================================================================
--- /FCKeditor/branches/developers/martinkou/editor/_source/internals/fcktools.js	(revision 438)
+++ /FCKeditor/branches/developers/martinkou/editor/_source/internals/fcktools.js	(revision 439)
@@ -94,4 +94,23 @@
 		return '' ;
 
+}
+
+//convert text to Proper Case
+FCKTools.ProperCase = function( text )
+{
+	var strPC = text.toLowerCase();
+	return strPC.replace(/(\S)(\S*\s*)/g,
+						function(str,p1,p2) 
+							{return p1.toUpperCase()+p2});
+}
+
+FCKTools.HTMLToText = function( st )
+{
+	if ( !st ) 
+		return null;
+		
+	st = st.replace(/<([^>]*?)>/g,'');
+	st = st.replace(/&nbsp;/gi,' ');
+	return st;
 	text = text.replace( /&/g, '&amp;' ) ;
 	text = text.replace( /</g, '&lt;' ) ;
