Index: _source/core/config.js
===================================================================
--- _source/core/config.js	(revision 3043)
+++ _source/core/config.js	(working copy)
@@ -146,7 +146,7 @@
 	 * @example
 	 * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea';
 	 */
-	plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,removeformat,smiley,sourcearea,specialchar,tab,toolbar,wysiwygarea',
+	plugins : 'basicstyles,button,elementspath,forms,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,removeformat,smiley,sourcearea,specialchar,tab,toolbar,wysiwygarea',
 
 	/**
 	 * The theme to be used to build the UI.
Index: _source/plugins/forms/dialogs/button.js
===================================================================
--- _source/plugins/forms/dialogs/button.js	(revision 0)
+++ _source/plugins/forms/dialogs/button.js	(revision 0)
@@ -0,0 +1,112 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'button', function( editor )
+{
+	return {
+		title : editor.lang.button.title,
+		minWidth : 400,
+		minHeight : 230,
+		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" )
+			{
+				var type = element.getAttribute( 'type' );
+				if ( type == "button" || type == "reset" || type == "submit" )
+				{
+					this._element = element;
+					this.setupContent( element );
+				}
+			}
+		},
+		onOk : function()
+		{
+			var editor,
+				element = this._element,
+				isInsertMode = !element;
+
+			if ( isInsertMode )
+			{
+				editor = this.getParentEditor();
+				element = editor.document.createElement( 'input' );
+			}
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.button.title,
+				title : editor.lang.button.title,
+				accessKey : 'I',
+				elements : [
+					{
+						id : 'txtName',
+						type : 'text',
+						label : editor.lang.common.name,
+						'default' : '',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'name' ) );
+							this.focus();
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'name', this.getValue() );
+						}
+					},
+					{
+						id : 'txtValue',
+						type : 'text',
+						label : editor.lang.button.text,
+						accessKey : 'V',
+						'default' : '',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'value' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'value', this.getValue() );
+						}
+					},
+					{
+						id : 'txtType',
+						type : 'select',
+						label : editor.lang.button.type,
+						'default' : 'button',
+						accessKey : 'T',
+						items :
+						[
+							[ editor.lang.button.typeBtn, 'button' ],
+							[ editor.lang.button.typeSbm, 'submit' ],
+							[ editor.lang.button.typeRst, 'reset' ]
+						],
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'type' ) );
+						},
+						commit : function( element )
+						{
+							element.setAttribute( 'type', this.getValue() );
+						}
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/dialogs/checkbox.js
===================================================================
--- _source/plugins/forms/dialogs/checkbox.js	(revision 0)
+++ _source/plugins/forms/dialogs/checkbox.js	(revision 0)
@@ -0,0 +1,109 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'checkbox', function( editor )
+{
+	return {
+		title : editor.lang.checkboxAndRadio.checkboxTitle,
+		minWidth : 400,
+		minHeight : 230,
+		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.getAttribute( 'type' ) == "checkbox" )
+			{
+				this._element = element;
+				this.setupContent( element );
+			}
+		},
+		onOk : function()
+		{
+			var editor,
+				element = this._element,
+				isInsertMode = !element;
+			
+			if ( isInsertMode )
+			{
+				editor = this.getParentEditor();
+				element = editor.document.createElement( 'input' );
+				element.setAttribute( 'type', 'checkbox' );
+			}
+
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.checkboxAndRadio.checkboxTitle,
+				title : editor.lang.checkboxAndRadio.checkboxTitle,
+				accessKey : 'I',
+				startupFocus : 'txtName',
+				elements : [
+					{
+						id : 'txtName',
+						type : 'text',
+						label : editor.lang.common.name,
+						'default' : '',
+						accessKey : 'N',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'name' ) );
+							this.focus();
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'name', this.getValue() );
+						}
+					},
+					{
+						id : 'txtValue',
+						type : 'text',
+						label : editor.lang.checkboxAndRadio.value,
+						'default' : '',
+						accessKey : 'V',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'value' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'value', this.getValue() );
+						}
+					},
+					{
+						id : 'cmbSelected',
+						type : 'checkbox',
+						label : editor.lang.checkboxAndRadio.selected,
+						'default' : '',
+						accessKey : 'S',
+						value : "checked",
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'checked' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() == true || this.isChanged() )
+								element.setAttribute( 'checked', this.getValue() );
+						}
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/dialogs/form.js
===================================================================
--- _source/plugins/forms/dialogs/form.js	(revision 0)
+++ _source/plugins/forms/dialogs/form.js	(revision 0)
@@ -0,0 +1,189 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'form', function( editor )
+{
+	return {
+		title : editor.lang.form.title,
+		minWidth : 400,
+		minHeight : 270,
+		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" )
+			{
+				this._element = element;
+				this.setupContent( element );
+			}
+
+			this.getContentElement( 'info', 'txtName' ).focus();
+		},
+		onOk : function()
+		{
+			var editor,
+				element = this._element,
+				isInsertMode = !element;
+
+			if ( isInsertMode )
+			{
+				editor = this.getParentEditor();
+				element = editor.document.createElement( 'form' );
+			}
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.form.title,
+				title : editor.lang.form.title,
+				accessKey : 'I',
+				elements : [
+					{
+						id : 'txtName',
+						type : 'text',
+						label : editor.lang.common.name,
+						'default' : '',
+						accessKey : 'N',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'name' ) );
+							this.focus();
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'name', this.getValue() );
+						}
+					},
+					{
+						id : 'txtAction',
+						type : 'text',
+						label : editor.lang.form.action,
+						'default' : '',
+						accessKey : 'A',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'action' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'action', this.getValue() );
+						}
+					},
+					{
+						type : 'hbox',
+						widths : [ '45%', '55%' ],
+						children :
+						[
+							{
+								id : 'txtId',
+								type : 'text',
+								label : editor.lang.common.id,
+								'default' : '',
+								accessKey : 'I',
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'id' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'id', this.getValue() );
+								}
+							},
+							{
+								id : 'cmbEncoding',
+								type : 'select',
+								label : editor.lang.form.encoding,
+								style : 'width:100%',
+								accessKey : 'E',
+								'default' : '',
+								items :
+								[
+									[ '' ],
+									[ 'text/plain' ],
+									[ 'multipart/form-data' ],
+									[ 'application/x-www-form-urlencoded' ]
+								],
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'encoding' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'encoding', this.getValue() );
+								}
+							}
+						]
+					},
+					{
+						type : 'hbox',
+						widths : [ '45%', '55%' ],
+						children :
+						[
+							{
+								id : 'cmbTarget',
+								type : 'select',
+								label : editor.lang.form.target,
+								style : 'width:100%',
+								accessKey : 'M',
+								'default' : '',
+								items :
+								[
+									[ editor.lang.form.targetNotSet, '' ],
+									[ editor.lang.form.targetNew, '_blank' ],
+									[ editor.lang.form.targetTop, '_top' ],
+									[ editor.lang.form.targetSelf, '_self' ],
+									[ editor.lang.form.targetParent, '_parent' ]
+								],
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'target' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'target', this.getValue() );
+								}
+							},
+							{
+								id : 'cmbMethod',
+								type : 'select',
+								label : editor.lang.form.method,
+								accessKey : 'M',
+								'default' : 'GET',
+								items :
+								[
+									[ 'GET', 'get' ],
+									[ 'POST', 'post' ]
+								],
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'method' ) );
+								},
+								commit : function( element )
+								{
+									element.setAttribute( 'method', this.getValue() );
+								}
+							}
+						]
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/dialogs/hiddenfield.js
===================================================================
--- _source/plugins/forms/dialogs/hiddenfield.js	(revision 0)
+++ _source/plugins/forms/dialogs/hiddenfield.js	(revision 0)
@@ -0,0 +1,89 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'hiddenfield', function( editor )
+{
+	return {
+		title : editor.lang.hidden.title,
+		minWidth : 400,
+		minHeight : 200,
+		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" )
+			{
+				this._element = element;
+				this.setupContent( element );
+			}
+		},
+		onOk : function()
+		{
+			var editor,
+				element = this._element,
+				isInsertMode = !element;
+
+			if ( isInsertMode )
+			{
+				editor = this.getParentEditor();
+				element = editor.document.createElement( 'input' );
+				element.setAttribute( 'type', 'hidden' );
+			}
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.hidden.title,
+				title : editor.lang.hidden.title,
+				accessKey : 'I',
+				elements : [
+					{
+						id : 'txtName',
+						type : 'text',
+						label : editor.lang.hidden.name,
+						'default' : '',
+						accessKey : 'N',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'name' ) );
+							this.focus();
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'name', this.getValue() );
+						}
+					},
+					{
+						id : 'txtValue',
+						type : 'text',
+						label : editor.lang.hidden.value,
+						'default' : '',
+						accessKey : 'V',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'value' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'value', this.getValue() );
+						}
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/dialogs/radio.js
===================================================================
--- _source/plugins/forms/dialogs/radio.js	(revision 0)
+++ _source/plugins/forms/dialogs/radio.js	(revision 0)
@@ -0,0 +1,106 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'radio', function( editor )
+{
+	return {
+		title : editor.lang.checkboxAndRadio.radioTitle,
+		minWidth : 400,
+		minHeight : 200,
+		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" )
+			{
+				this._element = element;
+				this.setupContent( element );
+			}
+		},
+		onOk : function()
+		{
+			var editor,
+				element = this._element,
+				isInsertMode = !element;
+
+			if ( isInsertMode )
+			{
+				editor = this.getParentEditor();
+				element = editor.document.createElement( 'input' );
+				element.setAttribute( 'type', 'radio' );
+			}
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.checkboxAndRadio.radioTitle,
+				title : editor.lang.checkboxAndRadio.radioTitle,
+				accessKey : 'I',
+				elements : [
+					{
+						id : 'txtName',
+						type : 'text',
+						label : editor.lang.common.name,
+						'default' : '',
+						accessKey : 'N',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'name' ) );
+							this.focus();
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'name', this.getValue() );
+						}
+					},
+					{
+						id : 'txtValue',
+						type : 'text',
+						label : editor.lang.checkboxAndRadio.value,
+						'default' : '',
+						accessKey : 'V',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'value' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'value', this.getValue() );
+						}
+					},
+					{
+						id : 'cmbSelected',
+						type : 'checkbox',
+						label : editor.lang.checkboxAndRadio.selected,
+						'default' : '',
+						accessKey : 'S',
+						value : "checked",
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'checked' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() == true || this.isChanged() )
+								element.setAttribute( 'checked', this.getValue() );
+						}
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/dialogs/select.js
===================================================================
--- _source/plugins/forms/dialogs/select.js	(revision 0)
+++ _source/plugins/forms/dialogs/select.js	(revision 0)
@@ -0,0 +1,394 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'select', function( editor )
+{
+	var plugin = CKEDITOR.plugins.forms.select;
+	return {
+		title : editor.lang.select.title,
+		minWidth : 400,
+		minHeight : 370,
+		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();
+			if ( element && element.getName() == "select" )
+			{
+				this._element = element;
+				this.setupContent( element.getName(), element );
+
+				//Load Options into dialog.
+				var objOptions = plugin.getOptions( element );
+				for ( var i = 0 ; i < objOptions.length ; i++ )
+					this.setupContent( objOptions[i].getName(), objOptions[i] );
+			}
+		},
+		onOk : function()
+		{
+			var editor = this.getParentEditor(),
+				element = this._element,
+				isInsertMode = !element;
+
+			if ( isInsertMode )
+				element = editor.document.createElement( 'select' );
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.select.selectInfo,
+				title : editor.lang.select.selectInfo,
+				accessKey : '',
+				elements : [
+					{
+						id : 'txtName',
+						type : 'text',
+						widths : [ '25%','75%' ],
+						labelLayout : 'horizontal',
+						label : editor.lang.common.name,
+						'default' : '',
+						accessKey : 'N',
+						align : 'center',
+						style : 'width:350px',
+						setup : function( name, element )
+						{
+							if ( name == 'select' )
+							{
+								this.setValue( element.getAttribute( 'name' ) );
+								this.focus();
+							}
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'name', this.getValue() );
+						}
+					},
+					{
+						id : 'txtValue',
+						type : 'text',
+						widths : [ '25%','75%' ],
+						labelLayout : 'horizontal',
+						label : editor.lang.select.value,
+						style : 'width:350px',
+						'default' : '',
+						readonly : true,		//TODO: make it readonly somehow.
+						disabled : true
+					},
+					{
+						type : 'hbox',
+						widths : [ '175px', '170px' ],
+						align : 'center',
+						children :
+						[
+							{
+								id : 'txtSize',
+								type : 'text',
+								align : 'center',
+								labelLayout : 'horizontal',
+								label : editor.lang.select.size,
+								'default' : '',
+								accessKey : 'S',
+								style : 'width:175px',
+								validate: function()
+								{
+									var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
+									return ( ( this.getValue() == '' ) || func.apply( this ) );
+								},
+								setup : function( name, element )
+								{
+									if ( name == 'select' )
+										this.setValue( element.getAttribute( 'size' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'size', this.getValue() );
+								}
+							},
+							{
+								type : 'html',
+								html : '<span>' + CKEDITOR.tools.htmlEncode( editor.lang.select.lines ) + '</span>'
+							}
+						]
+					},
+					{
+						type : 'html',
+						html : '<span>' + CKEDITOR.tools.htmlEncode( editor.lang.select.opAvail ) + '</span>'
+					},
+					{
+						type : 'hbox',
+						widths : [ '35%', '35%' ,'30%' ],
+						padding : 2,
+						align : 'top',
+						children :
+						[
+							{
+								type : 'vbox',
+								padding : 0,
+								children :
+								[
+									{
+										id : 'txtOptName',
+										type : 'text',
+										label : editor.lang.select.opText,
+										style : 'width:100%;margin-bottom:10px'
+									},
+									{
+										type : 'select',
+										id : 'cmbName',
+										label : '',
+										title : '',
+										size : 5,
+										style : 'width:100%; height:75px; margin-bottom:5px',
+										items : [],
+										onChange : function()
+										{
+											var dialog = this.getDialog(),
+												values = dialog.getContentElement( 'info', 'cmbValue' ),
+												optName = dialog.getContentElement( 'info', 'txtOptName' ),
+												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
+												iIndex = plugin.getSelectedIndex( this );
+
+											plugin.setSelectedIndex( values, iIndex );
+											optName.setValue( this.getValue() );
+											optValue.setValue( values.getValue() );
+										},
+										setup : function( name, element )
+										{
+											if ( name == 'clear' )
+												plugin.removeAllOptions( this );
+											else if ( name == 'option' )
+												plugin.addOption( this, element.innerHTML, element.innerHTML, 
+													this.getDialog.getParentEditor().document );
+										},
+										commit : function( element )
+										{
+											var dialog = this.getDialog(),
+												optionsNames = plugin.getOptions( this ),
+												optionsValues = plugin.getOptions( 
+													dialog.getContentElement( 'info', 'cmbValue' ) ),
+												selectValue = dialog.getContentElement( 'info', 'txtValue' );
+
+											plugin.removeAllOptions( element );
+
+											for ( var i = 0 ; i < optionsNames.length ; i++ )
+											{
+												var oOption = plugin.addOption( element, optionsNames[i].value, 
+													optionsValues[i].value, dialog.getParentEditor().document );	
+												if ( optionsValues == selectValue )
+												{
+													oOption.setAttribute( 'selected', 'selected' );
+													oOption.selected = true;
+												}	
+											}
+										}
+									}
+								]
+							},
+							{
+								type : 'vbox',
+								padding : 0,
+								children :
+								[
+									{
+										id : 'txtOptValue',
+										type : 'text',
+										label : editor.lang.select.opValue,
+										style : 'width:100%;margin-bottom:10px;'
+									},
+									{
+										type : 'select',
+										id : 'cmbValue',
+										label : '',
+										size : 5,
+										style : 'width:100%; height:75px;margin-bottom:5px',
+										items : [],
+										onChange : function()
+										{
+											var dialog = this.getDialog(),
+												names = dialog.getContentElement( 'info', 'cmbName' ),
+												optName = dialog.getContentElement( 'info', 'txtOptName' ),
+												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
+												iIndex = plugin.getSelectedIndex( this );
+												
+											plugin.setSelectedIndex( names, iIndex );
+											optName.setValue( names.getValue() );
+											optValue.setValue( this.getValue() );
+										},
+										setup : function( name, element )
+										{
+											if ( name == 'clear' )
+												plugin.removeAllOptions( this );
+											else if ( name == 'option' )
+											{
+												var oValue	= element.value;
+												plugin.addOption( this, oValue, oValue, 
+													this.getDialog.getParentEditor().document );
+												if ( element.getAttribute( 'selected' ) == 'selected' )
+													this.getDialog().getContentElement( 'info', 'txtValue' ).setValue( oValue );
+											}
+										}
+									},
+								]
+							},
+							{
+								type : 'vbox',
+								children :
+								[
+									{
+										type : 'button',
+										style : '',
+										label : editor.lang.select.btnAdd,
+										title : editor.lang.select.btnAdd,
+										style : 'width:100%;',
+										onClick : function()
+										{
+											//Add new option.
+											var dialog = this.getDialog();
+												parentEditor = dialog.getParentEditor(),
+												optName = dialog.getContentElement( 'info', 'txtOptName' ),
+												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
+												names = dialog.getContentElement( 'info', 'cmbName' ),
+												values = dialog.getContentElement( 'info', 'cmbValue' );
+
+											plugin.addOption(names, optName.getValue(), optName.getValue() );
+											plugin.addOption(values, optValue.getValue(), optValue.getValue() );
+
+											optName.setValue( "" );
+											optValue.setValue( "" );
+										}
+									},
+									{
+										type : 'button',
+										label : editor.lang.select.btnModify,
+										title : editor.lang.select.btnModify,
+										style : 'width:100%;',
+										onClick : function()
+										{
+											//Modify selected option.
+											var dialog = this.getDialog();
+												optName = dialog.getContentElement( 'info', 'txtOptName' ),
+												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
+												names = dialog.getContentElement( 'info', 'cmbName' ),
+												values = dialog.getContentElement( 'info', 'cmbValue' ),
+												iIndex = plugin.getSelectedIndex( names );
+
+											if ( iIndex >= 0 )
+											{
+												plugin.modifyOption( names, iIndex, optName.getValue(), optName.getValue() );
+												plugin.modifyOption( values, iIndex, optValue.getValue(), optValue.getValue() );
+											}
+										}
+									},
+									{
+										type : 'button',
+										style : 'width:100%;',
+										label : editor.lang.select.btnUp,
+										title : editor.lang.select.btnUp,
+										onClick : function()
+										{
+											//Move up.
+											var dialog = this.getDialog(),
+												names = dialog.getContentElement( 'info', 'cmbName' ),
+												values = dialog.getContentElement( 'info', 'cmbValue' );
+
+											plugin.changeOptionPosition( names, -1, dialog.getParentEditor().document );
+											plugin.changeOptionPosition( values, -1, dialog.getParentEditor().document );
+										}
+									},
+									{
+										type : 'button',
+										style : 'width:100%;',
+										label : editor.lang.select.btnDown,
+										title : editor.lang.select.btnDown,
+										onClick : function()
+										{
+											//Move down.
+											var dialog = this.getDialog(),
+											names = dialog.getContentElement( 'info', 'cmbName' ),
+											values = dialog.getContentElement( 'info', 'cmbValue' );
+
+											plugin.changeOptionPosition( names, 1, dialog.getParentEditor().document );
+											plugin.changeOptionPosition( values, 1, dialog.getParentEditor().document );
+										}
+									}
+								]
+							}
+						]
+					},
+					{
+						type : 'hbox',
+						widths : [ '40%', '20%', '40%' ],
+						children :
+						[
+							{
+								type : 'button',
+								label : editor.lang.select.btnSetValue,
+								title : editor.lang.select.btnSetValue,
+								onClick : function()
+								{
+									//Set as default value.
+									var dialog = this.getDialog(),
+										values = dialog.getContentElement( 'info', 'cmbValue' ),
+										txtValue = dialog.getContentElement( 'info', 'txtValue' );
+									txtValue.setValue( values.getValue() );
+								}
+							},
+							{
+								type : 'button',
+								label : editor.lang.select.btnDelete,
+								title : editor.lang.select.btnDelete,
+								onClick : function()
+								{
+									// Delete option.
+									var dialog = this.getDialog(),
+										names = dialog.getContentElement( 'info', 'cmbName' ),
+										values = dialog.getContentElement( 'info', 'cmbValue' ),
+										optName = dialog.getContentElement( 'info', 'txtOptName' ),
+										optValue = dialog.getContentElement( 'info', 'txtOptValue' );
+									
+									plugin.removeSelectedOptions( names );
+									plugin.removeSelectedOptions( values );
+
+									optName.setValue( "" );
+									optValue.setValue( "" );
+								}
+							},
+							{
+								id : 'chkMulti',
+								type : 'checkbox',
+								label : editor.lang.select.chkMulti,
+								'default' : 'url',
+								accessKey : 'M',
+								value : "checked",
+								setup : function( name, element )
+								{
+									if ( name == 'select' )
+										this.setValue( element.getAttribute( 'multiple' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() == true || this.isChanged() )
+										element.setAttribute( 'multiple', this.getValue() );
+								}
+							}
+						]
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/dialogs/textarea.js
===================================================================
--- _source/plugins/forms/dialogs/textarea.js	(revision 0)
+++ _source/plugins/forms/dialogs/textarea.js	(revision 0)
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'textarea', function( editor )
+{
+	return {
+		title : editor.lang.textarea.title,
+		minWidth : 400,
+		minHeight : 230,
+		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" )
+			{
+				this._element = element;
+				this.setupContent( element );
+			}
+		},
+		onOk : function()
+		{
+			var editor,
+				element = this._element,
+				isInsertMode = !element;
+
+			if ( isInsertMode )
+			{
+				editor = this.getParentEditor();
+				element = editor.document.createElement( 'textarea' );
+			}
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.textarea.title,
+				title : editor.lang.textarea.title,
+				accessKey : 'I',
+				elements : [
+					{
+						id : 'txtName',
+						type : 'text',
+						label : editor.lang.common.name,
+						'default' : '',
+						accessKey : 'N',
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'name' ) );
+							this.focus();
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'name', this.getValue() );
+						}
+					},
+					{
+						id : 'txtColumns',
+						type : 'text',
+						label : editor.lang.textarea.cols,
+						'default' : '',
+						accessKey : 'C',
+						style : 'width:50px',
+						validate: function()
+						{
+							var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
+							return func.apply( this );
+						},
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'cols' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'cols', this.getValue() );
+						}
+					},
+					{
+						id : 'txtRows',
+						type : 'text',
+						label : editor.lang.textarea.rows,
+						'default' : '',
+						accessKey : 'R',
+						style : 'width:50px',
+						validate: function()
+						{
+							var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
+							return func.apply( this );
+						},
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'rows' ) );
+						},
+						commit : function( element )
+						{
+							if ( this.getValue() != '' || this.isChanged() )
+								element.setAttribute( 'rows', this.getValue() );
+						}
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/dialogs/textfield.js
===================================================================
--- _source/plugins/forms/dialogs/textfield.js	(revision 0)
+++ _source/plugins/forms/dialogs/textfield.js	(revision 0)
@@ -0,0 +1,167 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.dialog.add( 'textfield', function( editor )
+{
+	return {
+		title : editor.lang.textfield.title,
+		minWidth : 400,
+		minHeight : 230,
+		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' ) ) )
+			{
+				this._element = element;
+				this.setupContent( element );
+			}
+		},
+		onOk : function()
+		{
+			var editor,
+				element = this._element,
+				isInsertMode = !element;
+
+			if ( isInsertMode )
+			{
+				editor = this.getParentEditor();
+				element = editor.document.createElement( 'input' );
+				element.setAttribute( 'type', 'text' );
+			}
+			this.commitContent( element );
+
+			if ( isInsertMode )
+			{
+				this.restoreSelection();
+				this.clearSavedSelection();
+				editor.insertElement( element );
+			}
+		},
+		contents : [
+			{
+				id : 'info',
+				label : editor.lang.textfield.title,
+				title : editor.lang.textfield.title,
+				accessKey : 'I',
+				elements : [
+					{
+						type : 'hbox',
+						widths : [ '50%', '50%' ],
+						children :
+						[
+							{
+								id : 'txtName',
+								type : 'text',
+								label : editor.lang.textfield.name,
+								'default' : '',
+								accessKey : 'N',
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'name' ) );
+									this.focus();
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'name', this.getValue() );
+								}
+							},
+							{
+								id : 'txtValue',
+								type : 'text',
+								label : editor.lang.textfield.value,
+								'default' : '',
+								accessKey : 'V',
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'value' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'value', this.getValue() );
+								}
+							}
+						]
+					},
+					{
+						type : 'hbox',
+						widths : [ '50%', '50%' ],
+						children :
+						[
+							{
+								id : 'txtTextCharWidth',
+								type : 'text',
+								label : editor.lang.textfield.charWidth,
+								'default' : '',
+								accessKey : 'C',
+								style : 'width:50px',
+								validate: function()
+								{
+									var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
+									return isValid = func.apply( this );
+								},
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'size' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'size', this.getValue() );
+								}
+							},
+							{
+								id : 'txtMaxChars',
+								type : 'text',
+								label : editor.lang.textfield.maxChars,
+								'default' : '',
+								accessKey : 'M',
+								style : 'width:50px',
+								validate: function()
+								{
+									var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
+									return isValid = func.apply( this );
+								},
+								setup : function( element )
+								{
+									this.setValue( element.getAttribute( 'maxlength' ) );
+								},
+								commit : function( element )
+								{
+									if ( this.getValue() != '' || this.isChanged() )
+										element.setAttribute( 'maxlength', this.getValue() );
+								}
+							}
+						]
+					},
+					{
+						id : 'cmbType',
+						type : 'select',
+						label : editor.lang.textfield.type,
+						'default' : 'test',
+						accessKey : 'M',
+						items :
+						[
+							[ editor.lang.textfield.typeText, 'text' ],
+							[ editor.lang.textfield.typePass, 'pass' ],
+						],
+						setup : function( element )
+						{
+							this.setValue( element.getAttribute( 'type' ) );
+						},
+						commit : function( element )
+						{
+							element.setAttribute( 'type', this.getValue() );
+						}
+					}
+				]
+			}
+		]
+	};
+});
Index: _source/plugins/forms/plugin.js
===================================================================
--- _source/plugins/forms/plugin.js	(revision 0)
+++ _source/plugins/forms/plugin.js	(revision 0)
@@ -0,0 +1,244 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @file Forms Plugin
+ */
+
+CKEDITOR.plugins.add( 'forms',
+{
+	init : function( editor )
+	{
+		var forms = CKEDITOR.plugins.forms;
+		editor.ui.addButton( 'Form',
+			{
+				label : editor.lang.common.form,
+				command : 'form'
+			});
+		editor.addCommand( 'form', new CKEDITOR.dialogCommand( 'form' ) );
+
+		editor.ui.addButton( 'Checkbox',
+			{
+				label : editor.lang.common.checkbox,
+				command : 'checkbox'
+			});
+		editor.addCommand( 'checkbox', new CKEDITOR.dialogCommand( 'checkbox' ) );
+
+		editor.ui.addButton( 'Radio',
+			{
+				label : editor.lang.common.radio,
+				command : 'radio'
+			});
+		editor.addCommand( 'radio', new CKEDITOR.dialogCommand( 'radio' ) );
+
+		editor.ui.addButton( 'TextField',
+			{
+				label : editor.lang.common.textField,
+				command : 'textfield'
+			});
+		editor.addCommand( 'textfield', new CKEDITOR.dialogCommand( 'textfield' ) );
+
+		editor.ui.addButton( 'Textarea',
+			{
+				label : editor.lang.common.textarea,
+				command : 'textarea'
+			});
+		editor.addCommand( 'textarea', new CKEDITOR.dialogCommand( 'textarea' ) );
+
+		editor.ui.addButton( 'Select',
+			{
+				label : editor.lang.common.select,
+				command : 'select'
+			});
+		editor.addCommand( 'select', new CKEDITOR.dialogCommand( 'select' ) );
+
+		editor.ui.addButton( 'Button',
+			{
+				label : editor.lang.common.button,
+				command : 'button'
+			});
+		editor.addCommand( 'button', new CKEDITOR.dialogCommand( 'button' ) );
+
+		editor.ui.addButton( 'ImageButton',
+			{
+				label : editor.lang.common.imageButton,
+				command : 'imagebutton'
+			});
+		editor.addCommand( 'imagebutton', new CKEDITOR.dialogCommand( 'imagebutton' ) );
+
+		editor.ui.addButton( 'HiddenField',
+			{
+				label : editor.lang.common.hiddenField,
+				command : 'hiddenfield'
+			});
+		editor.addCommand( 'hiddenfield', new CKEDITOR.dialogCommand( 'hiddenfield' ) );
+
+		CKEDITOR.dialog.add( 'form',		this.path + 'dialogs/form.js' );
+		CKEDITOR.dialog.add( 'checkbox',	this.path + 'dialogs/checkbox.js' );
+		CKEDITOR.dialog.add( 'radio', 		this.path + 'dialogs/radio.js' );
+		CKEDITOR.dialog.add( 'textfield',	this.path + 'dialogs/textfield.js' );
+		CKEDITOR.dialog.add( 'textarea',	this.path + 'dialogs/textarea.js' );
+		CKEDITOR.dialog.add( 'select',		this.path + 'dialogs/select.js' );
+		CKEDITOR.dialog.add( 'button',		this.path + 'dialogs/button.js' );
+		CKEDITOR.dialog.add( 'hiddenfield',	this.path + 'dialogs/hiddenfield.js' );
+		CKEDITOR.dialog.add( 'imagebutton',	CKEDITOR.plugins.getPath('image') + 'dialogs/image.js' );
+	},
+	requires : [ 'image' ]
+} );
+
+CKEDITOR.plugins.forms =
+{
+	select :
+	{
+		// Add a new option to a SELECT object (combo or list).
+		addOption : function( combo, optionText, optionValue, documentObject, index )
+		{
+			combo = this._getObject( combo, false );
+			var oOption;
+			if ( documentObject )
+				oOption = documentObject.createElement( "OPTION" );
+			else
+				oOption = document.createElement( "OPTION" );
+
+			oOption = this._getObject( oOption, false );
+
+			if ( combo && oOption && oOption.getName() == 'option' )
+			{
+				 if ( index != null && index < combo.getChildCount() )
+				 {
+					index = index < 0 ? 0 : index;
+					var indexOpt = combo.getChild( index );
+					indexOpt.insertBeforeMe( oOption );						//Doesn't work in IE.
+				}
+				else
+					combo.append( oOption );
+
+				oOption.setText( optionText.length > 0 ? CKEDITOR.tools.htmlEncode( optionText ) : '' );
+				oOption.setValue( optionValue );
+			}
+			else
+				return false;
+
+			return oOption;
+		},
+
+		// Remove all selected options from a SELECT object.
+		removeSelectedOptions : function ( combo )
+		{
+			combo = this._getObject( combo, true );
+
+			// Save the selected index
+			var iSelectedIndex = combo.selectedIndex,
+				oOptions = combo.options;
+
+			// Remove all selected options.
+			for ( var i = oOptions.length - 1 ; i >= 0 ; i-- )
+				if ( oOptions[i].selected ) combo.remove(i);
+
+			// Reset the selection based on the original selected index.
+			if ( combo.options.length > 0 )
+			{
+				if ( iSelectedIndex >= combo.options.length ) 
+					iSelectedIndex = combo.options.length - 1;
+				combo.selectedIndex = iSelectedIndex;
+			}
+		},
+
+		//Modify option  from a SELECT object.
+		modifyOption : function( combo, index, title, value )
+		{
+			combo = this._getObject( combo, true  );
+			if ( index < 0 ) return ;
+
+			combo.options[ index ].innerHTML	= CKEDITOR.tools.htmlEncode( title ) ;
+			combo.options[ index ].value		= CKEDITOR.tools.htmlEncode( value ) ;
+		},
+		removeAllOptions : function( combo )
+		{
+			combo = this._getObject( combo, true );
+			while( combo.options.length )
+				combo.options[0].parentNode.removeChild( combo.options[0] );
+		},
+
+		// Moves the selected option by a number of steps (also negative).
+		changeOptionPosition : function ( combo, steps, documentObject )
+		{
+			combo = this._getObject( combo, false  );
+			var iActualIndex = this.getSelectedIndex( combo );
+			if ( iActualIndex < 0 )
+				return false;
+
+			var iFinalIndex = iActualIndex + steps;
+			iFinalIndex = ( iFinalIndex < 0 ) ? 0 : iFinalIndex;
+
+			if ( iFinalIndex >= combo.getChildCount() )
+				iFinalIndex = combo.getChildCount() - 1;
+
+			if ( iActualIndex == iFinalIndex )
+				return false;
+
+			var oOption = combo.getChild( iActualIndex ),
+				sText	= this._htmlDecode( oOption.getText() ),
+				sValue	= this._htmlDecode( oOption.getValue() );
+
+			oOption.remove();
+			if ( !documentObject )
+				documentObject = null;
+
+			oOption = this.addOption( combo, sText, sValue, documentObject, iFinalIndex );
+			this.setSelectedIndex( combo, iFinalIndex );
+			return oOption;
+		},
+		getSelectedIndex : function( combo )
+		{
+			combo = this._getObject( combo, true );
+			var iIndex = combo ? combo.selectedIndex : -1;
+			return iIndex;
+		},
+		setSelectedIndex : function( combo, index )
+		{
+			combo = this._getObject( combo, true );
+			if ( index < 0 ) return ;
+			combo.selectedIndex = index;
+			return combo;
+		},
+		getOptions : function ( combo )
+		{
+			combo = this._getObject( combo, true );
+			return combo ? combo.options : false;
+		},
+		_getObject : function ( obj, getReal )
+		{
+			if ( obj )
+			{
+				// Dialog element.
+				if ( obj.domId && obj.getInputElement().$ )
+					return  getReal ? obj.getInputElement().$ : obj.getInputElement();
+
+				else if ( obj.tagName && ( obj.tagName.toLowerCase() == 'select' || obj.tagName.toLowerCase() == 'option' ) )
+					return getReal ? obj : new CKEDITOR.dom.element( obj );
+
+				else if ( obj.$ )
+					return getReal ? obj.$ : obj;
+
+				return false;
+			}
+			else
+				return false;
+		},
+		_htmlDecode : function( text )
+		{
+			if ( !text )
+				return '';
+
+			text = text.replace( /&gt;/g, '>' );
+			text = text.replace( /&lt;/g, '<' );
+			text = text.replace( /&amp;/g, '&' );
+
+			return text;
+		}
+	}
+}
+
Index: _source/plugins/toolbar/plugin.js
===================================================================
--- _source/plugins/toolbar/plugin.js	(revision 3043)
+++ _source/plugins/toolbar/plugin.js	(working copy)
@@ -211,6 +211,7 @@
 		'Bold', 'Italic', 'Underline', 'Strike', '-',
 		'Subscript', 'Superscript', '-',
 		'SelectAll', 'RemoveFormat', '-',
+		'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField', '-',
 		'Smiley', 'HorizontalRule', 'SpecialChar', 'PageBreak'
 	]
 ];
