Index: /CKEditor/trunk/_source/core/config.js
===================================================================
--- /CKEditor/trunk/_source/core/config.js	(revision 3086)
+++ /CKEditor/trunk/_source/core/config.js	(revision 3087)
@@ -148,5 +148,5 @@
 	 */
 
-	plugins : 'basicstyles,blockquote,button,clipboard,elementspath,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,sourcearea,table,specialchar,tab,toolbar,undo,wysiwygarea',
+	plugins : 'basicstyles,blockquote,button,clipboard,elementspath,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,sourcearea,table,specialchar,tab,templates,toolbar,undo,wysiwygarea',
 
 	/**
Index: /CKEditor/trunk/_source/lang/en.js
===================================================================
--- /CKEditor/trunk/_source/lang/en.js	(revision 3086)
+++ /CKEditor/trunk/_source/lang/en.js	(revision 3087)
@@ -420,4 +420,13 @@
 		button : 'Paste as plain text',
 		title : 'Paste as Plain Text'
+	},
+
+	templates :
+	{
+		button : 'Templates',
+		title : 'Content Templates',
+		insertOption: 'Replace actual contents',
+		selectPromptMsg: 'Please select the template to open in the editor',
+		emptyListMsg : '(No templates defined)'
 	}
 };
Index: /CKEditor/trunk/_source/plugins/dialog/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/dialog/plugin.js	(revision 3086)
+++ /CKEditor/trunk/_source/plugins/dialog/plugin.js	(revision 3087)
@@ -882,4 +882,9 @@
 			{
 				return !!this._.dialogDefinitions[ name ];
+			},
+
+			getCurrent : function()
+			{
+				return CKEDITOR.dialog._.currentTop;
 			},
 
Index: /CKEditor/trunk/_source/plugins/templates/dialogs/templates.js
===================================================================
--- /CKEditor/trunk/_source/plugins/templates/dialogs/templates.js	(revision 3087)
+++ /CKEditor/trunk/_source/plugins/templates/dialogs/templates.js	(revision 3087)
@@ -0,0 +1,174 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+	var doc = CKEDITOR.document;
+	
+	var listId = 'cke' + CKEDITOR.tools.getNextNumber();
+
+	// Constructs the HTML view of the specified templates data.
+	function renderTemplatesList( editor, templatesDefinitions )
+	{
+		var listDiv = doc.getById( listId );
+
+		// clear loading wait text.
+		listDiv.setHtml( '' );
+
+		for ( var i = 0 ; i < templatesDefinitions.length ; i++ )
+		{
+			var definition = CKEDITOR.getTemplates( templatesDefinitions[ i ] ),
+				imagesPath = definition.imagesPath,
+				templates = definition.templates;
+			
+			for ( var j = 0 ; j < templates.length ; j++ )
+			{
+				var template = templates[ j ];
+				listDiv.append( createTemplateItem( editor, template, imagesPath ) );
+			}
+		}
+	}
+	
+	function createTemplateItem( editor, template, imagesPath )
+	{
+		var div = doc.createElement( 'div' );
+		div.setAttribute( 'class', 'cke_tpl_item' );
+
+		// Build the inner HTML of our new item DIV.
+		var html = '<table class="cke_tpl_preview"><tr>';
+
+		if( template.image && imagesPath )
+			html += '<td class="cke_tpl_preview_img"><img src="' + CKEDITOR.getUrl( imagesPath + template.image ) + '"></td>';
+
+		html += '<td><span class="cke_tpl_title">' + template.title + '</span><br/>';
+
+		if( template.description )
+			html += '<span>' + template.description + '</span>';
+
+		html += '</td></tr></table>';
+
+		div.setHtml( html );
+
+		div.on( 'mouseover', function()
+			{
+				div.addClass( 'cke_tpl_hover' );
+			});
+
+		div.on( 'mouseout', function()
+			{
+				div.removeClass( 'cke_tpl_hover' );
+			});
+
+		div.on( 'click', function()
+			{
+				insertTemplate( editor, template.html );
+			});
+		
+		return div;
+	}
+
+	/**
+	 * Insert the specified template content
+	 * to document.
+	 * @param {Number} index
+	 */
+	function insertTemplate( editor, html )
+	{
+		var dialog = CKEDITOR.dialog.getCurrent(),
+			isInsert = dialog.getValueOf( 'selectTpl', 'chkInsertOpt' );
+
+		if( isInsert )
+		{
+			editor.setData( html );
+		}
+		else
+		{
+			if( CKEDITOR.env.ie )
+				dialog.restoreSelection();
+			
+			editor.insertHtml( html );
+		}
+
+		dialog.clearSavedSelection();
+		dialog.hide();
+	}
+
+	CKEDITOR.dialog.add( 'templates', function( editor )
+		{
+			// Load skin at first.
+			CKEDITOR.skins.load( 'default', 'templates' );
+
+			/**
+			 * Load templates once.
+			 */
+			var isLoaded = false;
+
+			return {
+				title :editor.lang.templates.title,
+				
+				minWidth :450,
+				minHeight :400,
+				
+				contents :
+				[
+					{
+						id :'selectTpl',
+						label : editor.lang.templates.title,
+						elements :
+						[
+							{
+								type : 'vbox',
+								padding : 5,
+								children :
+								[
+									{
+										type : 'html',
+										html :
+											'<span>'  +
+												editor.lang.templates.selectPromptMsg +
+											'</span>'
+									},
+									{
+										type : 'html',
+										html :
+											'<div id="' + listId + '" class="cke_tpl_list">' +
+												'<div class="cke_tpl_loading"><span></span></div>' +
+											'</div>'
+									},
+									{
+										id : 'chkInsertOpt',
+										type : 'checkbox',
+										label : editor.lang.templates.insertOption,
+										'default' : editor.config.templates_replaceContent
+									}
+								]
+							}
+						]
+					}
+				],
+				
+				buttons : [ CKEDITOR.dialog.cancelButton ],
+				
+				onShow : function()
+				{
+					CKEDITOR.loadTemplates( editor.config.templates_files, function()
+						{
+							var templates = editor.config.templates.split( ',' );
+
+							if ( templates.length )
+								renderTemplatesList( editor, templates );
+							else
+							{
+								var listCtEl = doc.getById( listId );
+								listCtEl.setHtml(
+									'<div class="cke_tpl_empty">' +
+										'<span>' + editor.lang.templates.emptyListMsg + '</span>' +
+									'</div>' );
+							}
+						});
+				}
+			};
+		});
+})();
Index: /CKEditor/trunk/_source/plugins/templates/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/templates/plugin.js	(revision 3087)
+++ /CKEditor/trunk/_source/plugins/templates/plugin.js	(revision 3087)
@@ -0,0 +1,89 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+	CKEDITOR.plugins.add( 'templates',
+		{
+			requires : [ 'dialog' ],
+
+			init : function( editor )
+			{
+				CKEDITOR.dialog.add( 'templates', CKEDITOR.getUrl( this.path + 'dialogs/templates.js' ) );
+
+				editor.addCommand( 'templates', new CKEDITOR.dialogCommand( 'templates' ) );
+
+				editor.ui.addButton( 'Templates',
+					{
+						label : editor.lang.templates.button,
+						command : 'templates'
+					});
+			}
+		});
+
+	var templates = {},
+		loadedTemplatesFiles = {};
+
+	CKEDITOR.addTemplates = function( name, definition )
+	{
+		templates[ name ] = definition;
+	};
+
+	CKEDITOR.getTemplates = function( name )
+	{
+		return templates[ name ];
+	};
+
+	CKEDITOR.loadTemplates = function( templateFiles, callback )
+	{
+		// Holds the templates files to be loaded.
+		var toLoad = [];
+
+		// Look for pending template files to get loaded.
+		for ( var i = 0 ; i < templateFiles.length ; i++ )
+		{
+			if ( !loadedTemplatesFiles[ templateFiles[ i ] ] )
+			{
+				toLoad.push( templateFiles[ i ] );
+				loadedTemplatesFiles[ templateFiles[ i ] ] = 1;
+			}
+		}
+
+		if ( toLoad.length > 0 )
+			CKEDITOR.scriptLoader.load( toLoad, callback );
+		else
+			setTimeout( callback, 0 );
+	};
+})();
+
+
+
+/**
+ * The templates definition set to use. It accepts a list of names separated by
+ * comma. It must match definitions loaded with the templates_files setting.
+ * @type String
+ * @default 'default'
+ */
+CKEDITOR.config.templates = 'default';
+
+/**
+ * The list of templates definition files to load.
+ * @type (String) Array
+ * @default [ 'plugins/templates/templates/default.js' ]
+ */
+CKEDITOR.config.templates_files =
+	[
+		CKEDITOR.getUrl(
+			'_source/' + // %REMOVE_LINE%
+			'plugins/templates/templates/default.js' )
+	];
+
+/**
+ * Whether replace the current document content OR insert current
+ * editing position.
+ * @type Boolean
+ * @default true
+ */
+CKEDITOR.config.templates_replaceContent = true;
Index: /CKEditor/trunk/_source/plugins/templates/templates/default.js
===================================================================
--- /CKEditor/trunk/_source/plugins/templates/templates/default.js	(revision 3087)
+++ /CKEditor/trunk/_source/plugins/templates/templates/default.js	(revision 3087)
@@ -0,0 +1,94 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+// Register a templates definition set named "default".
+CKEDITOR.addTemplates( 'default',
+{
+	// The name of sub folder which hold the shortcut preview images of the
+	// templates.
+	imagesPath : CKEDITOR.getUrl( CKEDITOR.plugins.getPath( 'templates' ) + 'templates/images/' ),
+
+	// The templates definitions.
+	templates :
+		[
+			{
+				title: 'Image and Title',
+				image: 'template1.gif',
+				description: 'One main image with a title and text that surround the image.',
+				html:
+					'<h3>' +
+						'<img style="margin-right: 10px" height="100" alt="" width="100" align="left"/>' +				
+						'Type the title here'+
+					'</h3>' +
+					'<p>' +
+						'Type the text here' +
+					'</p>'
+			},
+			{
+				title: 'Strange Template',
+				image: 'template2.gif',
+				description: 'A template that defines two colums, each one with a title, and some text.',
+				html:
+					'<table cellspacing="0" cellpadding="0" width="100%" border="0">' +
+						'<tr>' +
+							'<td width="50%">' +
+								'<h3>Title 1</h3>' +
+							'</td>' +
+							'<td></td>' +
+							'<td width="50%">' +
+								'<h3>Title 2</h3>' +
+							'</td>' +
+						'</tr>' +
+						'<tr>' +
+							'<td>' +
+								'Text 1' +
+							'</td>' +
+							'<td></td>' +
+							'<td>' +
+								'Text 2' +
+							'</td>' +
+						'</tr>' +
+					'</table>' +
+					'<p>' +
+						'More text goes here.' +
+					'</p>'
+			},
+			{
+				title: 'Text and Table',
+				image: 'template3.gif',
+				description: 'A title with some text and a table.',
+				html:
+					'<div style="width: 80%">' +
+						'<h3>' +
+							'Title goes here' +
+						'</h3>' +
+						'<table style="float: right" cellspacing="0" cellpadding="0" width="150" border="1">' +
+							'<caption style="border:solid 1px black">' +
+								'<strong>Table title</strong>' +
+							'</caption>' +
+							'</tr>' +
+							'<tr>' +
+								'<td>&nbsp;</td>' +
+								'<td>&nbsp;</td>' +
+								'<td>&nbsp;</td>' +
+							'</tr>' +
+							'<tr>' +
+								'<td>&nbsp;</td>' +
+								'<td>&nbsp;</td>' +
+								'<td>&nbsp;</td>' +
+							'</tr>' +
+							'<tr>' +
+								'<td>&nbsp;</td>' +
+								'<td>&nbsp;</td>' +
+								'<td>&nbsp;</td>' +
+							'</tr>' +
+						'</table>' +
+						'<p>' +
+							'Type the text here' +
+						'</p>' +
+					'</div>'
+			}
+		]
+});
Index: /CKEditor/trunk/_source/plugins/toolbar/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/toolbar/plugin.js	(revision 3086)
+++ /CKEditor/trunk/_source/plugins/toolbar/plugin.js	(revision 3087)
@@ -208,5 +208,5 @@
 	[
 		'Source', '-',
-		'NewPage', 'Preview', 'Print', '-',
+		'NewPage', 'Preview', 'Templates', 'Print', '-',
 		'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-',
 		'Undo', 'Redo', '-',
Index: /CKEditor/trunk/_source/skins/default/skin.js
===================================================================
--- /CKEditor/trunk/_source/skins/default/skin.js	(revision 3086)
+++ /CKEditor/trunk/_source/skins/default/skin.js	(revision 3087)
@@ -23,5 +23,6 @@
 		preload : preload,
 		editor : { css : [ 'editor.css' ] },
-		dialog : { css : [ 'dialog.css' ],  js : dialogJs }
+		dialog : { css : [ 'dialog.css' ],  js : dialogJs },
+		templates : { css : [ 'templates.css' ] } 
 	};
 })() );
