Index: /CKEditor/branches/versions/3.1.x/CHANGES.html
===================================================================
--- /CKEditor/branches/versions/3.1.x/CHANGES.html	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/CHANGES.html	(revision 4613)
@@ -34,6 +34,5 @@
 	<h1>
 		CKEditor Changelog
-	</h1>l45
-
+	</h1>
 	<h3>
 		CKEditor 3.1 (SVN)</h3>
@@ -98,4 +97,9 @@
 		<li><a href="http://dev.fckeditor.net/ticket/4714">#4714</a> : Fixed IE6 JavaScript error when editing flash by commit 'Flash' dialog.</li>
 		<li><a href="http://dev.fckeditor.net/ticket/3905">#3905</a> : Fixed 'wysiwyg' mode causes unauthenticated content warnings over SSL in FF 3.5.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4736">#4736</a> : Fixed 'Page Up/Page Down' keystroke in standard compliant wysiwyg is not working.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4725">#4725</a> : Fixed hitting 'enter' before html comment node produces an JavaScript error.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4522">#4522</a> : Fixed unable to redo when typing after insert an image with relative url.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4594">#4594</a> : Fixed context menu goes off-screen when mouse is at right had side of screen.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4673">#4673</a> : Fixed undo not available straight away if shift key is used to enter first character.</li>
 	</ul>
 	<h3>
Index: /CKEditor/branches/versions/3.1.x/_dev/releaser/ckreleaser.release
===================================================================
--- /CKEditor/branches/versions/3.1.x/_dev/releaser/ckreleaser.release	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_dev/releaser/ckreleaser.release	(revision 4613)
@@ -29,5 +29,10 @@
 		source : '_source/plugins',
 		target : 'plugins',
-		minify : true
+		minify : true,
+		ignore :
+		{
+			sourcePackage : 'ckeditor.pack',
+			files : 'packages[1].files'
+		}
 	},
 
Index: /CKEditor/branches/versions/3.1.x/_dev/releaser/langtool.bat
===================================================================
--- /CKEditor/branches/versions/3.1.x/_dev/releaser/langtool.bat	(revision 4613)
+++ /CKEditor/branches/versions/3.1.x/_dev/releaser/langtool.bat	(revision 4613)
@@ -0,0 +1,6 @@
+::
+:: Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+:: For licensing, see LICENSE.html or http://ckeditor.com/license
+::
+
+java -jar ../langtool/langtool/langtool.jar release/release/_source/lang
Index: /CKEditor/branches/versions/3.1.x/_dev/releaser/langtool.sh
===================================================================
--- /CKEditor/branches/versions/3.1.x/_dev/releaser/langtool.sh	(revision 4613)
+++ /CKEditor/branches/versions/3.1.x/_dev/releaser/langtool.sh	(revision 4613)
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2003-2009, Frederico Caldeira Knabben. All rights reserved.
+# For licensing, see LICENSE.html or http://ckeditor.com/license
+
+if [ -L $0 ] ; then
+    DIR=$(dirname $(readlink -f $0)) ;
+else
+    DIR=$(dirname $0) ;
+fi ;
+
+# pushd $DIR
+java -jar ../langtool/langtool/langtool.jar release/release/_source/lang
+# popd
Index: /CKEditor/branches/versions/3.1.x/_dev/releaser/release.bat
===================================================================
--- /CKEditor/branches/versions/3.1.x/_dev/releaser/release.bat	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_dev/releaser/release.bat	(revision 4613)
@@ -11,3 +11,3 @@
 :: rmdir /S /Q release
 
-java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.0 SVN" ckeditor_3.0_svn
+java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.0 SVN" ckeditor_3.0_svn --run-before-release=langtool.bat
Index: /CKEditor/branches/versions/3.1.x/_dev/releaser/release.sh
===================================================================
--- /CKEditor/branches/versions/3.1.x/_dev/releaser/release.sh	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_dev/releaser/release.sh	(revision 4613)
@@ -10,5 +10,7 @@
 fi ;
 
+LANGTOOL="$(cd $(dirname "$0"); pwd)/langtool.sh"
+
 pushd $DIR
