Index: /FCKeditor/trunk/editor/_source/internals/fck_gecko.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fck_gecko.js	(revision 595)
+++ /FCKeditor/trunk/editor/_source/internals/fck_gecko.js	(revision 596)
@@ -59,4 +59,78 @@
 	}
 
+	this._ExecCheckCaret = function( evt )
+	{
+		if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
+			return ;
+
+		var keyCode = evt.keyCode ;
+		var modKeys = { 34 : 1, 35 : 1, 39 : 1, 40 : 1 } ;
+		if ( ! modKeys[keyCode] )
+			return ;
+
+		var moveCursor = function()
+		{
+			var selection = FCK.EditorWindow.getSelection() ;
+			var range = selection.getRangeAt(0) ;
+			if ( ! range || ! range.collapsed )
+				return ;
+
+			var node = range.endContainer ;
+			
+			if ( node.nodeType != 3 )
+				return ;
+
+			if ( node.nodeValue.length != range.endOffset )
+				return ;
+
+			// we've moved to just after the last character of a text node under an unknown tag, how to proceed?
+			// first, see if there are other text nodes by DFS walking from this text node.
+			// 	- if the DFS has scanned all nodes under my parent, then go the next step.
+			//	- if there is a text node after me but still under my parent, then do nothing and return.
+			var nextTextNode = FCKTools.GetNextTextNode( node, node.parentNode ) ;
+			if ( nextTextNode )
+				return ;
+
+			// we're pretty sure we need to move the caret forcefully from here.
+			range = FCK.EditorDocument.createRange() ;
+
+			nextTextNode = FCKTools.GetNextTextNode( node, node.parentNode.parentNode ) ;
+			if ( nextTextNode )
+			{
+				// now we want to get out of our current parent node, adopt the next parent, and move the caret to 
+				// the appropriate text node under our new parent.
+				// our new parent might be our curernt parent's siblings if we are lucky.
+				range.setStart( nextTextNode, 0 ) ;
+				range.setEnd( nextTextNode, 0 ) ;
+			}
+			else
+			{
+				// no suitable next siblings under our grandparent! what to do next?
+				node = node.parentNode ;
+				if ( FCKListsLib.BlockElements[ node.tagName.toLowerCase() ] || node == FCK.EditorDocument.body )
+				{
+					// if our parent is a block node, move to the end of our parent.
+					range.setStart( node, node.childNodes.length ) ;
+					range.setEnd( node, node.childNodes.length ) ;
+				}
+				else
+				{
+					// if our parent is not a block node, move to the end of our grandparent.
+					// note that the dummy marker below is NEEDED, otherwise the caret's behavior will 
+					// be broken in Gecko.
+					var marker = FCK.EditorDocument.createTextNode( "" ) ;
+					node.parentNode.appendChild( marker ) ;
+					range.setStart( marker, 0 ) ;
+					range.setEnd( marker, 0 ) ;
+				}
+			}
+
+			selection.removeAllRanges() ;
+			selection.addRange( range ) ;
+		}
+		
+		setTimeout( moveCursor, 1 ) ;
+	}
+
 	this.ExecOnSelectionChangeTimer = function()
 	{
@@ -96,4 +170,8 @@
 		this.EditorDocument.addEventListener( 'drop', this._ExecDrop, true ) ;
 	}
+
+	// Kludge for buggy Gecko caret positioning logic (Bug #393)
+	if ( FCKBrowserInfo.IsGecko )
+		this.EditorDocument.addEventListener( 'keypress', this._ExecCheckCaret, false ) ;
 
 	// Reset the context menu.
Index: /FCKeditor/trunk/editor/_source/internals/fcktools.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fcktools.js	(revision 595)
+++ /FCKeditor/trunk/editor/_source/internals/fcktools.js	(revision 596)
@@ -511,2 +511,33 @@
 	}
 }
+
+// Perform a one-step DFS walk.
+FCKTools.GetNextNode = function( node, limitNode )
+{
+	if ( node.firstChild )
+		return node.firstChild ;
+	else if ( node.nextSibling )
+		return node.nextSibling ;
+	else
+	{
+		var ancestor = node.parentNode ;
+		while ( ancestor )
+		{
+			if ( ancestor == limitNode )
+				return null ;
+			if ( ancestor.nextSibling )
+				return ancestor.nextSibling ;
+			else
+				ancestor = ancestor.parentNode ;
+		}
+	}
+	return null ;
+}
+
+FCKTools.GetNextTextNode = function( textnode, limitNode )
+{
+	node = this.GetNextNode( textnode, limitNode ) ;
+	while ( node && node.nodeType != 3 )
+		node = this.GetNextNode( node, limitNode ) ;
+	return node ;
+}