Index: /CKEditor/trunk/_source/skins/default/templates.css
===================================================================
--- /CKEditor/trunk/_source/skins/default/templates.css	(revision 3087)
+++ /CKEditor/trunk/_source/skins/default/templates.css	(revision 3087)
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * Styles for the "templates" plugin.
+ */
+
+.cke_skin_default .cke_tpl_list
+{
+	border: #dcdcdc 2px solid;
+	background-color: #ffffff;
+	overflow: auto;
+	width: 100%;
+	height: 220px;
+}
+
+.cke_skin_default .cke_tpl_item
+{
+	margin: 5px;
+	padding: 7px;
+	border: #eeeeee 1px solid;
+	*width: 88%;
+}
+
+.cke_skin_default .cke_tpl_preview
+{
+	border-collapse: separate;
+	text-indent:0;
+	width: 100%;
+}
+.cke_skin_default .cke_tpl_preview td
+{
+	padding: 2px;
+	vertical-align: middle;
+}
+.cke_skin_default .cke_tpl_preview .cke_tpl_preview_img
+{
+	width: 100px;
+}
+.cke_skin_default .cke_tpl_preview span
+{
+	white-space: normal;
+}
+
+.cke_skin_default .cke_tpl_title
+{
+	font-weight: bold;
+}
+
+.cke_skin_default .cke_tpl_hover
+{
+	border: #ff9933 1px solid !important;
+	background-color: #fffacd !important;
+	cursor: pointer;
+	cursor: hand;
+}
+/*
+ * Fix property 'cursor' doesn't inherit on table
+ */
+.cke_skin_default .cke_tpl_hover *
+{
+	cursor: inherit;
+}
+
+.cke_skin_default .cke_tpl_empty, .cke_tpl_loading
+{
+	text-align: center;
+	padding: 5px;
+}
Index: /CKEditor/trunk/_source/skins/default/toolbar.css
===================================================================
--- /CKEditor/trunk/_source/skins/default/toolbar.css	(revision 3086)
+++ /CKEditor/trunk/_source/skins/default/toolbar.css	(revision 3087)
@@ -339,4 +339,10 @@
 	background-position: 0 -224px;
 }
+
+.cke_skin_default a.cke_button_templates .cke_icon
+{
+	background-position: 0 -80px;
+}
+
 .cke_skin_default a.cke_button_numberedlist .cke_icon
 {
