Index: /FCKeditor/trunk/editor/_source/internals/fcktablehandler.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fcktablehandler.js	(revision 673)
+++ /FCKeditor/trunk/editor/_source/internals/fcktablehandler.js	(revision 674)
@@ -299,5 +299,5 @@
 	}
 	var cells = FCKTableHandler.GetSelectedCells() ;
-	if ( ! ( cells && cells.length > 0 ) )
+	if ( cells.length != 1 )
 		return ;
 	
@@ -325,4 +325,5 @@
 FCKTableHandler.MergeDown = function()
 {
+	// TODO: the positional index algorithm is not accurate, use table map instead.
 	if ( ! FCKBrowserInfo.IsIE )
 	{
@@ -331,5 +332,5 @@
 	}
 	var cells = FCKTableHandler.GetSelectedCells() ;
-	if ( ! ( cells && cells.length > 0 ) )
+	if ( cells.length != 1 )
 		return ;
 
@@ -409,5 +410,71 @@
 FCKTableHandler.VerticalSplitCell = function()
 {
-	// TODO
+	var cells = FCKTableHandler.GetSelectedCells() ;
+	if ( cells.length != 1 )
+		return ;
+
+	var currentCell = cells[0] ;
+	var tableMap = this._CreateTableMap( currentCell.parentNode.parentNode ) ;
+	var cellIndex = FCKTableHandler._GetCellIndexSpan( tableMap, currentCell.parentNode.rowIndex, currentCell ) ;
+	var currentRowSpan = currentCell.rowSpan ;
+	var currentRowIndex = currentCell.parentNode.rowIndex ;
+	if ( isNaN( currentRowSpan ) )
+		currentRowSpan = 1 ;
+
+	if ( currentRowSpan > 1 )
+	{
+		// 1. Set the current cell's rowSpan to 1.
+		currentCell.rowSpan = 1 ;
+
+		// 2. Find the appropriate place to insert a new cell at the next row.
+		var newCellRowIndex = currentRowIndex + 1 ;
+		var insertMarker = null ;
+		for ( var i = cellIndex+1 ; i < tableMap[newCellRowIndex].length ; i++ )
+		{
+			if ( tableMap[newCellRowIndex][i].parentNode.rowIndex == newCellRowIndex )
+			{
+				insertMarker = tableMap[newCellRowIndex][i] ;
+				break ;
+			}
+		}
+
+		// 3. Insert the new cell to the indicated place, with the appropriate rowSpan, next row.
+		var newCell = FCK.EditorDocument.createElement( 'td' ) ;
+		newCell.rowSpan = currentRowSpan - 1 ;
+		if ( FCKBrowserInfo.IsGecko )
+			FCKTools.AppendBogusBr( newCell ) ;
+		currentCell.parentNode.parentNode.rows[newCellRowIndex].insertBefore( newCell, insertMarker ) ;
+	}
+	else
+	{
+		// 1. Insert a new row.
+		var newCellRowIndex = currentRowIndex + 1 ;
+		var newRow = FCK.EditorDocument.createElement( 'tr' ) ;
+		currentCell.parentNode.parentNode.insertBefore( newRow, currentCell.parentNode.parentNode.rows[newCellRowIndex] ) ;
+		
+		// 2. +1 to rowSpan for all cells crossing currentCell's row.
+		for ( var i = 0 ; i < tableMap[currentRowIndex].length ; )
+		{
+			var colSpan = tableMap[currentRowIndex][i].colSpan ;
+			if ( isNaN( colSpan ) || colSpan < 1 )
+				colSpan = 1 ;
+			if ( i == cellIndex )
+			{
+				i += colSpan ;
+				continue ;
+			}
+			var rowSpan = tableMap[currentRowIndex][i].rowSpan ;
+			if ( isNaN( rowSpan ) )
+				rowSpan = 1 ;
+			tableMap[currentRowIndex][i].rowSpan = rowSpan + 1 ;
+			i += colSpan ;
+		}
+
+		// 3. Insert a new cell to new row.
+		var newCell = FCK.EditorDocument.createElement( 'td' ) ;
+		if ( FCKBrowserInfo.IsGecko )
+			FCKTools.AppendBogusBr( newCell	) ;
+		newRow.appendChild( newCell ) ;
+	}
 }
 
