Index: /CKEditor/trunk/_source/core/command.js
===================================================================
--- /CKEditor/trunk/_source/core/command.js	(revision 3328)
+++ /CKEditor/trunk/_source/core/command.js	(revision 3329)
@@ -10,4 +10,7 @@
 		if ( this.state == CKEDITOR.TRISTATE_DISABLED )
 			return false;
+
+		// The editor will always have the focus when executing a command.
+		editor.focus();
 
 		return ( commandDefinition.exec.call( this, editor, data ) !== false );
Index: /CKEditor/trunk/_source/core/dom/document.js
===================================================================
--- /CKEditor/trunk/_source/core/dom/document.js	(revision 3328)
+++ /CKEditor/trunk/_source/core/dom/document.js	(revision 3329)
@@ -74,4 +74,9 @@
 		},
 
+		focus : function()
+		{
+			this.getWindow().focus();
+		},
+
 		/**
 		 * Gets and element based on its id.
Index: /CKEditor/trunk/_source/plugins/clipboard/dialogs/paste.js
===================================================================
--- /CKEditor/trunk/_source/plugins/clipboard/dialogs/paste.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/clipboard/dialogs/paste.js	(revision 3329)
@@ -91,7 +91,4 @@
 			html = html.replace( re, '#');
 
-			this.restoreSelection();
-			this.clearSavedSelection();
-
 			this.getParentEditor().insertHtml( html );
 		},
Index: /CKEditor/trunk/_source/plugins/colorbutton/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/colorbutton/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/colorbutton/plugin.js	(revision 3329)
@@ -13,5 +13,5 @@
 			lang = editor.lang.colorButton;
 
-		var saveRanges;
+		var clickFn;
 
 		addButton( 'TextColor', 'fore', lang.textColorTitle );
@@ -44,18 +44,4 @@
 						keys[ CKEDITOR.SHIFT + 9 ]	= 'prev';	// SHIFT + TAB
 						keys[ 32 ]	= 'click';					// SPACE
-					},
-
-					onOpen : function()
-					{
-						if ( CKEDITOR.env.ie )
-						{
-							editor.focus();
-							saveRanges = editor.getSelection().getRanges();
-						}
-					},
-
-					onClose : function()
-					{
-						saveRanges = null;
 					}
 				});
@@ -78,10 +64,4 @@
 
 					editor.focus();
-
-					if ( saveRanges )
-					{
-						editor.getSelection().selectRanges( saveRanges );
-						saveRanges = false;
-					}
 
 					panel.hide();
Index: /CKEditor/trunk/_source/plugins/contextmenu/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/contextmenu/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/contextmenu/plugin.js	(revision 3329)
@@ -52,19 +52,26 @@
 			else
 			{
+				var unlockFn = function()
+					{
+						editor.getSelection().unlock();
+					};
+
 				menu = this._.menu = new CKEDITOR.menu( editor );
 				menu.onClick = CKEDITOR.tools.bind( function( item )
 				{
+					menu.onHide = null;
+
+					noUnlock = true;
 					menu.hide();
-					editor.focus();
+
+					if ( CKEDITOR.env.ie )
+						menu.onEscape();
 
 					if ( item.onClick )
 						item.onClick();
 					else if ( item.command )
-					{
-						if ( CKEDITOR.env.ie )
-							this.restoreSelection();
+						editor.execCommand( item.command );
 
-						editor.execCommand( item.command );
-					}
+					noUnlock = false;
 				}, this );
 
@@ -72,4 +79,7 @@
 				{
 					editor.focus();
+
+					if ( CKEDITOR.env.ie )
+						editor.getSelection().unlock( true );
 				};
 			}
@@ -80,4 +90,12 @@
 			var selection = this.editor.getSelection(),
 				element = selection && selection.getStartElement();
+
+			// Lock the selection in IE, so it can be restored when closing the
+			// menu.
+			if ( CKEDITOR.env.ie )
+			{
+				selection.lock();
+				menu.onHide = unlockFn;
+			}
 
 			// Call all listeners, filling the list of items to be displayed.
@@ -100,7 +118,4 @@
 				}
 			}
-
-			if ( CKEDITOR.env.ie )
-				this.saveSelection();
 
 			menu.show( offsetParent, editor.lang.dir == 'rtl' ? 2 : 1, offsetX, offsetY );
@@ -141,33 +156,4 @@
 			this.editor.focus();
 			this._.onMenu( CKEDITOR.document.getDocumentElement(), 0, 0 );
-		},
-
-		/**
-		 * Saves the current selection position in the editor.
-		 */
-		saveSelection : function()
-		{
-			if ( this.editor.mode == 'wysiwyg' )
-			{
-				this.editor.focus();
-
-				var selection = new CKEDITOR.dom.selection( this.editor.document );
-				this._.selectedRanges = selection.getRanges();
-			}
-			else
-				delete this._.selectedRanges;
-		},
-
-		/**
-		 * Restores the editor's selection from the previously saved position in this
-		 * dialog.
-		 */
-		restoreSelection : function()
-		{
-			if ( this.editor.mode == 'wysiwyg' && this._.selectedRanges )
-			{
-				this.editor.focus();
-				( new CKEDITOR.dom.selection( this.editor.document ) ).selectRanges( this._.selectedRanges );
-			}
 		}
 	}
