Index: /CKEditor/branches/prototype/_source/core/config.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/config.js	(revision 2436)
+++ /CKEditor/branches/prototype/_source/core/config.js	(revision 2437)
@@ -187,5 +187,5 @@
 	 */
 	width : '100%',
-	
+
 	/**
 	 * The base Z-index for floating dialogs and popups.
Index: /CKEditor/branches/prototype/_source/core/dom/element.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/dom/element.js	(revision 2436)
+++ /CKEditor/branches/prototype/_source/core/dom/element.js	(revision 2437)
@@ -315,10 +315,10 @@
 				function( propertyName )
 				{
-					return this.$.currentStyle[ propertyName ];
+					return this.$.currentStyle[ CKEDITOR.tools.cssStyleToDomStyle( propertyName ) ];
 				}
 			:
 				function( propertyName )
 				{
-					return this.getWindow().$.getComputedStyle( this.$, '' ).getPropertyValue( CKEDITOR.tools.cssStyleToDomStyle( propertyName ) );
+					return this.getWindow().$.getComputedStyle( this.$, '' ).getPropertyValue( propertyName );
 				},
 
Index: /CKEditor/branches/prototype/_source/core/dom/event.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/dom/event.js	(revision 2436)
+++ /CKEditor/branches/prototype/_source/core/dom/event.js	(revision 2437)
@@ -110,4 +110,23 @@
 				$.cancelBubble = true;
 		}
+	},
+	/**
+	 * Returns the DOM node where the event was targeted to.
+	 * @returns {CKEDITOR.dom.node} The target DOM node.
+	 * @example
+	 * var element = CKEDITOR.document.getById( 'myElement' );
+	 * element.on( 'click', function( ev )
+	 *     {
+	 *         // The DOM event object is passed by the "data" property.
+	 *         var domEvent = ev.data;
+	 *         // Add a CSS class to the event target.
+	 *         domEvent.getTarget().addClass( 'clicked' );
+	 *     });
+	 */
+
+	getTarget : function()
+	{
+		var rawNode = this.$.target || this.$.srcElement;
+		return rawNode ? new CKEDITOR.dom.node( rawNode ) : null;
 	}
 };
Index: /CKEditor/branches/prototype/_source/core/dom/node.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/dom/node.js	(revision 2436)
+++ /CKEditor/branches/prototype/_source/core/dom/node.js	(revision 2437)
@@ -155,13 +155,17 @@
 
 		/**
-		 * Gets the (index+1)-th children under the current node.
-		 * @param {Number} index The child index under the node.
-		 * @returns {CKEDITOR.dom.node} The (index+1)-th children under the current node. Null if child does not exist.
+		 * Gets a DOM tree descendant under the current node.
+		 * @param {Array|Number} indices The child index or array of child indices under the node.
+		 * @returns {CKEDITOR.dom.node} The specified DOM child under the current node. Null if child does not exist.
 		 * @example
 		 * var strong = p.getChild(0);
 		 */
-		getChild : function( index )
+		getChild : function( indices )
 		{
-			var rawNode = this.$.childNodes[index];
+			if ( !indices.slice )
+				indices = [indices];
+			var rawNode = this.$;
+			while ( indices.length > 0 && rawNode )
+				rawNode = rawNode.childNodes[ indices.shift() ];
 			return rawNode ? new CKEDITOR.dom.node( rawNode ) : null;
 		}
Index: /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js	(revision 2436)
+++ /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js	(revision 2437)
@@ -56,5 +56,23 @@
 						id : 'tab1',
 						label : 'First Tab',
-						title : ''
+						title : 'First Tab Title',
+						accessKey : 'Q',
+						elements : []
+					},
+
+					{
+						id : 'tab2',
+						label : 'Second Tab',
+						title : 'Second Tab Title',
+						accessKey : 'W',
+						elements : []
+					},
+
+					{
+						id : 'tab3',
+						label : 'Third Tab',
+						title : 'Third Tab Title',
+						accessKey : 'E',
+						elements : []
 					}
 				]
