Index: CKEditor/trunk/_source/plugins/undo/plugin.js
===================================================================
--- CKEditor/trunk/_source/plugins/undo/plugin.js	(revision 3642)
+++ CKEditor/trunk/_source/plugins/undo/plugin.js	(revision 3643)
@@ -83,5 +83,5 @@
 									// Do not capture CTRL hotkeys.
 									if ( !event.data.$.ctrlKey && !event.data.$.metaKey )
-										undoManager.type();
+										undoManager.type( event );
 								});
 
@@ -168,4 +168,5 @@
 	{
 		this.typesCount = 0;
+		this.modifiersCount = 0;
 
 		this.editor = editor;
@@ -183,11 +184,47 @@
 
 		this.limit = editor.config.undoStackSize;
+
+		/**
+		 * Remember last pressed key.
+		 */
+		this.lastKeystroke = 0;
 	}
 
 	UndoManager.prototype =
 	{
-		type : function()
-		{
-			if ( !this.typing )
+		/**
+		 * Process undo system regard keystrikes.
+		 * @param {CKEDITOR.dom.event} event
+		 */
+		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 },
+				// Keystrokes which navigation through contents.
+				isReset = keystroke in resetTypingCodes,
+				wasReset = this.lastKeystroke in resetTypingCodes,
+
+				// Keystrokes which just introduce new contents.
+				isContent = ( !isModifier && !isReset ),
+
+				// Create undo snap for every different modifier key.
+				modifierSnapshot = ( isModifier && !lastWasSameModifier ),
+				// Create undo snap on the following cases:
+				// 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 ) );
+
+			if ( startedTyping || modifierSnapshot )
 			{
 				var beforeTypeImage = new Image( this.editor );
@@ -205,9 +242,9 @@
 						if ( beforeTypeImage.contents != currentSnapshot )
 						{
-							if ( !this.save( false, beforeTypeImage ) )
-							{
+							// This's a special save, with specified snapshot
+							// and without auto 'fireChange'.
+							if ( !this.save( false, beforeTypeImage, false ) )
 								// Drop future snapshots.
 								this.snapshots.splice( this.index + 1, this.snapshots.length - this.index - 1 );
-							}
 
 							this.hasUndo = true;
@@ -215,20 +252,36 @@
 
 							this.typesCount = 1;
-							this.typing = true;
+							this.modifiersCount = 1;
 
 							this.onChange();
 						}
 					},
-					0, this );
-
-				return;
-			}
-
-			this.typesCount++;
-
-			if ( this.typesCount > 25 )
-			{
-				this.save();
-				this.typesCount = 1;
+					0, this
+				);
+			}
+
+			this.lastKeystroke = keystroke;
+			// Create undo snap after typed too much (over 25 times).
+			if ( isModifier )
+			{
+				this.typesCount = 0;
+				this.modifiersCount++;
+
+				if ( this.modifiersCount > 25 )
+				{
+					this.save();
+					this.modifiersCount = 1;
+				}
+			}
+			else if ( !isReset )
+			{
+				this.modifiersCount = 0;
+				this.typesCount++;
+
+				if ( this.typesCount > 25 )
+				{
+					this.save();
+					this.typesCount = 1;
+				}
 			}
 
@@ -236,12 +289,21 @@
 		},
 
+		/**
+		 * Reset all states about typing.
+		 * @see  UndoManager.type
+		 */
+		resetType : function()
+		{
+			this.typing = false;
+			delete this.lastKeystroke;
+			this.typesCount = 0;
+			this.modifiersCount = 0;
+		},
 		fireChange : function()
 		{
 			this.hasUndo = !!this.getNextImage( true );
 			this.hasRedo = !!this.getNextImage( false );
-
-			this.typing = false;
-			this.typesCount = 0;
-
+			// Reset typing
+			this.resetType();
 			this.onChange();
 		},
@@ -250,5 +312,5 @@
 		 * Save a snapshot of document image for later retrieve.
 		 */
-		save : function( onContentOnly, image )
+		save : function( onContentOnly, image, autoFireChange )
 		{
 			var snapshots = this.snapshots;
@@ -274,6 +336,6 @@
 			this.currentImage = image;
 
-			this.fireChange();
-
+			if ( autoFireChange !== false )
+				this.fireChange();
 			return true;
 		},