Index: /CKEditor/trunk/_source/plugins/dialog/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/dialog/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/dialog/plugin.js	(revision 3329)
@@ -528,4 +528,7 @@
 		show : function()
 		{
+			if ( CKEDITOR.env.ie )
+				this._.editor.getSelection().lock();
+
 			// Insert the dialog's element to the root document.
 			var element = this._.element;
@@ -580,8 +583,4 @@
 					} );
 
-			// Save editor selection and grab the focus.
-			if ( !this._.parentDialog )
-				this.saveSelection();
-
 			// Reset the hasFocus state.
 			this._.hasFocus = false;
@@ -679,7 +678,9 @@
 				CKEDITOR.document.removeListener( 'keyup', accessKeyUpHandler );
 
-				// Restore focus and (if not already restored) selection in the editing area.
-				this.restoreSelection();
-				this._.editor.focus();
+				var editor = this._.editor;
+				editor.focus();
+
+				if ( CKEDITOR.env.ie )
+					editor.getSelection().unlock( true );
 			}
 			else
@@ -928,56 +929,10 @@
 
 		/**
-		 * Saves the current selection position in the editor.
-		 * This function is automatically called when a non-nested dialog is opened,
-		 * but it may also be called by event handlers in dialog definition.
-		 * @example
-		 */
-		saveSelection : function()
-		{
-			if ( this._.editor.mode )
-			{
-				this._.editor.focus();
-
-				var selection = new CKEDITOR.dom.selection( this._.editor.document );
-				this._.selectedRanges = selection.getRanges();
-				this._.selectedElement = selection.getSelectedElement();
-			}
-		},
-
-		/**
-		 * Clears the saved selection in the dialog object.
-		 * This function should be called if the dialog's code has already changed the
-		 * current selection position because the dialog closed. (e.g. at onOk())
-		 * @example
-		 */
-		clearSavedSelection : function()
-		{
-			delete this._.selectedRanges;
-			delete this._.selectedElement;
-		},
-
-		/**
-		 * Gets the saved control selection. Control selections should be retrieved
-		 * with this function instead of from restoreSelection() because
-		 * restoreSelection() does not properly restore control selections.
-		 * @returns {CKEDITOR.dom.element} The element that was selected.
-		 * @example
+		 * Gets the element that was selected when opening the dialog, if any.
+		 * @returns {CKEDITOR.dom.element} The element that was selected, or null.
 		 */
 		getSelectedElement : function()
 		{
-			return this._.selectedElement;
-		},
-
-		/**
-		 * Restores the editor's selection from the previously saved position in this
-		 * dialog.
-		 * This function is automatically called when a non-nested dialog is closed,
-		 * but it may also be called by event handlers in dialog definition.
-		 * @example
-		 */
-		restoreSelection : function()
-		{
-			if ( this._.editor.mode && this._.selectedRanges )
-				( new CKEDITOR.dom.selection( this._.editor.document ) ).selectRanges( this._.selectedRanges );
+			return this.getParentEditor().getSelection().getSelectedElement();
 		}
 	};
Index: /CKEditor/trunk/_source/plugins/find/dialogs/find.js
===================================================================
--- /CKEditor/trunk/_source/plugins/find/dialogs/find.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/find/dialogs/find.js	(revision 3329)
@@ -536,7 +536,4 @@
 		function getStartCursor()
 		{
-			if ( CKEDITOR.env.ie )
-				this.restoreSelection();
-
 			var sel = editor.getSelection();
 			if ( sel )
@@ -799,4 +796,5 @@
 				{
 					finder.range.removeHighlight();
+					editor.focus();
 					editor.getSelection().selectRanges(
 						[ finder.range.toDomRange() ] );
Index: /CKEditor/trunk/_source/plugins/flash/dialogs/flash.js
===================================================================
--- /CKEditor/trunk/_source/plugins/flash/dialogs/flash.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/flash/dialogs/flash.js	(revision 3329)
@@ -280,8 +280,5 @@
 					newFakeImage.replace( this.fakeImage );
 				else
-				{
-					this.restoreSelection();
 					editor.insertElement( newFakeImage );
-				}
 			},
 			
Index: /CKEditor/trunk/_source/plugins/font/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/font/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/font/plugin.js	(revision 3329)
@@ -9,5 +9,4 @@
 	{
 		var config = editor.config;
-		var saveRanges;
 
 		// Gets the list of fonts from the settings.
@@ -58,10 +57,4 @@
 					editor.fire( 'saveSnapshot' );
 
-					if ( saveRanges )
-					{
-						editor.getSelection().selectRanges( saveRanges );
-						saveRanges = false;
-					}
-
 					var style = styles[ value ];
 
@@ -103,18 +96,4 @@
 						},
 						this);
-				},
-
-				onOpen : function()
-				{
-					if ( CKEDITOR.env.ie )
-					{
-						editor.focus();
-						saveRanges = editor.getSelection().getRanges();
-					}
-				},
-
-				onClose : function()
-				{
-					saveRanges = null;
 				}
 			});