@@ -81,4 +99,9 @@
 		{
 			alert( 'Error: The dialog "' + dialogName + '" is missing its title or contents.' );
+			return;
+		}
+		if ( definition.contents.length < 1 )
+		{
+			alert( 'Error: The dialog "' + dialogName + '" has no contents.' );
 			return;
 		}
@@ -96,11 +119,4 @@
 		// Initialize the parts map.
 		var element = this._.element.getFirst();
-		function getPart(elementIndices)
-		{
-			var e = element;
-			for ( var i = 0 ; i < elementIndices.length ; i++ )
-				e = e.getChild( elementIndices[i] );
-			return e;
-		}
 		this._.parts = {
 			'tl' : [0,0],
@@ -119,8 +135,32 @@
 		};
 		for ( var i in this._.parts )
-			this._.parts[i] = getPart( this._.parts[i] );
+			this._.parts[i] = element.getChild( this._.parts[i] );
+
+		// Initialize the tab and page map.
+		this._.tabs = {};
 
 		// Insert the title.
-		( new CKEDITOR.dom.text( definition.title, CKEDITOR.document ) ).appendTo( this._.parts['title'] );
+		( new CKEDITOR.dom.text( definition.title, CKEDITOR.document ) ).appendTo( this._.parts.title );
+
+		// Insert the tabs and contents.
+		for ( var i = 0 ; i < definition.contents.length ; i++ )
+			this.addPage( definition.contents[i] );
+		this.selectPage( definition.contents[0].id );
+
+		var classRegex = /cke_dialog_tab(\s|$|_)/;
+		this._.parts['tabs'].on( 'click', function( evt )
+				{
+					var target = evt.data.getTarget(), firstNode = target, id, page;
+
+					// If we aren't inside a tab, bail out.
+					if ( !classRegex.test( target.$.className ) )
+						return;
+
+					// Find the outer <span> container of the tab.
+					while ( target.getName() == 'div' && classRegex.test( target.$.className ) )
+						target = target.getParent();
+					id = target.$.id.substr( 0, target.$.id.lastIndexOf( '_' ) );
+					this.selectPage( id );
+				}, this );
 	}
 };
@@ -174,5 +214,5 @@
 		// The dialog may be fixed positioned or absolute positioned. Ask the
 		// browser what is the current situation first.
-		var isFixed = this._.element.getComputedStyle( 'position' ) == 'fixed';
+		var isFixed = this._.element.getFirst().getComputedStyle( 'position' ) == 'fixed';
 
 		// If not fixed positioned, add scroll position to the coordinates.
@@ -214,4 +254,42 @@
 			return;
 		element.remove();
+	},
+
+	addPage : function( contents, index )
+	{
+		var page = CKEDITOR.dom.element.createFromHtml( '<div class="cke_dialog_page_contents"></div>' );
+		var tab = CKEDITOR.dom.element.createFromHtml( [
+					'<span><div class="cke_dialog_tab">',
+						'<div class="cke_dialog_tab_left"></div>',
+						'<div class="cke_dialog_tab_center">',
+							CKEDITOR.tools.htmlEncode( contents.label ),
+						'</div>',
+						'<div class="cke_dialog_tab_right"></div>',
+					'</div></span>'
+				].join( '' ) );
+		this._.tabs[ contents.id ] = [ tab, page ];
+		tab.getFirst().unselectable();
+		page.appendTo( this._.parts['contents'] );
+		tab.appendTo( this._.parts['tabs'] );
+		tab.setAttribute( 'id', contents.id + '_' + CKEDITOR.tools.getNextNumber() );
+	},
+
+	selectPage : function( id )
+	{
+		for ( var i in this._.tabs )
+		{
+			var tab = this._.tabs[i][0],
+				page = this._.tabs[i][1];
+			if ( i == id )
+			{
+				tab.addClass( 'cke_dialog_tab_selected');
+				page.show();
+			}
+			else
+			{
+				tab.removeClass( 'cke_dialog_tab_selected' );
+				page.hide();
+			}
+		}
 	}
 };