-java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.0 SVN" ckeditor_3.0_svn
+java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.0 SVN" ckeditor_3.0_svn --run-before-release=$LANGTOOL
 popd
Index: /CKEditor/branches/versions/3.1.x/_source/core/dom/range.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/core/dom/range.js	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_source/core/dom/range.js	(revision 4613)
@@ -279,5 +279,5 @@
 					return false;
 				}
-			else
+			else if( node.type == CKEDITOR.NODE_ELEMENT )
 			{
 				// If there are non-empty inline elements (e.g. <img />), then we're not
Index: /CKEditor/branches/versions/3.1.x/_source/plugins/dialog/plugin.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/plugins/dialog/plugin.js	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_source/plugins/dialog/plugin.js	(revision 4613)
@@ -642,10 +642,10 @@
 				addCover( this._.editor );
 
-				CKEDITOR.document.on( 'keydown', accessKeyDownHandler );
-				CKEDITOR.document.on( 'keyup', accessKeyUpHandler );
+				element.on( 'keydown', accessKeyDownHandler );
+				element.on( 'keyup', accessKeyUpHandler );
 
 				// Prevent some keys from bubbling up. (#4269)
 				for ( var event in { keyup :1, keydown :1, keypress :1 } )
-					CKEDITOR.document.on( event, preventKeyBubbling );
+					element.on( event, preventKeyBubbling );
 			}
 			else
@@ -772,11 +772,11 @@
 
 				// Remove access key handlers.
-				CKEDITOR.document.removeListener( 'keydown', accessKeyDownHandler );
-				CKEDITOR.document.removeListener( 'keyup', accessKeyUpHandler );
-				CKEDITOR.document.removeListener( 'keypress', accessKeyUpHandler );
+				element.removeListener( 'keydown', accessKeyDownHandler );
+				element.removeListener( 'keyup', accessKeyUpHandler );
+				element.removeListener( 'keypress', accessKeyUpHandler );
 
 				// Remove bubbling-prevention handler. (#4269)
 				for ( var event in { keyup :1, keydown :1, keypress :1 } )
-					CKEDITOR.document.removeListener( event, preventKeyBubbling );
+					element.removeListener( event, preventKeyBubbling );
 
 				var editor = this._.editor;
Index: /CKEditor/branches/versions/3.1.x/_source/plugins/dialogui/plugin.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/plugins/dialogui/plugin.js	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_source/plugins/dialogui/plugin.js	(revision 4613)
@@ -223,5 +223,8 @@
 								if ( evt.data.getKeystroke() == 13 && keyPressedOnMe )
 								{
-									dialog.getButton( 'ok' ) && dialog.getButton( 'ok' ).click();
+									dialog.getButton( 'ok' ) && setTimeout( function ()
+									{
+										dialog.getButton( 'ok' ).click();
+									}, 0 );
 									keyPressedOnMe = false;
 								}
Index: /CKEditor/branches/versions/3.1.x/_source/plugins/floatpanel/plugin.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/plugins/floatpanel/plugin.js	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_source/plugins/floatpanel/plugin.js	(revision 4613)
@@ -132,5 +132,4 @@
 						top : top + 'px',
 						left : '-3000px',
-						visibility : 'hidden',
 						opacity : '0',	// FF3 is ignoring "visibility"
 						display	: ''
@@ -192,14 +191,7 @@
 							left -= element.$.offsetWidth;
 