Index: /CKEditor/trunk/_source/plugins/format/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/format/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/format/plugin.js	(revision 3329)
@@ -12,6 +12,4 @@
 		var config = editor.config,
 			lang = editor.lang.format;
-
-		var saveRanges;
 
 		// Gets the list of tags from the settings.
@@ -56,10 +54,4 @@
 					editor.fire( 'saveSnapshot' );
 
-					if ( saveRanges )
-					{
-						editor.getSelection().selectRanges( saveRanges );
-						saveRanges = false;
-					}
-
 					styles[ value ].apply( editor.document );
 				},
@@ -87,18 +79,4 @@
 						},
 						this);
-				},
-
-				onOpen : function()
-				{
-					if ( CKEDITOR.env.ie )
-					{
-						editor.focus();
-						saveRanges = editor.getSelection().getRanges();
-					}
-				},
-
-				onClose : function()
-				{
-					saveRanges = null;
 				}
 			});
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/button.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/button.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/button.js	(revision 3329)
@@ -11,8 +11,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			var element = this.getParentEditor().getSelection().getSelectedElement();
 			if ( element && element.getName() == "input" )
@@ -40,9 +36,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/checkbox.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/checkbox.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/checkbox.js	(revision 3329)
@@ -11,8 +11,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			var element = this.getParentEditor().getSelection().getSelectedElement();
 
@@ -39,9 +35,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
@@ -61,5 +53,4 @@
 						{
 							this.setValue( element.getAttribute( 'name' ) );
-							this.focus();
 						},
 						commit : function( element )
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/form.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/form.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/form.js	(revision 3329)
@@ -11,8 +11,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			var element = this.getParentEditor().getSelection().getSelectedElement();
 			if ( element && element.getName() == "form" )
@@ -37,9 +33,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/hiddenfield.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/hiddenfield.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/hiddenfield.js	(revision 3329)
@@ -11,8 +11,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			var element = this.getParentEditor().getSelection().getSelectedElement();
 			if ( element && element.getName() == "input" && element.getAttribute( 'type' ) == "checkbox" )
@@ -37,9 +33,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/radio.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/radio.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/radio.js	(revision 3329)
@@ -11,8 +11,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			var element = this.getParentEditor().getSelection().getSelectedElement();
 			if ( element && element.getName() == "input" && element.getAttribute( 'type' ) == "radio" )
@@ -37,9 +33,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/select.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/select.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/select.js	(revision 3329)
@@ -136,8 +136,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			this.setupContent( 'clear' );
 			var element = this.getParentEditor().getSelection().getSelectedElement();
@@ -164,9 +160,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/textarea.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/textarea.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/textarea.js	(revision 3329)
@@ -11,8 +11,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			var element = this.getParentEditor().getSelection().getSelectedElement();
 			if ( element && element.getName() == "textarea" )
@@ -36,9 +32,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
Index: /CKEditor/trunk/_source/plugins/forms/dialogs/textfield.js
===================================================================
--- /CKEditor/trunk/_source/plugins/forms/dialogs/textfield.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/forms/dialogs/textfield.js	(revision 3329)
@@ -11,8 +11,4 @@
 		onShow : function()
 		{
-			// IE BUG: Selection must be in the editor for getSelectedElement()
-			// to work.
-			this.restoreSelection();
-
 			var element = this.getParentEditor().getSelection().getSelectedElement();
 			if ( element && element.getName() == "input" && ( element.getAttribute( 'type' ) == "text" || !element.getAttribute( 'type' ) ) )
@@ -37,9 +33,5 @@
 
 			if ( isInsertMode )
-			{
-				this.restoreSelection();
-				this.clearSavedSelection();
 				editor.insertElement( element );
-			}
 		},
 		contents : [
Index: /CKEditor/trunk/_source/plugins/image/dialogs/image.js
===================================================================
--- /CKEditor/trunk/_source/plugins/image/dialogs/image.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/image/dialogs/image.js	(revision 3329)
@@ -208,8 +208,4 @@
 				// Preview
 				this.preview = CKEDITOR.document.getById( 'previewImage' );
-
-				// IE BUG: Selection must be in the editor for getSelectedElement()
-				// to work.
-				this.restoreSelection();
 
 				var editor = this.getParentEditor(),
@@ -309,14 +305,7 @@
 				this.commitContent( LINK, this.linkElement );
 
-				this.restoreSelection();
-				this.clearSavedSelection();
-
 				// Insert a new Image.
 				if ( !this.imageEditMode )
 				{
-					// It doesn't work with IE.
-					this.restoreSelection();
-					this.clearSavedSelection();
-
 					if ( this.addLink )
 					{
Index: /CKEditor/trunk/_source/plugins/link/dialogs/anchor.js
===================================================================
--- /CKEditor/trunk/_source/plugins/link/dialogs/anchor.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/link/dialogs/anchor.js	(revision 3329)
@@ -9,5 +9,4 @@
 	var loadElements = function( editor, selection, ranges, element )
 	{
-		this.saveSelection();
 		this.editMode = true;
 		this.editObj = element;
@@ -46,12 +45,13 @@
 			if ( !this.editMode )
 			{
-				// It doesn't work with IE.
-				this.restoreSelection();
-				this.clearSavedSelection();
-
 				editor.insertElement( fakeElement );
 			}
 			else
+			{
 				fakeElement.replace( this.fakeObj );
+
+				editor.getSelection().selectElement( fakeElement );
+			}
+			
 			return true;
 		},
@@ -61,7 +61,4 @@
 			this.fakeObj = false;
 			this.editMode = false;
-
-			// IE BUG: Selection must be in the editor for getSelection() to work.
-			this.restoreSelection();
 
 			var editor = this.getParentEditor(),
@@ -80,5 +77,4 @@
 					loadElements.apply( this, [ editor, selection, ranges, element ] );
 					selection.selectElement( this.fakeObj );
-					this.saveSelection();
 				}
 			}
Index: /CKEditor/trunk/_source/plugins/link/dialogs/link.js
===================================================================
--- /CKEditor/trunk/_source/plugins/link/dialogs/link.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/link/dialogs/link.js	(revision 3329)
@@ -991,6 +991,5 @@
 		{
 			this.fakeObj = false;
-			// IE BUG: Selection must be in the editor for getSelection() to work.
-			this.restoreSelection();
+
 			var editor = this.getParentEditor(),
 				selection = editor.getSelection(),
@@ -1009,5 +1008,4 @@
 				{
 					selection.selectElement( element );
-					this.saveSelection();
 				}
 				else
@@ -1019,5 +1017,4 @@
 						element = editor.restoreRealElement( this.fakeObj );
 						selection.selectElement( this.fakeObj );
-						this.saveSelection();
 					}
 				}
