Index: /FCKeditor/trunk/editor/_source/classes/fckdomrange.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 775)
+++ /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 776)
@@ -726,4 +726,190 @@
 	{
 		return ( this._Range && true ) ;
+	},
+
+	_CheckIsParagraphBoundary : function( node )
+	{
+		if ( node.nodeType == 1 )
+		{
+			var tagName = node.tagName.toLowerCase() ;
+			return ! ( FCKListsLib.InlineNonEmptyElements[tagName] || tagName == 'img' ) ;
+		}
+		return false ;
+	},
+
+	_GenerateParagraphRange : function( paragraphList, targetWindow, startNode, endNode )
+	{
+		if ( ! startNode || ! endNode )
+			return ;
+		var range = new FCKDomRange( targetWindow ) ;
+		range._Range = new FCKW3CRange( targetWindow.document ) ;
+		if ( startNode.nodeName.toLowerCase() == 'br' )
+			range._Range.setStartBefore( startNode ) ;
+		else
+			range._Range.setStart( startNode, 0 ) ;
+		if ( endNode.nodeName.toLowerCase() == 'br' )
+			range._Range.setEndBefore( endNode ) ;
+		else
+			range._Range.setEnd( endNode, endNode.nodeType == 1 ? endNode.childNodes.length : endNode.nodeValue.length ) ;
+		range._UpdateElementInfo() ;
+		paragraphList.push( range ) ;
+	},
+
+	GetSelectedParagraphs : function()
+	{
+		this.MoveToSelection() ;
+
+		var startNode = this._Range.startContainer ;
+		var endNode = this._Range.endContainer ;
+		var startOffset = this._Range.startOffset ;
+		var endOffset = this._Range.endOffset ;
+		if ( startNode.childNodes && startNode.childNodes[startOffset] )
+			startNode = startNode.childNodes[startOffset] ;
+		if ( endNode.childNodes && endNode.childNodes[endOffset] )
+			endNode = endNode.childNodes[endOffset] ;
+
+		// Get the starting point of the selection's paragraph.
+		var paragraphStartNode = startNode ;
+		while ( paragraphStartNode && ! this._CheckIsParagraphBoundary( paragraphStartNode ) )
+		{
+			var candidate = null ;
+			if ( paragraphStartNode.previousSibling )
+			{
+				if ( ! this._CheckIsParagraphBoundary( paragraphStartNode.previousSibling ) )
+					candidate = paragraphStartNode.previousSibling ;
+				while ( candidate && candidate.lastChild && ! this._CheckIsParagraphBoundary( candidate.lastChild ) )
+					candidate = candidate.lastChild ;
+			}
+			else
+			{
+				if ( ! this._CheckIsParagraphBoundary( paragraphStartNode.parentNode ) )
+					candidate = paragraphStartNode.parentNode ;
+			}
+
+			if ( candidate )
+				paragraphStartNode = candidate ;
+			else
+				break ;
+		}
+
+		// Get the ending point of the selection's paragraph.
+		var paragraphEndNode = endNode ;
+		while ( paragraphEndNode && ! this._CheckIsParagraphBoundary( paragraphEndNode ) )
+		{
+			var candidate = null ;
+			if ( paragraphEndNode.firstChild )
+			{
+				if ( ! this._CheckIsParagraphBoundary( paragraphEndNode.firstChild ) )
+					candidate = paragraphEndNode.firstChild ;
+			}
+			else if ( paragraphEndNode.nextSibling )
+			{
+				if ( ! this._CheckIsParagraphBoundary( paragraphEndNode.nextSibling ) )
+					candidate = paragraphEndNode.nextSibling ;
+			}
+			else
+			{
+				var ancestor = paragraphEndNode.parentNode ;
+				while ( ancestor )
+				{
+					if ( this._CheckIsParagraphBoundary( ancestor ) )
+						break ;
+					if ( ancestor.nextSibling )
+					{
+						if ( this._CheckIsParagraphBoundary( ancestor.nextSibling ) )
+							break ;
+						candidate = ancestor.nextSibling ;
+						break ;
+					}
+					else
+						ancestor = ancestor.parentNode ;
+				}
+			}
+
+			if ( candidate )
+				paragraphEndNode = candidate ;
+			else
+				break ;
+		}
+
+		// Break up the range between paragraphStartNode and paragraphEndNode into paragraphs represented by ranges.
+		var retval = [] ;
+		var currentStart = paragraphStartNode ;
+		var currentEnd = currentStart ;
+
+		// Each iteration advances the position by one node in a DFS tree walk.
+		while ( currentEnd != paragraphEndNode )
+		{
+			// 1. if we come across a <br> node, save a new paragraph
+			// 2. if we come across a block element boundary, save a new paragraph
+			// 3. set currentStart to null after saving a new paragraph
+			// 4. set currentStart to currentEnd if currentStart is null and currentEnd is not boundary node
+			if ( currentStart == null && currentEnd.nodeType == 3 )
+			{
+				// Ignore normal whitespaces (i.e. not including &nbsp; or other unicode whitespaces) after a block node.
+				if ( currentEnd.nodeValue.search( /^[\r\n\t ]+$/ ) == 0 )
+				{
+					var prevNode = currentEnd.previousSibling ;
+					if ( prevNode )
+					{
+						var prevTag = String( prevNode.tagName ).toLowerCase() ;
+						if ( ! ( FCKListsLib.BlockElements[prevTag] || FCKListsLib.NonEmptyBlockElements[prevTag] ) )
+							currentStart = currentEnd ;
+					}
+				}
+				else if ( currentEnd.nodeValue.length > 0 )
+					currentStart = currentEnd ;
+			}
+
+			if ( currentEnd.firstChild )
+			{
+				if ( this._CheckIsParagraphBoundary( currentEnd.firstChild ) )
+				{
+					this._GenerateParagraphRange( retval, this.Window, currentStart, currentEnd ) ;
+					currentStart = null ;
+				}
+				currentEnd = currentEnd.firstChild ;
+			}
+			else if ( currentEnd.nextSibling )
+			{
+				if ( this._CheckIsParagraphBoundary( currentEnd.nextSibling ) )
+				{
+					this._GenerateParagraphRange( retval, this.Window, currentStart, currentEnd ) ;
+					currentStart = null ;
+				}
+				currentEnd = currentEnd.nextSibling ;
+			}
+			else
+			{
+				var ancestor = currentEnd.parentNode ;
+				while ( ancestor )
+				{
+					if ( this._CheckIsParagraphBoundary( ancestor ) )
+					{
+						this._GenerateParagraphRange( retval, this.Window, currentStart, currentEnd ) ;
+						currentStart = null ;
+					}
+					if ( ancestor.nextSibling )
+					{
+						if ( this._CheckIsParagraphBoundary( ancestor.nextSibling ) )
+						{
+							this._GenerateParagraphRange( retval, this.Window, currentStart, currentEnd ) ;
+							currentStart = null ;
+						}
+						currentEnd = ancestor.nextSibling ;
+						break ;
+					}
+					else
+						ancestor = ancestor.parentNode ;
+				}
+			}
+		}
+		// Record the final range as well.
+		if ( currentStart == null && currentEnd.nodeType == 3 )
+			currentStart = currentEnd ;
+		this._GenerateParagraphRange( retval, this.Window, currentStart, currentEnd ) ;
+
+		return retval ;
 	}
+
 } ;