-						element.setStyles(
-							{
-								left : left + 'px',
-								visibility	: '',
-								opacity : '1'	// FF3 is ignoring "visibility"
-							});
-
-						if ( block.autoSize )
+						var panelLoad = CKEDITOR.tools.bind( function ()
 						{
-							function setHeight()
+							if ( block.autoSize )
 							{
 								var target = element.getFirst();
@@ -217,14 +209,38 @@
 								panel._.currentBlock.element.setStyle( 'display', 'none' ).removeStyle( 'display' );
 							}
-
-							if ( panel.isLoaded )
-								setHeight();
 							else
-								panel.onLoad = setHeight;
-						}
-						else
-							element.getFirst().removeStyle( 'height' );
-
-						// Set the IFrame focus, so the blur event gets fired.
+								element.getFirst().removeStyle( 'height' );
+
+							var panelElement = panel.element,
+								panelWindow = panelElement.getWindow(),
+								windowScroll = panelWindow.getScrollPosition(),
+								viewportSize = panelWindow.getViewPaneSize(),
+								panelSize =
+								{
+									'height' : panelElement.$.offsetHeight,
+									'width' : panelElement.$.offsetWidth
+								};
+
+							// If the menu is horizontal off, shift it toward
+							// the opposite language direction.
+							if ( rtl ? left < 0 : left + panelSize.width > viewportSize.width + windowScroll.x )
+								left += ( panelSize.width * ( rtl ? 1 : -1 ) );
+
+							// Vertical off screen is simpler.
+							if( top + panelSize.height > viewportSize.height + windowScroll.y )
+								top -= panelSize.height;
+
+							element.setStyles(
+								{
+									top : top + 'px',
+									left : left + 'px',
+									opacity : '1'
+								} );
+
+						} , this );
+
+						panel.isLoaded ? panelLoad() : panel.onLoad = panelLoad;
+
+						// Set the panel frame focus, so the blur event gets fired.
 						CKEDITOR.tools.setTimeout( function()
 							{
@@ -240,10 +256,9 @@
 									}
 								}
-								
+
 								iframe.$.contentWindow.focus();
-
 								// We need this get fired manually because of unfired focus() function.
-								if ( CKEDITOR.env.ie && !CKEDITOR.env.quirks )
-									this.allowBlur( true );
+								this.allowBlur( true );
+
 							}, 0, this);
 					}, 0, this);
Index: /CKEditor/branches/versions/3.1.x/_source/plugins/selection/plugin.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/plugins/selection/plugin.js	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_source/plugins/selection/plugin.js	(revision 4613)
@@ -958,5 +958,14 @@
 				endNode = ranges[ ranges.length - 1 ].endContainer;
 			return startNode.getCommonAncestor( endNode );
-		 }
+		},
+
+		// Moving scroll bar to the current selection's start position.
+		scrollIntoView : function()
+		{
+			// If we have split the block, adds a temporary span at the
+			// range position and scroll relatively to it.
+			var start = this.getStartElement();
+			start.scrollIntoView();
+		}
 	};
 })();
Index: /CKEditor/branches/versions/3.1.x/_source/plugins/undo/plugin.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/plugins/undo/plugin.js	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_source/plugins/undo/plugin.js	(revision 4613)
@@ -131,9 +131,22 @@
 	}
 
+	// Attributes that browser may changing them when setting via innerHTML. 
+	var protectedAttrs = /\b(?:href|src|name)="[^"]*?"/gi;
+
 	Image.prototype =
 	{
 		equals : function( otherImage, contentOnly )
 		{
-			if ( this.contents != otherImage.contents )
+			var thisContents = this.contents,
+				otherContents = otherImage.contents;
+
+			// For IE6/7 : Comparing only the protected attribute values but not the original ones.(#4522)
+			if( CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) )
+			{
+				thisContents = thisContents.replace( protectedAttrs, '' );
+				otherContents = otherContents.replace( protectedAttrs, '' );
+			}
+
+			if( thisContents != otherContents )
 				return false;
 
@@ -180,4 +193,9 @@
 	}
 