@@ -1128,8 +1125,4 @@
 			if ( !this._.selectedElement )
 			{
-				// IE BUG: Selection must be in the editor for getSelection() to work.
-				this.restoreSelection();
-				this.clearSavedSelection();
-
 				// Create element if current selection is collapsed.
 				var selection = editor.getSelection(),
@@ -1174,5 +1167,4 @@
 							editor.document );
 
-					this.restoreSelection();
 					selection = editor.getSelection();
 
@@ -1182,5 +1174,4 @@
 					element = newElement;
 
-					this.clearSavedSelection();
 					selection.selectElement( element );
 				}
Index: /CKEditor/trunk/_source/plugins/menu/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/menu/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/menu/plugin.js	(revision 3329)
@@ -128,6 +128,12 @@
 					panel.onEscape = CKEDITOR.tools.bind( function()
 					{
+						this.onEscape && this.onEscape();
 						this.hide();
-						this.onEscape && this.onEscape();
+					},
+					this );
+
+					panel.onHide = CKEDITOR.tools.bind( function()
+					{
+						this.onHide && this.onHide();
 					},
 					this );
Index: /CKEditor/trunk/_source/plugins/pastefromword/dialogs/pastefromword.js
===================================================================
--- /CKEditor/trunk/_source/plugins/pastefromword/dialogs/pastefromword.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/pastefromword/dialogs/pastefromword.js	(revision 3329)
@@ -184,5 +184,4 @@
 						this.getValueOf( 'general', 'removeStyle' ) );
 
-			this.restoreSelection();
 			editor.insertHtml( html );
 		},
Index: /CKEditor/trunk/_source/plugins/pastetext/dialogs/pastetext.js
===================================================================
--- /CKEditor/trunk/_source/plugins/pastetext/dialogs/pastetext.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/pastetext/dialogs/pastetext.js	(revision 3329)
@@ -26,8 +26,4 @@
 					// Get the textarea value.
 					var text = CKEDITOR.document.getById( textareaId ).getValue();
-
-					// Restore the editing area selection.
-					this.restoreSelection();
-					this.clearSavedSelection();
 
 					// Inserts the text.