Index: /CKEditor/branches/prototype/_source/skins/default/dialog.css
===================================================================
--- /CKEditor/branches/prototype/_source/skins/default/dialog.css	(revision 2436)
+++ /CKEditor/branches/prototype/_source/skins/default/dialog.css	(revision 2437)
@@ -32,7 +32,7 @@
 }
 
-.cke_skin_default .cke_dialog_tl, 
+.cke_skin_default .cke_dialog_tl,
 .cke_skin_default .cke_dialog_t,
-.cke_skin_default .cke_dialog_tr, 
+.cke_skin_default .cke_dialog_tr,
 .cke_skin_default .cke_dialog_l,
 .cke_skin_default .cke_dialog_c,
@@ -52,5 +52,5 @@
 }
 
-.cke_skin_default .cke_dialog_tl, 
+.cke_skin_default .cke_dialog_tl,
 .cke_skin_default .cke_dialog_tr,
 .cke_skin_default .cke_dialog_l,
@@ -168,6 +168,9 @@
 	right: 16px;
 	background-color: #e3e3c7;
-	/* 
-	 * IE6 and IE7+ quirks mode do not support CSS right and bottom attributes 
+	clear: both;
+	padding-left: 10px;
+	z-index: 1;
+	/*
+	 * IE6 and IE7+ quirks mode do not support CSS right and bottom attributes
 	 * when left and top are defined. Use IE-specific expressions to
 	 * workaround.
@@ -199,2 +202,52 @@
 	_width: expression(this.offsetParent.offsetWidth - 32);		/* 16px left cell + 16px right cell */
 }
+
+.cke_skin_default .cke_dialog_page_contents
+{
+	position: absolute;
+	top: 0px;
+	bottom: 0px;
+	left: 0px;
+	right: 0px;
+	_width: expression(this.offsetParent.offsetWidth);
+	_height: expression(this.offsetParent.offsetHeight);
+}
+
+.cke_skin_default .cke_dialog_tab_center
+{
+	float: left;
+	cursor: pointer;
+	height: 15px;
+}
+
+.cke_skin_default .cke_dialog_tab,
+.cke_skin_default .cke_dialog_tab_left,
+.cke_skin_default .cke_dialog_tab_right
+{
+	float: left;
+	cursor: pointer;
+	height: 23px;
+}
+
+.cke_skin_default .cke_dialog_tab_center
+{
+	color: #737357;
+	padding: 4px 5px 3px 5px;
+	border-left: 1px solid #d5d59d;
+	border-right: 1px solid #d5d59d;
+	border-top: 1px solid #d5d59d;
+}
+
+.cke_skin_default .cke_dialog_tab_selected .cke_dialog_tab_left,
+.cke_skin_default .cke_dialog_tab_selected .cke_dialog_tab_center,
+.cke_skin_default .cke_dialog_tab_selected .cke_dialog_tab_right
+{
+	cursor: default;
+}
+
+.cke_skin_default .cke_dialog_tab_selected .cke_dialog_tab_center
+{
+	background-color: #f1f1e3;
+	font-weight: bold;
+	padding: 5px 5px 3px 5px;
+}
Index: /CKEditor/branches/prototype/_source/themes/default/theme.js
===================================================================
--- /CKEditor/branches/prototype/_source/themes/default/theme.js	(revision 2436)
+++ /CKEditor/branches/prototype/_source/themes/default/theme.js	(revision 2437)
@@ -129,4 +129,6 @@
 			].join( '' ).replace( /%d/g, dialogId ) );
 
+		container.getChild( [0, 1, 1, 0] ).unselectable();
+
 		return container;
 	},