+
+	var editingKeyCodes = { /*Backspace*/ 8:1, /*Delete*/ 46:1 },
+		modifierKeyCodes = { /*Shift*/ 16:1, /*Ctrl*/ 17:1, /*Alt*/ 18:1 },
+		navigationKeyCodes = { 37:1, 38:1, 39:1, 40:1 };  // Arrows: L, T, R, B
+
 	UndoManager.prototype =
 	{
@@ -188,30 +206,24 @@
 		type : function( event )
 		{
-			var keystroke = event && event.data.getKeystroke(),
-
-				// Backspace, Delete
-				modifierCodes = { 8:1, 46:1 },
-				// Keystrokes which will modify the contents.
-				isModifier = keystroke in modifierCodes,
-				wasModifier = this.lastKeystroke in modifierCodes,
-				lastWasSameModifier = isModifier && keystroke == this.lastKeystroke,
-
-				// Arrows: L, T, R, B
-				resetTypingCodes = { 37:1, 38:1, 39:1, 40:1 },
+			var keystroke = event && event.data.getKey(),
+				isModifierKey = keystroke in modifierKeyCodes,
+				isEditingKey = keystroke in editingKeyCodes,
+				wasEditingKey = this.lastKeystroke in editingKeyCodes,
+				sameAsLastEditingKey = isEditingKey && keystroke == this.lastKeystroke,
 				// Keystrokes which navigation through contents.
-				isReset = keystroke in resetTypingCodes,
-				wasReset = this.lastKeystroke in resetTypingCodes,
+				isReset = keystroke in navigationKeyCodes,
+				wasReset = this.lastKeystroke in navigationKeyCodes,
 
 				// Keystrokes which just introduce new contents.
-				isContent = ( !isModifier && !isReset ),
+				isContent = ( !isEditingKey && !isReset ),
 
 				// Create undo snap for every different modifier key.
-				modifierSnapshot = ( isModifier && !lastWasSameModifier ),
+				modifierSnapshot = ( isEditingKey && !sameAsLastEditingKey ),
 				// Create undo snap on the following cases:
-				// 1. Just start to type.
+				// 1. Just start to type .
 				// 2. Typing some content after a modifier.
 				// 3. Typing some content after make a visible selection.
-				startedTyping = !this.typing
-					|| ( isContent && ( wasModifier || wasReset ) );
+				startedTyping = !( isModifierKey || this.typing )
+					|| ( isContent && ( wasEditingKey || wasReset ) );
 
 			if ( startedTyping || modifierSnapshot )
@@ -251,6 +263,10 @@
 
 			this.lastKeystroke = keystroke;
+
+			// Ignore modifier keys. (#4673)
+			if( isModifierKey )
+				return;
 			// Create undo snap after typed too much (over 25 times).
-			if ( isModifier )
+			if ( isEditingKey )
 			{
 				this.typesCount = 0;
Index: /CKEditor/branches/versions/3.1.x/_source/plugins/wysiwygarea/plugin.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/plugins/wysiwygarea/plugin.js	(revision 4612)
+++ /CKEditor/branches/versions/3.1.x/_source/plugins/wysiwygarea/plugin.js	(revision 4613)
@@ -184,5 +184,5 @@
 			{
 				var first = fixedBlock.getFirst( isNotEmpty );
-				isNbsp( first ) && first.remove();
+				first && isNbsp( first ) && first.remove();
 			}
 
@@ -470,14 +470,11 @@
 							keystrokeHandler.attach( domDocument );
 
-						// Cancel default action for backspace in IE on control types. (#4047)
 						if ( CKEDITOR.env.ie )
 						{
-							editor.on( 'key', function( event )
-							{
-								if( editor.mode != 'wysiwyg' )
-									return;
-
+							// Cancel default action for backspace in IE on control types. (#4047)
+							domDocument.on( 'keydown', function( evt )
+							{
 								// Backspace.
-								var control = event.data.keyCode == 8
+								var control = evt.data.getKeystroke() == 8
 											  && editor.getSelection().getSelectedElement();
 								if ( control )
@@ -488,7 +485,24 @@
 									control.remove();
 									editor.fire( 'saveSnapshot' );
-									event.cancel();
+									evt.cancel();
 								}
 							} );
+
+							// PageUp/PageDown scrolling is broken in document
+							// with standard doctype, manually fix it. (#4736)
+							if( domDocument.$.compatMode == 'CSS1Compat' )
+							{
+								var pageUpDownKeys = { 33 : 1, 34 : 1 };
+								domDocument.on( 'keydown', function( evt )
+								{
+									if( evt.data.getKeystroke() in pageUpDownKeys )
+									{
+										setTimeout( function ()
+										{
+											editor.getSelection().scrollIntoView();
+										}, 0 );
+									}
+								} );
+							}
 						}
 