Index: /CKEditor/trunk/_source/plugins/pastetext/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/pastetext/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/pastetext/plugin.js	(revision 3329)
@@ -1,3 +1,3 @@
-/*
+﻿/*
 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.html or http://ckeditor.com/license
@@ -22,8 +22,4 @@
 				return;
 			}
-
-			// Check if the selection is inside the editing area for IE. (#3216)
-			if ( !editor.getSelection() )
-				editor.focus();
 
 			editor.insertText( window.clipboardData.getData( 'Text' ) );
Index: /CKEditor/trunk/_source/plugins/selection/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/selection/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/selection/plugin.js	(revision 3329)
@@ -11,25 +11,31 @@
 	// the current node and check it on successive requests. If there is any
 	// change on the tree, then the selectionChange event gets fired.
-	var checkSelectionChange = function()
+	function checkSelectionChange()
 	{
-		// In IE, the "selectionchange" event may still get thrown when
-		// releasing the WYSIWYG mode, so we need to check it first.
-		var sel = this.getSelection();
-		if ( !sel )
-			return;
-
-		var firstElement = sel.getStartElement();
-		var currentPath = new CKEDITOR.dom.elementPath( firstElement );
-
-		if ( !currentPath.compare( this._.selectionPreviousPath ) )
-		{
-			this._.selectionPreviousPath = currentPath;
-			this.fire( 'selectionChange', { selection : sel, path : currentPath, element : firstElement } );
+		try
+		{
+			// In IE, the "selectionchange" event may still get thrown when
+			// releasing the WYSIWYG mode, so we need to check it first.
+			var sel = this.getSelection();
+			if ( !sel )
+				return;
+
+			var firstElement = sel.getStartElement();
+			var currentPath = new CKEDITOR.dom.elementPath( firstElement );
+
+			if ( !currentPath.compare( this._.selectionPreviousPath ) )
+			{
+				this._.selectionPreviousPath = currentPath;
+				this.fire( 'selectionChange', { selection : sel, path : currentPath, element : firstElement } );
+			}
 		}
+		catch (e)
+		{}
 	};
 
-	var checkSelectionChangeTimer;
-	var checkSelectionChangeTimeoutPending;
-	var checkSelectionChangeTimeout = function()
+	var checkSelectionChangeTimer,
+		checkSelectionChangeTimeoutPending;
+
+	function checkSelectionChangeTimeout()
 	{
 		// Firing the "OnSelectionChange" event on every key press started to
@@ -45,7 +51,7 @@
 
 		checkSelectionChangeTimer = CKEDITOR.tools.setTimeout( checkSelectionChangeTimeoutExec, 200, this );
-	};
-
-	var checkSelectionChangeTimeoutExec = function()
+	}
+
+	function checkSelectionChangeTimeoutExec()
 	{
 		checkSelectionChangeTimer = null;
@@ -61,5 +67,5 @@
 			checkSelectionChangeTimeoutPending = false;
 		}
-	};
+	}
 
 	// #### checkSelectionChange : END
@@ -86,9 +92,122 @@
 			editor.on( 'contentDom', function()
 				{
+					var doc = editor.document;
+
 					if ( CKEDITOR.env.ie )
 					{
+						// Other browsers don't loose the selection if the
+						// editor document loose the focus. In IE, we don't
+						// have support for it, so we reproduce it here, other
+						// than firing the selection change event.
+
+						var savedRange,
+							saveEnabled;
+
+						// "onfocusin" is fired before "onfocus". It makes it
+						// possible to restore the selection before click
+						// events get executed.
+						doc.on( 'focusin', function()
+							{
+								// If we have saved a range, restore it at this
+								// point.
+								if ( savedRange )
+								{
+									// Well not break because of this.
+									try
+									{
+										savedRange.select();
+									}
+									catch (e)
+									{}
+
+									savedRange = null;
+								}
+							});
+
+						editor.window.on( 'focus', function()
+							{
+								// Enable selections to be saved.
+								saveEnabled = true;
+
+								saveSelection();
+							});
+
+						editor.window.on( 'blur', function()
+							{
+								// Disable selections from being saved.
+								saveEnabled = false;
+
+								// IE may leave the selection still inside the
+								// document. Let's force it to be removed.
+								// TODO: The following has effect for
+								// collapsed selections.
+								editor.document.$.execCommand( 'Unselect' );
+							});
+
+						// IE fires the "selectionchange" event when clicking
+						// inside a selection. We don't want to capture that.
+						doc.on( 'mousedown', disableSave );
+						doc.on( 'mouseup',
+							function()
+							{
+								saveEnabled = true;
+								setTimeout( function()
+									{
+										saveSelection( true );
+									},
+									0 );
+							});
+
+						doc.on( 'keydown', disableSave );
+						doc.on( 'keyup',
+							function()
+							{
+								saveEnabled = true;
+								saveSelection();
+							});
+
+
 						// IE is the only to provide the "selectionchange"
 						// event.
-						editor.document.on( 'selectionchange', checkSelectionChangeTimeout, editor );
+						doc.on( 'selectionchange', saveSelection );
+
+						function disableSave()
+						{
+							saveEnabled = false;
+						}
+
+						function saveSelection( testIt )
+						{
+							if ( saveEnabled )
+							{
+								var doc = editor.document,
+									sel = doc && doc.$.selection;
+
+								// There is a very specific case, when clicking
+								// inside a text selection. In that case, the
+								// selection collapses at the clicking point,
+								// but the selection object remains in an
+								// unknown state, making createRange return a
+								// range at the very start of the document. In
+								// such situation we have to test the range, to
+								// be sure it's valid.
+								if ( testIt && sel && sel.type == 'None' )
+								{
+									// The "InsertImage" command can be used to
+									// test whether the selection is good or not.
+									// If not, it's enough to give some time to
+									// IE to put things in order for us.
+									if ( !doc.$.queryCommandEnabled( 'InsertImage' ) )
+									{
+										CKEDITOR.tools.setTimeout( saveSelection, 50, this, true );
+										return;
+									}
+								}
+
+								savedRange = sel && sel.createRange();
+
+								checkSelectionChangeTimeout.call( editor );
+							}
+						}
 					}
 					else
@@ -98,6 +217,6 @@
 						// press.
 
-						editor.document.on( 'mouseup', checkSelectionChangeTimeout, editor );
-						editor.document.on( 'keyup', checkSelectionChangeTimeout, editor );
+						doc.on( 'mouseup', checkSelectionChangeTimeout, editor );
+						doc.on( 'keyup', checkSelectionChangeTimeout, editor );
 					}
 				});
@@ -124,22 +243,5 @@
 	CKEDITOR.editor.prototype.getSelection = function()
 	{
-		var retval = this.document ? this.document.getSelection() : null;
-
-		/**
-		 * IE BUG: The selection's document may be a different document than the
-		 * editor document. Return null if that's the case.
-		 */
-		if ( retval && CKEDITOR.env.ie )
-		{
-			var range = retval.getNative().createRange();
-			if ( !range )
-				return null;
-			else if ( range.item )
-				return range.item(0).ownerDocument == this.document.$ ? retval : null;
-			else
-				return range.parentElement().ownerDocument == this.document.$ ? retval : null;
-		}
-
-		return retval;
+		return this.document && this.document.getSelection();
 	};
 
@@ -195,9 +297,32 @@
 	CKEDITOR.dom.selection = function( document )
 	{
+		var lockedSelection = document.getCustomData( 'cke_locked_selection' );
+
+		if ( lockedSelection )
+			return lockedSelection;
+
 		this.document = document;
+		this.isLocked = false;
 		this._ =
 		{
 			cache : {}
 		};
+
+		/**
+		 * IE BUG: The selection's document may be a different document than the
+		 * editor document. Return null if that's the case.
+		 */
+		if ( CKEDITOR.env.ie )
+		{
+			var range = this.getNative().createRange();
+			if ( !range 
+				|| ( range.item && range.item(0).ownerDocument != this.document.$ )
+				|| ( range.parentElement && range.parentElement().ownerDocument != this.document.$ ) )
+			{
+				return null;
+			}
+		}
+		
+		return this;
 	};
 
@@ -251,6 +376,7 @@
 				function()
 				{
-					if ( this._.cache.type )
-						return this._.cache.type;
+					var cache = this._.cache;
+					if ( cache.type )
+						return cache.type;
 
 					var type = CKEDITOR.SELECTION_NONE;
@@ -276,11 +402,12 @@
 					catch(e) {}
 
-					return ( this._.cache.type = type );
+					return ( cache.type = type );
 				}
 			:
 				function()
 				{
-					if ( this._.cache.type )
-						return this._.cache.type;
+					var cache = this._.cache;
+					if ( cache.type )
+						return cache.type;
 
 					var type = CKEDITOR.SELECTION_TEXT;
@@ -307,5 +434,5 @@
 					}
 
-					return ( this._.cache.type = type );
+					return ( cache.type = type );
 				},
 
@@ -383,6 +510,7 @@
 					return function()
 					{
-						if ( this._.cache.ranges )
-							return this._.cache.ranges;
+						var cache = this._.cache;
+						if ( cache.ranges )
+							return cache.ranges;
 
 						// IE doesn't have range support (in the W3C way), so we
@@ -405,5 +533,5 @@
 							range.setEnd( new CKEDITOR.dom.node( boundaryInfo.container ), boundaryInfo.offset );
 
-							return ( this._.cache.ranges = [ range ] );
+							return ( cache.ranges = [ range ] );
 						}
 						else if ( type == CKEDITOR.SELECTION_ELEMENT )
@@ -430,5 +558,5 @@
 						}
 
-						return ( this._.cache.ranges = [] );
+						return ( cache.ranges = [] );
 					};
 				})()
@@ -436,6 +564,7 @@
 				function()
 				{
-					if ( this._.cache.ranges )
-						return this._.cache.ranges;
+					var cache = this._.cache;
+					if ( cache.ranges )
+						return cache.ranges;
 
 					// On browsers implementing the W3C range, we simply
@@ -456,5 +585,5 @@
 					}
 
-					return ( this._.cache.ranges = ranges );
+					return ( cache.ranges = ranges );
 				},
 
@@ -469,4 +598,8 @@
 		getStartElement : function()
 		{
+			var cache = this._.cache;
+			if ( cache.startElement !== undefined )
+				return cache.startElement;
+
 			var node,
 				sel = this.getNative();
@@ -524,5 +657,5 @@
 			}
 
-			return ( node ? new CKEDITOR.dom.element( node ) : null );
+			return cache.startElement = ( node ? new CKEDITOR.dom.element( node ) : null );
 		},
 
@@ -538,4 +671,8 @@
 		getSelectedElement : function()
 		{
+			var cache = this._.cache;
+			if ( cache.selectedElement !== undefined )
+				return cache.selectedElement;
+
 			var node;
 
@@ -559,5 +696,54 @@
 			}
 
-			return ( node ? new CKEDITOR.dom.element( node ) : null );
+			return cache.selectedElement = ( node ? new CKEDITOR.dom.element( node ) : null );
+		},
+		
+		lock : function()
+		{
+			// Call all cacheable function.
+			this.getRanges();
+			this.getStartElement();
+			this.getSelectedElement();
+
+			// The native selection is not available when locked.
+			this._.cache.nativeSel = {};
+
+			this.isLocked = true;
+
+			// Save this selection inside the DOM document.
+			this.document.setCustomData( 'cke_locked_selection', this );
+		},
+		
+		unlock : function( restore )
+		{
+			var doc = this.document,
+				lockedSelection = doc.getCustomData( 'cke_locked_selection' );
+
+			if ( lockedSelection )
+			{
+				doc.setCustomData( 'cke_locked_selection', null );
+
+				if ( restore )
+				{
+					var selectedElement = lockedSelection.getSelectedElement(),
+						ranges = !selectedElement && lockedSelection.getRanges();
+
+					this.isLocked = false;
+					this.reset();
+
+					doc.getBody().focus();
+					
+					if ( selectedElement )
+						this.selectElement( selectedElement );
+					else
+						this.selectRanges( ranges );
+				}
+			}
+
+			if  ( !lockedSelection || !restore )
+			{
+				this.isLocked = false;
+				this.reset();
+			}
 		},
 
@@ -567,65 +753,97 @@
 		},
 
-		selectElement :
-			CKEDITOR.env.ie ?
-				function( element )
-				{
-					this.getNative().empty();
-
-					var range;
-					try
-					{
-						// Try to select the node as a control.
-						range = this.document.$.body.createControlRange();
-						range.addElement( element.$ );
-					}
-					catch(e)
-					{
-						// If failed, select it as a text range.
-						range = this.document.$.body.createTextRange();
-						range.moveToElementText( element.$ );
-					}
-
-					range.select();
+		selectElement : function( element )
+		{
+			if ( this.isLocked )
+			{
+				var range = new CKEDITOR.dom.range();
+				range.setStartBefore( element );
+				range.setEndAfter( element );
+			
+				this._.cache.selectedElement = element;
+				this._.cache.startElement = element;
+				this._.cache.ranges = [ range ];
+				this._.cache.type = CKEDITOR.SELECTION_ELEMENT;
+				
+				return;
+			}
+
+			if ( CKEDITOR.env.ie )
+			{
+				this.getNative().empty();
+
+				var range;
+				try
+				{
+					// Try to select the node as a control.
+					range = this.document.$.body.createControlRange();
+					range.addElement( element.$ );
 				}
-			:
-				function( element )
-				{
-					// Create the range for the element.
-					var range = this.document.$.createRange();
-					range.selectNode( element.$ );
+				catch(e)
+				{
+					// If failed, select it as a text range.
+					range = this.document.$.body.createTextRange();
+					range.moveToElementText( element.$ );
+				}
+
+				range.select();
+
+				this.reset();
+			}
+			else
+			{
+				// Create the range for the element.
+				var range = this.document.$.createRange();
+				range.selectNode( element.$ );
+
+				// Select the range.
+				var sel = this.getNative();
+				sel.removeAllRanges();
+				sel.addRange( range );
+
+				this.reset();
+			}
+		},
+
+		selectRanges : function( ranges )
+		{
+			if ( this.isLocked )
+			{
+				this._.cache.selectedElement = null;
+				this._.cache.startElement = ranges[ 0 ].getTouchedStartNode();
+				this._.cache.ranges = ranges;
+				this._.cache.type = CKEDITOR.SELECTION_TEXT;
+				
+				return;
+			}
+
+			if ( CKEDITOR.env.ie )
+			{
+				// IE doesn't accept multiple ranges selection, so we just
+				// select the first one.
+				if ( ranges[ 0 ] )
+					ranges[ 0 ].select();
+
+				this.reset();
+			}
+			else
+			{
+				var sel = this.getNative();
+				sel.removeAllRanges();
+
+				for ( var i = 0 ; i < ranges.length ; i++ )
+				{
+					var range = ranges[ i ];
+					var nativeRange = this.document.$.createRange();
+					nativeRange.setStart( range.startContainer.$, range.startOffset );
+					nativeRange.setEnd( range.endContainer.$, range.endOffset );
 
 					// Select the range.
-					var sel = this.getNative();
-					sel.removeAllRanges();
-					sel.addRange( range );
-				},
-
-		selectRanges :
-			CKEDITOR.env.ie ?
-				function( ranges )
-				{
-					// IE doesn't accept multiple ranges selection, so we just
-					// select the first one.
-					if ( ranges[ 0 ] )
-						ranges[ 0 ].select();
+					sel.addRange( nativeRange );
 				}
-			:
-				function( ranges )
-				{
-					var sel = this.getNative();
-					sel.removeAllRanges();
-
-					for ( var i = 0 ; i < ranges.length ; i++ )
-					{
-						var range = ranges[ i ];
-						var nativeRange = this.document.$.createRange();
-						nativeRange.setStart( range.startContainer.$, range.startOffset );
-						nativeRange.setEnd( range.endContainer.$, range.endOffset );
-
-						// Select the range.
-						sel.addRange( nativeRange );
-					}
-				},
+
+				this.reset();
+			}
+		},
 
 		createBookmarks : function( serializable )
Index: /CKEditor/trunk/_source/plugins/smiley/dialogs/smiley.js
===================================================================
--- /CKEditor/trunk/_source/plugins/smiley/dialogs/smiley.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/smiley/dialogs/smiley.js	(revision 3329)
@@ -55,6 +55,4 @@
 				return;
 
-			this.getDialog().restoreSelection();
-
 			var src = target.getAttribute( 'src' ),
 				title = target.getAttribute( 'title' );
Index: /CKEditor/trunk/_source/plugins/specialchar/dialogs/specialchar.js
===================================================================
--- /CKEditor/trunk/_source/plugins/specialchar/dialogs/specialchar.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/specialchar/dialogs/specialchar.js	(revision 3329)
@@ -129,5 +129,4 @@
 										var dialog = this.getDialog();
 										target.removeClass( "LightBackground" );
-										dialog.restoreSelection();
 										dialog.getParentEditor().insertHtml( value );
 										dialog.hide();
Index: /CKEditor/trunk/_source/plugins/stylescombo/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/stylescombo/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/stylescombo/plugin.js	(revision 3329)
@@ -15,6 +15,5 @@
 				lang = editor.lang.stylesCombo,
 				pluginPath = this.path,
-				styles,
-				saveRanges;
+				styles;
 
 			editor.ui.addRichCombo( 'Styles',
@@ -98,10 +97,4 @@
 						var style = styles[ value ],
 							selection = editor.getSelection();
-
-						if ( saveRanges )
-						{
-							selection.selectRanges( saveRanges );
-							saveRanges = false;
-						}
 
 						if ( style.type == CKEDITOR.STYLE_OBJECT )
@@ -161,7 +154,4 @@
 						var selection = editor.getSelection();
 
-						if ( CKEDITOR.env.ie && selection )
-							saveRanges = selection.getRanges();
-
 						var elementPath,
 							element = selection.getSelectedElement(),
@@ -220,9 +210,4 @@
 						if ( !counter[ CKEDITOR.STYLE_OBJECT ] )
 							this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_OBJECT ) ] );
-					},
-
-					onClose : function()
-					{
-						saveRanges = null;
 					}
 				});
Index: /CKEditor/trunk/_source/plugins/table/dialogs/table.js
===================================================================
--- /CKEditor/trunk/_source/plugins/table/dialogs/table.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/table/dialogs/table.js	(revision 3329)
@@ -90,5 +90,4 @@
 			{
 				// Detect if there's a selected table.
-				this.restoreSelection();
 				var selection = editor.getSelection(),
 					ranges = selection.getRanges(),
@@ -100,5 +99,5 @@
 				if ( command == 'tableProperties' )
 				{
-					if ( ( selectedTable = this.getSelectedElement() ) )
+					if ( ( selectedTable = editor.getSelection().getSelectedElement() ) )
 					{
 						if ( selectedTable.getName() != 'table' )
@@ -247,9 +246,5 @@
 				// Insert the table element if we're creating one.
 				if ( !this._.selectedElement )
-				{
-					this.restoreSelection();
 					editor.insertElement( table );
-					this.clearSavedSelection();
-				}
 
 				return true;
Index: /CKEditor/trunk/_source/plugins/templates/dialogs/templates.js
===================================================================
--- /CKEditor/trunk/_source/plugins/templates/dialogs/templates.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/templates/dialogs/templates.js	(revision 3329)
@@ -86,11 +86,7 @@
 		else
 		{
-			if( CKEDITOR.env.ie )
-				dialog.restoreSelection();
-
 			editor.insertHtml( html );
 		}
 
-		dialog.clearSavedSelection();
 		dialog.hide();
 	}
Index: /CKEditor/trunk/_source/plugins/wsc/dialogs/wsc.js
===================================================================
--- /CKEditor/trunk/_source/plugins/wsc/dialogs/wsc.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/wsc/dialogs/wsc.js	(revision 3329)
@@ -98,6 +98,4 @@
 			onFinish : function( dT )
 			{
-				dialog.restoreSelection();
-				dialog.clearSavedSelection();
 				dialog.getParentEditor().setData( dT.value );
 				dialog.hide();
Index: /CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js	(revision 3328)
+++ /CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js	(revision 3329)
@@ -15,5 +15,7 @@
 		if ( this.mode == 'wysiwyg' )
 		{
-			var $doc = this.document.$,
+			this.focus();
+				
+			var selection = this.getSelection(),
 				data = evt.data;
 
@@ -22,5 +24,18 @@
 
 			if ( CKEDITOR.env.ie )
-				$doc.selection.createRange().pasteHTML( data );
+			{
+				var selIsLocked = selection.isLocked;
+				
+				if ( selIsLocked )
+					selection.unlock();
+				
+				var $sel = selection.getNative();
+				if ( $sel.type == 'Control' )
+					$sel.clear();
+				$sel.createRange().pasteHTML( data );
+				
+				if ( selIsLocked )
+					this.getSelection().lock();
+			}
 			else
 				$doc.execCommand( 'inserthtml', false, data );
@@ -32,4 +47,6 @@
 		if ( this.mode == 'wysiwyg' )
 		{
+			this.focus();
+
 			var element = evt.data,
 				elementName = element.getName(),
@@ -38,4 +55,9 @@
 			var selection = this.getSelection(),
 				ranges = selection.getRanges();
+
+			var selIsLocked = selection.isLocked;
+
+			if ( selIsLocked )
+				selection.unlock();
 
 			var range, clone, lastElement, bookmark;
@@ -88,4 +110,7 @@
 
 			selection.selectRanges( [ range ] );
+
+			if ( selIsLocked )
+				this.getSelection().lock();
 		}
 	}
