Index: CKEditor/branches/versions/3.3.x/CHANGES.html
===================================================================
--- CKEditor/branches/versions/3.3.x/CHANGES.html	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/CHANGES.html	(revision 5488)
@@ -49,4 +49,6 @@
 		<li><a href="http://dev.fckeditor.net/ticket/3593">#3593</a> : Apply contentEditable="true" instead of designMode="on" to allow creating uneditable content elements in all browsers.</li>
 		<li><a href="http://dev.fckeditor.net/ticket/4649">#4649</a> : Accessible color picker dialog.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4231">#4231</a> : Option to restrict manual resizing of the editor to only one direction with config.resize_dir.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5479">#5479</a> : Classic asp integration file and samples.</li>
 	</ul>
 	<p>
@@ -77,4 +79,26 @@
 		<li><a href="http://dev.fckeditor.net/ticket/5562">#5562</a> : [IE] Unable to have "contentEditable:false" in effect in IE8 stricts mode.</li>
 		<li><a href="http://dev.fckeditor.net/ticket/5660">#5660</a> : [Firefox] Native error when focus an maximized editor.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5512">#5512</a> : Open context menu with SHIFT+F10 doesn't get correct editor selection.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5433">#5433</a> : English protocol text directions in Link dialog are not incorrect in 'rtl' UI languages.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5553">#5553</a> : Paste dialog clipboard area text direction is incorrect for 'rtl' content languages.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4734">#4734</a> : Font size resets when font name is changed in an empty numbered list.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5237">#5237</a> : English text in dialogs' title is flipped when using RTL language.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5632">#5632</a> : SCAYT word marker is not visible on text with background-color set.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/3257">#3257</a> : Create list doesn't keep blocks as headings.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5111">#5111</a> : [Firefox] JAWS doesn't respect PC cursor mode (application role) on toolbar.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4125">#4125</a> : Remove Format command incorrectly removes SCAYT word markers.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5530">#5530</a> : Page break for printing can't be removed with undo.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5381">#5381</a> : Unable to place cursor between two paragraphs in body.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5568">#5568</a> : [IE6/7] Selecting a entire table cell changes the original range.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5623">#5623</a> : [Firefox] Apply style that edges another inline style result incorrect.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5586">#5586</a> : [Firefox] Maximize the second editor ruins fullscreen mode.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5671">#5671</a> : SCAYT bookstrap script could be added multiple times unnecessarily.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5617">#5617</a> : Html filter system does not allow two 'text' filter rules.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/5663">#5663</a> : General memory clean up after destroying last instance.</li>
+		<li>Updated the following language files:<ul>
+			<li><a href="http://dev.fckeditor.net/ticket/5432">#5432</a> : Dutch;</li>
+			<li><a href="http://dev.fckeditor.net/ticket/5619">#5619</a> : Finnish;</li>
+			<li><a href="http://dev.fckeditor.net/ticket/5515">#5515</a> : Hebrew;</li>
+		</ul></li>
 	</ul>
 	<h3>
Index: CKEditor/branches/versions/3.3.x/_samples/asp/advanced.asp
===================================================================
--- CKEditor/branches/versions/3.3.x/_samples/asp/advanced.asp	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/_samples/asp/advanced.asp	(revision 5488)
@@ -0,0 +1,105 @@
+<%@  codepage="65001" language="VBScript" %>
+<% Option Explicit %>
+<!-- #INCLUDE file="../../ckeditor.asp" -->
+<%
+
+	' You must set "Enable Parent Paths" on your web site
+	' in order for the above relative include to work.
+	' Or you can use #INCLUDE VIRTUAL="/full path/ckeditor.asp"
+
+%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Sample - CKEditor</title>
+	<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+	<link href="../sample.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+	<h1>
+		CKEditor Sample
+	</h1>
+	<!-- This <div> holds alert messages to be display in the sample page. -->
+	<div id="alerts">
+		<noscript>
+			<p>
+				<strong>CKEditor requires JavaScript to run</strong>. In a browser with no JavaScript
+				support, like yours, you should still see the contents (HTML data) and you should
+				be able to edit it normally, without a rich editor interface.
+			</p>
+		</noscript>
+	</div>
+	<!-- This <fieldset> holds the HTML that you will usually find in your pages. -->
+	<fieldset title="Output">
+		<legend>Output</legend>
+		<form action="sample_posteddata.asp" method="post">
+			<p>
+				<label>Editor 1:</label><br/>
+			</p>
+<%
+	' Create class instance.
+	dim editor, initialValue, code, textareaAttributes
+	set editor = New CKEditor
+
+	' Do not print the code directly to the browser, return it instead
+	editor.returnOutput = true
+
+	' Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+	'   editor.basePath = "/ckeditor/"
+	' If not set, CKEditor will default to /ckeditor/
+	editor.basePath = "../../"
+
+	' Set global configuration (will be used by all instances of CKEditor).
+	editor.config("width") = 600
+
+	' Change default textarea attributes
+	set textareaAttributes = CreateObject("Scripting.Dictionary")
+	textareaAttributes.Add "rows", 10
+	textareaAttributes.Add "cols", 80
+	Set editor.textareaAttributes = textareaAttributes
+
+	' The initial value to be displayed in the editor.
+	initialValue = "<p>This is some <strong>sample text</strong>. You are using <a href=""http://ckeditor.com/"">CKEditor</a>.</p>"
+
+	' Create first instance.
+	code = editor.editor("editor1", initialValue)
+
+	response.write code
+%>
+			<p>
+				<label>Editor 2:</label><br/>
+			</p>
+<%
+' Configuration that will be used only by the second editor.
+
+editor.instanceConfig("toolbar") = Array( _
+		Array( "Source", "-", "Bold", "Italic", "Underline", "Strike" ), _
+		Array( "Image", "Link", "Unlink", "Anchor" ) _
+	)
+
+editor.instanceConfig("skin") = "v2"
+
+' Create second instance.
+response.write editor.editor("editor2", initialValue)
+%>
+			<p>
+				<input type="submit" value="Submit"/>
+			</p>
+		</form>
+	</fieldset>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico
+			Knabben. All rights reserved.
+		</p>
+	</div>
+</body>
+</html>
Index: CKEditor/branches/versions/3.3.x/_samples/asp/events.asp
===================================================================
--- CKEditor/branches/versions/3.3.x/_samples/asp/events.asp	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/_samples/asp/events.asp	(revision 5488)
@@ -0,0 +1,136 @@
+<%@  codepage="65001" language="VBScript" %>
+<% Option Explicit %>
+<!-- #INCLUDE file="../../ckeditor.asp" -->
+<%
+
+	' You must set "Enable Parent Paths" on your web site
+	' in order for the above relative include to work.
+	' Or you can use #INCLUDE VIRTUAL="/full path/ckeditor.asp"
+
+%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Sample - CKEditor</title>
+	<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+	<link href="../sample.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+	<h1>
+		CKEditor Sample
+	</h1>
+	<!-- This <div> holds alert messages to be display in the sample page. -->
+	<div id="alerts">
+		<noscript>
+			<p>
+				<strong>CKEditor requires JavaScript to run</strong>. In a browser with no JavaScript
+				support, like yours, you should still see the contents (HTML data) and you should
+				be able to edit it normally, without a rich editor interface.
+			</p>
+		</noscript>
+	</div>
+	<!-- This <fieldset> holds the HTML that you will usually find in your pages. -->
+	<fieldset title="Output">
+		<legend>Output</legend>
+		<form action="sample_posteddata.asp" method="post">
+			<p>
+				<label>Editor 1:</label><br/>
+			</p>
+<%
+
+''
+ ' Adds global event, will hide "Target" tab in Link dialog in all instances.
+ '
+function CKEditorHideLinkTargetTab(editor)
+	dim functionCode
+	functionCode = "function (ev) {" & vbcrlf & _
+		"// Take the dialog name and its definition from the event data" & vbcrlf & _
+		"var dialogName = ev.data.name;" & vbcrlf & _
+		"var dialogDefinition = ev.data.definition;" & vbcrlf & _
+		"" & vbcrlf & _
+		"// Check if the definition is from the Link dialog." & vbcrlf & _
+		"if ( dialogName == 'link' )" & vbcrlf & _
+		"	dialogDefinition.removeContents('target')" & vbcrlf & _
+	"}" & vbcrlf
+
+	editor.addGlobalEventHandler "dialogDefinition", functionCode
+end function
+
+''
+ ' Adds global event, will notify about opened dialog.
+ '
+function CKEditorNotifyAboutOpenedDialog(editor)
+	dim functionCode
+	functionCode = "function (evt) {" & vbcrlf & _
+		"alert('Loading dialog: ' + evt.data.name);" & vbcrlf & _
+	"}"
+
+	editor.addGlobalEventHandler "dialogDefinition", functionCode
+end function
+
+
+dim editor, initialValue
+
+' Create class instance.
+set editor = new CKEditor
+
+' Set configuration option for all editors.
+editor.config("width") = 750
+
+' Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+'   editor.basePath = "/ckeditor/"
+' If not set, CKEditor will default to /ckeditor/
+editor.basePath = "../../"
+
+' The initial value to be displayed in the editor.
+initialValue = "<p>This is some <strong>sample text</strong>. You are using <a href=""http://ckeditor.com/"">CKEditor</a>.</p>"
+
+' Event that will be handled only by the first editor.
+editor.addEventHandler "instanceReady", "function (evt) {	alert('Loaded editor: ' + evt.editor.name );}"
+
+' Create first instance.
+editor.editor "editor1", initialValue
+
+' Clear event handlers, instances that will be created later will not have
+' the 'instanceReady' listener defined a couple of lines above.
+editor.clearEventHandlers empty
+%>
+			<p>
+				<label>Editor 2:</label><br/>
+			</p>
+<%
+' Configuration that will be used only by the second editor.
+editor.instanceConfig("width") = 600
+editor.instanceConfig("toolbar") = "Basic"
+
+' Add some global event handlers (for all editors).
+CKEditorHideLinkTargetTab(editor)
+CKEditorNotifyAboutOpenedDialog(editor)
+
+' Event that will be handled only by the second editor.
+editor.addInstanceEventHandler "instanceReady", "function (evt) { alert('Loaded second editor: ' + evt.editor.name );}"
+
+' Create second instance.
+editor.editor "editor2", initialValue
+%>
+			<p>
+				<input type="submit" value="Submit"/>
+			</p>
+		</form>
+	</fieldset>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico
+			Knabben. All rights reserved.
+		</p>
+	</div>
+</body>
+</html>
Index: CKEditor/branches/versions/3.3.x/_samples/asp/index.html
===================================================================
--- CKEditor/branches/versions/3.3.x/_samples/asp/index.html	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/_samples/asp/index.html	(revision 5488)
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>ASP integration Samples List - CKEditor</title>
+	<link type="text/css" rel="stylesheet" href="../sample.css" />
+</head>
+<body>
+	<h1>
+		CKEditor Samples List for ASP
+	</h1>
+	<h2>
+		Overview
+	</h2>
+	<p>The ckeditor.asp file provides a wrapper to ease the work of creating CKEditor instances from classic Asp.</p>
+	<p>To use it, you must first include it into your page:
+	<code>
+		&lt;!-- #INCLUDE file="../../ckeditor.asp" --&gt;
+	</code>
+	Of course, you should adjust the path to make it point to the correct location, and maybe use a full path (with virtual="" instead of file="")
+	</p>
+	<p>After that script is included, you can use it in different ways, based on the following pattern:</p>
+
+<ol>
+	<li>
+		Create an instance of the CKEditor class:
+<pre>dim editor
+set editor = New CKEditor</pre>
+	</li>
+	<li>
+		Set the path to the folder where CKEditor has been installed, by default it will use /ckeditor/
+		<pre>editor.basePath = "../../"</pre>
+	</li>
+	<li>
+	Now use one of the three main methods to create the CKEditor instances:
+	<ul>
+		<li>
+				Replace textarea with id (or name) "editor1".
+			<pre>editor.replaceInstance "editor1"</pre>
+		</li>
+		<li>
+			Replace all textareas with CKEditor.
+			<pre>editor.replaceAll empty</pre>
+		</li>
+		<li>
+			Create a textarea element and attach CKEditor to it.
+			<pre>editor.editor "editor1", initialValue</pre>
+		</li>
+	</ul>
+	</li>
+</ol>
+<p>Before step 3 you can use a number of methods and properties to adjust the behavior of this class and the CKEditor instances
+that will be created:</p>
+<ul>
+	<li>returnOutput : if set to true, the functions won't dump the code with response.write, but instead they will return it so 
+	you can do anything you want</li>
+	<li>basePath: location of the CKEditor scripts</li>
+	<li>initialized: if you set it to true, it means that you have already included the CKEditor.js file into the page and it 
+		doesn't have to be generated again.</li>
+	<li>textareaAttributes: You can set here a Dictionary object with the attributes that you want to output in the call to the "editor" method.</li>
+	
+	<li>config: Allows to set config values for all the instances from now on.</li>
+	<li>instanceConfig: Allows to set config values just for the next instance.</li>
+
+	<li>addEventHandler: Adds an event handler for all the instances from now on.</li>
+	<li>addInstanceEventHandler: Adds an event handler just for the next instance.</li>
+	<li>addGlobalEventHandler: Adds an event handler for the global CKEDITOR object.</li>
+
+	<li>clearEventHandlers: Removes one or all the event handlers from all the instances from now on.</li>
+	<li>clearInstanceEventHandlers: Removes one or all the event handlers  from the next instance.</li>
+	<li>clearGlobalEventHandlers: Removes one or all the event handlers  from the global CKEDITOR object.</li>
+
+</ul>
+
+	<h2>
+		Basic Samples
+	</h2>
+	<ul>
+		<li><a href="replace.asp">Replace existing textareas by code</a></li>
+		<li><a href="replaceAll.asp">Replace all textareas by code</a></li>
+		<li><a href="standalone.asp">Create instances in asp</a></li>
+	</ul>
+	<h2>
+		Advanced Samples
+	</h2>
+	<ul>
+		<li><a href="advanced.asp">Advanced example</a></li>
+		<li><a href="events.asp">Listening to events</a></li>
+	</ul>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico Knabben. All rights reserved.
+		</p>
+	</div>
+</body>
+</html>
Index: CKEditor/branches/versions/3.3.x/_samples/asp/replace.asp
===================================================================
--- CKEditor/branches/versions/3.3.x/_samples/asp/replace.asp	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/_samples/asp/replace.asp	(revision 5488)
@@ -0,0 +1,72 @@
+<%@  codepage="65001" language="VBScript" %>
+<% Option Explicit %>
+<!-- #INCLUDE file="../../ckeditor.asp" -->
+<%
+
+	' You must set "Enable Parent Paths" on your web site
+	' in order for the above relative include to work.
+	' Or you can use #INCLUDE VIRTUAL="/full path/ckeditor.asp"
+
+%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Sample - CKEditor</title>
+	<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+	<link href="../sample.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+	<h1>
+		CKEditor Sample
+	</h1>
+	<!-- This <div> holds alert messages to be display in the sample page. -->
+	<div id="alerts">
+		<noscript>
+			<p>
+				<strong>CKEditor requires JavaScript to run</strong>. In a browser with no JavaScript
+				support, like yours, you should still see the contents (HTML data) and you should
+				be able to edit it normally, without a rich editor interface.
+			</p>
+		</noscript>
+	</div>
+	<!-- This <fieldset> holds the HTML that you will usually find in your pages. -->
+	<fieldset title="Output">
+		<legend>Output</legend>
+		<form action="sample_posteddata.asp" method="post">
+			<p>
+				<label for="editor1">
+					Editor 1:</label><br/>
+				<textarea cols="80" id="editor1" name="editor1" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
+			</p>
+			<p>
+				<input type="submit" value="Submit"/>
+			</p>
+		</form>
+	</fieldset>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico
+			Knabben. All rights reserved.
+		</p>
+	</div>
+	<%
+	' Create class instance.
+	dim editor
+	set editor = New CKEditor
+	' Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+	'   editor.basePath = "/ckeditor/"
+	' If not set, CKEditor will default to /ckeditor/
+	editor.basePath = "../../"
+	' Replace textarea with id (or name) "editor1".
+	editor.replaceInstance "editor1"
+	%>
+</body>
+</html>
Index: CKEditor/branches/versions/3.3.x/_samples/asp/replaceall.asp
===================================================================
--- CKEditor/branches/versions/3.3.x/_samples/asp/replaceall.asp	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/_samples/asp/replaceall.asp	(revision 5488)
@@ -0,0 +1,77 @@
+<%@  codepage="65001" language="VBScript" %>
+<% Option Explicit %>
+<!-- #INCLUDE file="../../ckeditor.asp" -->
+<%
+
+	' You must set "Enable Parent Paths" on your web site
+	' in order for the above relative include to work.
+	' Or you can use #INCLUDE VIRTUAL="/full path/ckeditor.asp"
+
+%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Sample - CKEditor</title>
+	<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+	<link href="../sample.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+	<h1>
+		CKEditor Sample
+	</h1>
+	<!-- This <div> holds alert messages to be display in the sample page. -->
+	<div id="alerts">
+		<noscript>
+			<p>
+				<strong>CKEditor requires JavaScript to run</strong>. In a browser with no JavaScript
+				support, like yours, you should still see the contents (HTML data) and you should
+				be able to edit it normally, without a rich editor interface.
+			</p>
+		</noscript>
+	</div>
+	<!-- This <fieldset> holds the HTML that you will usually find in your pages. -->
+	<fieldset title="Output">
+		<legend>Output</legend>
+		<form action="sample_posteddata.asp" method="post">
+			<p>
+				<label for="editor1">
+					Editor 1:</label><br/>
+				<textarea cols="80" id="editor1" name="editor1" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
+			</p>
+			<p>
+				<label for="editor2">
+					Editor 2:</label><br/>
+				<textarea cols="80" id="editor2" name="editor2" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
+			</p>
+			<p>
+				<input type="submit" value="Submit"/>
+			</p>
+		</form>
+	</fieldset>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico
+			Knabben. All rights reserved.
+		</p>
+	</div>
+	<%
+	' Create class instance.
+	dim editor
+	set editor = New CKEditor
+	' Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+	'   editor.basePath = "/ckeditor/"
+	' If not set, CKEditor will default to /ckeditor/
+	editor.basePath = "../../"
+	' Replace all textareas with CKEditor.
+	editor.replaceAll empty
+	%>
+</body>
+</html>
Index: CKEditor/branches/versions/3.3.x/_samples/asp/sample_posteddata.asp
===================================================================
--- CKEditor/branches/versions/3.3.x/_samples/asp/sample_posteddata.asp	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/_samples/asp/sample_posteddata.asp	(revision 5488)
@@ -0,0 +1,46 @@
+<%@  codepage="65001" language="VBScript" %>
+<% Option Explicit %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Sample - CKEditor</title>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	<link type="text/css" rel="stylesheet" href="../sample.css" />
+</head>
+<body>
+	<h1>
+		CKEditor - Posted Data
+	</h1>
+	<table border="1" cellspacing="0" id="outputSample">
+		<colgroup><col width="100" /></colgroup>
+		<thead>
+			<tr>
+				<th>Field&nbsp;Name</th>
+				<th>Value</th>
+			</tr>
+		</thead>
+			<%
+			Dim sForm
+			For Each sForm in Request.Form
+			%>
+			<tr>
+				<th><%=Server.HTMLEncode( sForm )%></th>
+				<td><pre><%=Server.HTMLEncode( Request.Form(sForm) )%></pre></td>
+			</tr>
+			<% Next %>
+	</table>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico Knabben. All rights reserved.
+		</p>
+	</div>
+</body>
+</html>
Index: CKEditor/branches/versions/3.3.x/_samples/asp/standalone.asp
===================================================================
--- CKEditor/branches/versions/3.3.x/_samples/asp/standalone.asp	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/_samples/asp/standalone.asp	(revision 5488)
@@ -0,0 +1,72 @@
+<%@  codepage="65001" language="VBScript" %>
+<% Option Explicit %>
+<!-- #INCLUDE file="../../ckeditor.asp" -->
+<%
+
+	' You must set "Enable Parent Paths" on your web site
+	' in order for the above relative include to work.
+	' Or you can use #INCLUDE VIRTUAL="/full path/ckeditor.asp"
+
+%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Sample - CKEditor</title>
+	<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+	<link href="../sample.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+	<h1>
+		CKEditor Sample
+	</h1>
+	<!-- This <div> holds alert messages to be display in the sample page. -->
+	<div id="alerts">
+		<noscript>
+			<p>
+				<strong>CKEditor requires JavaScript to run</strong>. In a browser with no JavaScript
+				support, like yours, you should still see the contents (HTML data) and you should
+				be able to edit it normally, without a rich editor interface.
+			</p>
+		</noscript>
+	</div>
+	<!-- This <fieldset> holds the HTML that you will usually find in your pages. -->
+	<fieldset title="Output">
+		<legend>Output</legend>
+		<form action="sample_posteddata.asp" method="post">
+			<p>
+				Editor 1:
+			</p>
+			<p>
+			<%
+				dim initialValue, editor
+				' The initial value to be displayed in the editor.
+				initialValue = "<p>This is some <strong>sample text</strong>.</p>"
+				' Create class instance.
+				set editor = New CKEditor
+				' Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+				'   editor.basePath = "/ckeditor/"
+				' If not set, CKEditor will default to /ckeditor/
+				editor.basePath = "../../"
+				' Create textarea element and attach CKEditor to it.
+				editor.editor "editor1", initialValue
+			%>
+				<input type="submit" value="Submit"/>
+			</p>
+		</form>
+	</fieldset>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico
+			Knabben. All rights reserved.
+		</p>
+	</div>
+</body>
+</html>
Index: CKEditor/branches/versions/3.3.x/_source/core/ckeditor.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/core/ckeditor.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/core/ckeditor.js	(revision 5488)
@@ -70,4 +70,14 @@
 };
 
+/**
+ * Perform global clean up to free as much memory as possible
+ * when there are no instances left
+ */
+CKEDITOR.on( 'instanceDestroyed', function ()
+	{
+		if ( CKEDITOR.tools.isEmpty( this.instances ) )
+			CKEDITOR.fire( 'reset' );
+	});
+
 // Load the bootstrap script.
 CKEDITOR.loader.load( 'core/_bootstrap' );		// @Packager.RemoveLine
Index: CKEditor/branches/versions/3.3.x/_source/core/dom/domobject.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/core/dom/domobject.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/core/dom/domobject.js	(revision 5488)
@@ -144,4 +144,9 @@
 	var customData = {};
 
+	CKEDITOR.on( 'reset', function()
+		{
+			customData = {};
+		});
+
 	/**
 	 * Determines whether the specified object is equal to the current object.
Index: CKEditor/branches/versions/3.3.x/_source/core/dom/range.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/core/dom/range.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/core/dom/range.js	(revision 5488)
@@ -1241,5 +1241,5 @@
 		 * @param {Number} mode  ( CKEDITOR.SHRINK_ELEMENT | CKEDITOR.SHRINK_TEXT ) The shrinking mode.
 		 */
-		shrink : function( mode )
+		shrink : function( mode, selectContents )
 		{
 			// Unable to shrink a collapsed range.
@@ -1316,5 +1316,5 @@
 				{
 					var textStart = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastForward' : 'next']();
-					textStart && this.setStartBefore( textStart );
+					textStart && this.setStartAt( textStart, selectContents ? CKEDITOR.POSITION_AFTER_START : CKEDITOR.POSITION_BEFORE_START );
 				}
 
@@ -1323,5 +1323,5 @@
 					walker.reset();
 					var textEnd = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastBackward' : 'previous']();
-					textEnd && this.setEndAfter( textEnd );
+					textEnd && this.setEndAt( textEnd, selectContents ? CKEDITOR.POSITION_BEFORE_END : CKEDITOR.POSITION_AFTER_END );
 				}
 
@@ -1383,4 +1383,9 @@
 			// ignore it for now.
 
+			// Fixing invalid range start inside dtd empty elements.
+			if( startNode.type == CKEDITOR.NODE_ELEMENT
+				&& CKEDITOR.dtd.$empty[ startNode.getName() ] )
+				startNode = startNode.getParent(), startOffset = startNode.getIndex();
+			
 			this.startContainer	= startNode;
 			this.startOffset	= startOffset;
@@ -1408,4 +1413,9 @@
 			// will not need this check for our use of this class so we can ignore
 			// it for now.
+
+			// Fixing invalid range end inside dtd empty elements.
+			if( endNode.type == CKEDITOR.NODE_ELEMENT 
+				&& CKEDITOR.dtd.$empty[ endNode.getName() ] )
+				endNode = endNode.getParent(), endOffset = endNode.getIndex() + 1;
 
 			this.endContainer	= endNode;
Index: CKEditor/branches/versions/3.3.x/_source/core/htmlparser/filter.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/core/htmlparser/filter.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/core/htmlparser/filter.js	(revision 5488)
@@ -228,24 +228,50 @@
 	}
 
+	// Invoke filters sequentially on the array, break the iteration
+	// when it doesn't make sense to continue anymore.
 	function callItems( currentEntry )
 	{
-		var isObject = ( typeof currentEntry == 'object' );
+		var isNode = currentEntry.type
+			|| currentEntry instanceof CKEDITOR.htmlParser.fragment;
 
 		for ( var i = 0 ; i < this.length ; i++ )
 		{
+			// Backup the node info before filtering.
+			if ( isNode )
+			{
+				var orgType = currentEntry.type,
+						orgName = currentEntry.name;
+			}
+
 			var item = this[ i ],
 				ret = item.apply( window, arguments );
 
-			if ( typeof ret != 'undefined' )
-			{
-				if ( ret === false )
-					return false;
-
-				if ( isObject && ret != currentEntry )
+			if ( ret === false )
+				return ret;
+
+			// We're filtering node (element/fragment).
+			if ( isNode )
+			{
+				// No further filtering if it's not anymore 
+				// fitable for the subsequent filters.
+				if ( ret && ( ret.name != orgName
+					|| ret.type != orgType ) )
+				{
 					return ret;
-			}
-		}
-
-		return null;
+				}
+			}
+			// Filtering value (nodeName/textValue/attrValue).
+			else
+			{
+				// No further filtering if it's not
+				// any more values.
+				if ( typeof ret != 'string' )
+					return ret;
+			}
+
+			ret != undefined && ( currentEntry = ret );
+		}
+
+		return currentEntry;
 	}
 })();
Index: CKEditor/branches/versions/3.3.x/_source/core/tools.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/core/tools.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/core/tools.js	(revision 5488)
@@ -1,3 +1,3 @@
-﻿/*
+/*
 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.html or http://ckeditor.com/license
@@ -12,4 +12,9 @@
 {
 	var functions = [];
+
+	CKEDITOR.on( 'reset', function()
+		{
+			functions = [];
+		});
 
 	/**
@@ -692,4 +697,16 @@
 			}
 			return returnValue;
+		},
+
+		/**
+		 * Generate a combined key from a series of params.
+		 * @param {String} subKey One or more string used as sub keys.
+		 * @example
+		 * var key = CKEDITOR.tools.genKey( 'key1', 'key2', 'key3' );
+		 * alert( key );		// "key1-key2-key3".
+		 */
+		genKey : function()
+		{
+			return Array.prototype.slice.call( arguments ).join( '-' );
 		}
 	};
Index: CKEditor/branches/versions/3.3.x/_source/lang/_translationstatus.txt
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/lang/_translationstatus.txt	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/lang/_translationstatus.txt	(revision 5488)
@@ -21,5 +21,5 @@
 eu.js      Found: 403 Missing: 121
 fa.js      Found: 302 Missing: 222
-fi.js      Found: 489 Missing: 35
+fi.js      Found: 518 Missing: 6
 fo.js      Found: 420 Missing: 104
 fr-ca.js   Found: 301 Missing: 223
@@ -27,5 +27,5 @@
 gl.js      Found: 283 Missing: 241
 gu.js      Found: 300 Missing: 224
-he.js      Found: 467 Missing: 57
+he.js      Found: 523 Missing: 1
 hi.js      Found: 302 Missing: 222
 hr.js      Found: 404 Missing: 120
@@ -41,5 +41,5 @@
 ms.js      Found: 265 Missing: 259
 nb.js      Found: 470 Missing: 54
-nl.js      Found: 467 Missing: 57
+nl.js      Found: 494 Missing: 30
 no.js      Found: 470 Missing: 54
 pl.js      Found: 411 Missing: 113
Index: CKEditor/branches/versions/3.3.x/_source/lang/ar.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/lang/ar.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/lang/ar.js	(revision 5488)
@@ -716,5 +716,5 @@
 	{
 		title		: 'عن CKEditor',
-		dlgTitle	: 'عن rotidEKC',
+		dlgTitle	: 'عن CKEditor',
 		moreInfo	: 'للحصول على معلومات الترخيص ، يرجى زيارة موقعنا على شبكة الانترنت:',
 		copy		: 'حقوق النشر &copy; $1. جميع الحقوق محفوظة.'
Index: CKEditor/branches/versions/3.3.x/_source/lang/fi.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/lang/fi.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/lang/fi.js	(revision 5488)
@@ -128,5 +128,5 @@
 	{
 		toolbar		: 'Lisää linkki/muokkaa linkkiä',
-		other 		: '<other>', // MISSING
+		other 		: '<muu>',
 		menu		: 'Muokkaa linkkiä',
 		title		: 'Linkki',
@@ -193,22 +193,22 @@
 	list:
 	{
-		numberedTitle		: 'Numbered List Properties', // MISSING
-		bulletedTitle		: 'Bulleted List Properties', // MISSING
-		type				: 'Type', // MISSING
-		start				: 'Start', // MISSING
-		circle				: 'Circle', // MISSING
-		disc				: 'Disc', // MISSING
-		square				: 'Square', // MISSING
-		none				: 'None', // MISSING
-		notset				: '<not set>', // MISSING
-		armenian			: 'Armenian numbering', // MISSING
+		numberedTitle		: 'Numeroidun listan ominaisuudet',
+		bulletedTitle		: 'Numeroimattoman listan ominaisuudet',
+		type				: 'Tyyppi',
+		start				: 'Alku',
+		circle				: 'Ympyrä',
+		disc				: 'Levy',
+		square				: 'Neliö',
+		none				: 'Ei mikään',
+		notset				: '<ei asetettu>',
+		armenian			: 'Armeenialainen numerointi',
 		georgian			: 'Georgian numbering (an, ban, gan, etc.)', // MISSING
-		lowerRoman			: 'Lower Roman (i, ii, iii, iv, v, etc.)', // MISSING
-		upperRoman			: 'Upper Roman (I, II, III, IV, V, etc.)', // MISSING
-		lowerAlpha			: 'Lower Alpha (a, b, c, d, e, etc.)', // MISSING
-		upperAlpha			: 'Upper Alpha (A, B, C, D, E, etc.)', // MISSING
-		lowerGreek			: 'Lower Greek (alpha, beta, gamma, etc.)', // MISSING
-		decimal				: 'Decimal (1, 2, 3, etc.)', // MISSING
-		decimalLeadingZero	: 'Decimal leading zero (01, 02, 03, etc.)' // MISSING
+		lowerRoman			: 'Pienet roomalaiset (i, ii, iii, iv, v, jne.)',
+		upperRoman			: 'Isot roomalaiset (I, II, III, IV, V, jne.)',
+		lowerAlpha			: 'Pienet aakkoset (a, b, c, d, e, jne.)',
+		upperAlpha			: 'Isot aakkoset (A, B, C, D, E, jne.)',
+		lowerGreek			: 'Pienet kreikkalaiset (alpha, beta, gamma, jne.)',
+		decimal				: 'Desimaalit (1, 2, 3, jne.)',
+		decimalLeadingZero	: 'Desimaalit, alussa nolla (01, 02, 03, jne.)'
 	},
 	
@@ -411,5 +411,5 @@
 		unlockRatio	: 'Vapauta suhteet',
 		resetSize	: 'Alkuperäinen koko',
-		border		: 'Raja',
+		border		: 'Kehys',
 		hSpace		: 'Vaakatila',
 		vSpace		: 'Pystytila',
@@ -424,5 +424,5 @@
 		validateWidth	: 'Leveyden täytyy olla kokonaisluku.',
 		validateHeight	: 'Korkeuden täytyy olla kokonaisluku.',
-		validateBorder	: 'Reunan täytyy olla kokonaisluku.',
+		validateBorder	: 'Kehyksen täytyy olla kokonaisluku.',
 		validateHSpace	: 'HSpace-määrityksen täytyy olla kokonaisluku.',
 		validateVSpace	: 'VSpace-määrityksen täytyy olla kokonaisluku.'
@@ -432,5 +432,5 @@
 	flash :
 	{
-		properties		: 'Flash ominaisuudet',
+		properties		: 'Flash-ominaisuudet',
 		propertiesTab	: 'Ominaisuudet',
 		title			: 'Flash ominaisuudet',
@@ -681,5 +681,5 @@
 	{
 		title			: 'Oikolue kirjoitettaessa',
-		opera_title		: 'Not supported by Opera', // MISSING
+		opera_title		: 'Opera ei tue tätä ominaisuutta',
 		enable			: 'Ota käyttöön oikoluku kirjoitettaessa',
 		disable			: 'Poista käytöstä oikoluku kirjoitetaessa',
@@ -695,18 +695,18 @@
 		
 		optionsTab		: 'Asetukset',
-		allCaps			: 'Ignore All-Caps Words', // MISSING
-		ignoreDomainNames : 'Ignore Domain Names', // MISSING
-		mixedCase		: 'Ignore Words with Mixed Case', // MISSING
-		mixedWithDigits	: 'Ignore Words with Numbers', // MISSING
+		allCaps			: 'Ohita sanat, jotka on kirjoitettu kokonaan isoilla kirjaimilla',
+		ignoreDomainNames : 'Ohita verkkotunnukset',
+		mixedCase		: 'Ohita sanat, joissa on sekoitettu isoja ja pieniä kirjaimia',
+		mixedWithDigits	: 'Ohita sanat, joissa on numeroita',
 		
 		languagesTab	: 'Kielet',
 		
 		dictionariesTab	: 'Sanakirjat',
-		dic_field_name	: 'Dictionary name', // MISSING
-		dic_create		: 'Create', // MISSING
-		dic_restore		: 'Restore', // MISSING
-		dic_delete		: 'Delete', // MISSING
-		dic_rename		: 'Rename', // MISSING
-		dic_info		: 'Initially the User Dictionary is stored in a Cookie. However, Cookies are limited in size. When the User Dictionary grows to a point where it cannot be stored in a Cookie, then the dictionary may be stored on our server. To store your personal dictionary on our server you should specify a name for your dictionary. If you already have a stored dictionary, please type it\'s name and click the Restore button.', // MISSING
+		dic_field_name	: 'Sanakirjan nimi',
+		dic_create		: 'Luo',
+		dic_restore		: 'Palauta',
+		dic_delete		: 'Poista',
+		dic_rename		: 'Nimeä uudelleen',
+		dic_info		: 'Oletuksena sanakirjat tallennetaan evästeeseen, mutta evästeiden koko on kuitenkin rajallinen. Sanakirjan kasvaessa niin suureksi, ettei se enää mahdu evästeeseen, sanakirja täytyy tallentaa palvelimellemme. Tallentaaksesi sanakirjasi palvelimellemme tulee sinun antaa sille nimi. Jos olet jo tallentanut sanakirjan, anna sen nimi ja klikkaa Palauta-painiketta',
 		
 		aboutTab		: 'Tietoa'
Index: CKEditor/branches/versions/3.3.x/_source/lang/he.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/lang/he.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/lang/he.js	(revision 5488)
@@ -32,9 +32,9 @@
 	 * of reading non-English words. So be careful while translating it.
 	 */
-	editorTitle : 'Rich text editor, %1, press ALT 0 for help.', // MISSING
+	editorTitle : 'עורך טקסט עשיר, %1, לחץ אלט (ALT) + 0 לעזרה.',
 
 	// ARIA descriptions.
-	toolbar	: 'Toolbar', // MISSING
-	editor	: 'Rich Text Editor', // MISSING
+	toolbar	: 'סרגל הכלים',
+	editor	: 'עורך טקסט עשיר',
 
 	// Toolbar buttons without dialogs.
@@ -93,6 +93,6 @@
 		ok				: 'אישור',
 		cancel			: 'ביטול',
-		close			: 'Close', // MISSING
-		preview			: 'Preview', // MISSING
+		close			: 'סגירה',
+		preview			: 'תצוגה מקדימה',
 		generalTab		: 'כללי',
 		advancedTab		: 'אפשרויות מתקדמות',
@@ -100,10 +100,10 @@
 		confirmNewPage	: 'כל השינויים שלא נשמרו יאבדו. האם להעלות דף חדש?',
 		confirmCancel	: 'חלק מהאפשרויות שונו, האם לסגור את הדיאלוג?',
-		options			: 'Options', // MISSING
-		target			: 'Target', // MISSING
-		targetNew		: 'New Window (_blank)', // MISSING
-		targetTop		: 'Topmost Window (_top)', // MISSING
-		targetSelf		: 'Same Window (_self)', // MISSING
-		targetParent	: 'Parent Window (_parent)', // MISSING
+		options			: 'אפשרויות',
+		target			: 'מטרה',
+		targetNew		: 'חלון חדש (_blank)',
+		targetTop		: 'החלון העליון ביותר (_top)',
+		targetSelf		: 'אותו חלון (_self)',
+		targetParent	: 'חלון האב (_parent)',
 
 		// Put the voice-only part of the label in the span.
@@ -113,5 +113,5 @@
 	contextmenu :
 	{
-		options : 'Context Menu Options' // MISSING
+		options : 'אפשרויות תפריט ההקשר'
 	},
 
@@ -121,5 +121,5 @@
 		toolbar		: 'הוספת תו מיוחד',
 		title		: 'בחירת תו מיוחד',
-		options : 'Special Character Options' // MISSING
+		options : 'אפשרויות תווים מיוחדים'
 	},
 
@@ -136,5 +136,5 @@
 		advanced	: 'אפשרויות מתקדמות',
 		type		: 'סוג קישור',
-		toUrl		: 'URL', // MISSING
+		toUrl		: 'כתובת (URL)',
 		toAnchor	: 'עוגן בעמוד זה',
 		toEmail		: 'דוא"ל',
@@ -193,22 +193,22 @@
 	list:
 	{
-		numberedTitle		: 'Numbered List Properties', // MISSING
-		bulletedTitle		: 'Bulleted List Properties', // MISSING
-		type				: 'Type', // MISSING
-		start				: 'Start', // MISSING
-		circle				: 'Circle', // MISSING
-		disc				: 'Disc', // MISSING
-		square				: 'Square', // MISSING
-		none				: 'None', // MISSING
-		notset				: '<not set>', // MISSING
-		armenian			: 'Armenian numbering', // MISSING
-		georgian			: 'Georgian numbering (an, ban, gan, etc.)', // MISSING
-		lowerRoman			: 'Lower Roman (i, ii, iii, iv, v, etc.)', // MISSING
-		upperRoman			: 'Upper Roman (I, II, III, IV, V, etc.)', // MISSING
-		lowerAlpha			: 'Lower Alpha (a, b, c, d, e, etc.)', // MISSING
-		upperAlpha			: 'Upper Alpha (A, B, C, D, E, etc.)', // MISSING
-		lowerGreek			: 'Lower Greek (alpha, beta, gamma, etc.)', // MISSING
-		decimal				: 'Decimal (1, 2, 3, etc.)', // MISSING
-		decimalLeadingZero	: 'Decimal leading zero (01, 02, 03, etc.)' // MISSING
+		numberedTitle		: 'תכונות רשימה ממוספרת',
+		bulletedTitle		: 'תכונות רשימת תבליטים',
+		type				: 'סוג',
+		start				: 'תחילת מספור',
+		circle				: 'עיגול ריק',
+		disc				: 'עיגול מלא',
+		square				: 'ריבוע',
+		none				: 'ללא',
+		notset				: '<לא נקבע>',
+		armenian			: 'ספרות ארמניות',
+		georgian			: 'ספרות גיאורגיות (an, ban, gan וכו\')',
+		lowerRoman			: 'ספירה רומית באותיות קטנות (i, ii, iii, iv, v וכו\')',
+		upperRoman			: 'ספירה רומיות באותיות גדולות (I, II, III, IV, V וכו\')',
+		lowerAlpha			: 'אותיות אנגליות קטנות (a, b, c, d, e וכו\')',
+		upperAlpha			: 'אותיות אנגליות גדולות (A, B, C, D, E וכו\')',
+		lowerGreek			: 'אותיות יווניות קטנות (alpha, beta, gamma וכו\')',
+		decimal				: 'ספרות (1, 2, 3 וכו\')',
+		decimalLeadingZero	: 'ספרות עם 0 בהתחלה (01, 02, 03 וכו\')'
 	},
 	
@@ -246,5 +246,5 @@
 		widthPx		: 'פיקסלים',
 		widthPc		: 'אחוז',
-		widthUnit	: 'width unit', // MISSING
+		widthUnit	: 'יחידת רוחב',
 		height		: 'גובה',
 		cellSpace	: 'מרווח תא',
@@ -409,5 +409,5 @@
 		height		: 'גובה',
 		lockRatio	: 'נעילת היחס',
-		unlockRatio	: 'Unlock Ratio', // MISSING
+		unlockRatio	: 'ביטול נעילת היחס',
 		resetSize	: 'איפוס הגודל',
 		border		: 'מסגרת',
@@ -422,9 +422,9 @@
 		img2Button	: 'האם להפוך את התמונה לכפתור תמונה?',
 		urlMissing	: 'כתובת התמונה חסרה.',
-		validateWidth	: 'Width must be a whole number.', // MISSING
-		validateHeight	: 'Height must be a whole number.', // MISSING
-		validateBorder	: 'Border must be a whole number.', // MISSING
-		validateHSpace	: 'HSpace must be a whole number.', // MISSING
-		validateVSpace	: 'VSpace must be a whole number.' // MISSING
+		validateWidth	: 'שדה הרוחב חייב להיות מספר שלם.',
+		validateHeight	: 'שדה הגובה חייב להיות מספר שלם.',
+		validateBorder	: 'שדה המסגרת חייב להיות מספר שלם.',
+		validateHSpace	: 'שדה המרווח האופקי חייב להיות מספר שלם.',
+		validateVSpace	: 'שדה המרווח האנכי חייב להיות מספר שלם.'
 	},
 
@@ -508,10 +508,10 @@
 		toolbar	: 'סמיילי',
 		title	: 'הוספת סמיילי',
-		options : 'Smiley Options' // MISSING
+		options : 'אפשרויות סמיילים'
 	},
 
 	elementsPath :
 	{
-		eleLabel : 'Elements path', // MISSING
+		eleLabel : 'עץ האלמנטים',
 		eleTitle : '%1 אלמנט'
 	},
@@ -539,5 +539,5 @@
 		pasteMsg	: 'נא להדביק בתוך הקופסה באמצעות (<b>Ctrl/Cmd+V</b>) וללחוץ על <b>אישור</b>.',
 		securityMsg	: 'עקב הגדרות אבטחה בדפדפן, לא ניתן לגשת אל לוח הגזירים (Clipboard) בצורה ישירה. נא להדביק שוב בחלון זה.',
-		pasteArea	: 'Paste Area' // MISSING
+		pasteArea	: 'איזור הדבקה'
 	},
 
@@ -560,5 +560,5 @@
 		button			: 'תבניות',
 		title			: 'תביות תוכן',
-		options : 'Template Options', // MISSING
+		options : 'אפשרויות התבניות',
 		insertOption	: 'החלפת תוכן ממשי',
 		selectPromptMsg	: 'יש לבחור תבנית לפתיחה בעורך.<br />התוכן המקורי ימחק:',
@@ -571,5 +571,5 @@
 	{
 		label		: 'סגנון',
-		panelTitle	: 'Formatting Styles', // MISSING
+		panelTitle	: 'סגנונות פורמט',
 		panelTitle1	: 'סגנונות בלוק',
 		panelTitle2	: 'סגנונות רצף',
@@ -629,5 +629,5 @@
 		textColorTitle	: 'צבע טקסט',
 		bgColorTitle	: 'צבע רקע',
-		panelTitle		: 'Colors', // MISSING
+		panelTitle		: 'צבעים',
 		auto			: 'אוטומטי',
 		more			: 'צבעים נוספים...'
@@ -681,5 +681,5 @@
 	{
 		title			: 'בדיקת איות בזמן כתיבה (SCAYT)',
-		opera_title		: 'Not supported by Opera', // MISSING
+		opera_title		: 'לא זמין בדפדפן אופרה',
 		enable			: 'אפשר SCAYT',
 		disable			: 'בטל SCAYT',
@@ -695,18 +695,18 @@
 		
 		optionsTab		: 'אפשרויות',
-		allCaps			: 'Ignore All-Caps Words', // MISSING
-		ignoreDomainNames : 'Ignore Domain Names', // MISSING
-		mixedCase		: 'Ignore Words with Mixed Case', // MISSING
-		mixedWithDigits	: 'Ignore Words with Numbers', // MISSING
+		allCaps			: 'התעלם ממילים שכל אותיותיהן גדולות',
+		ignoreDomainNames : 'התעלם משמות מתחם',
+		mixedCase		: 'התעלם ממילים עם אותיות גדולות וקטנות ביחד',
+		mixedWithDigits	: 'התעלם ממילים עם מספרים',
 		
 		languagesTab	: 'שפות',
 		
 		dictionariesTab	: 'מילון',
-		dic_field_name	: 'Dictionary name', // MISSING
-		dic_create		: 'Create', // MISSING
-		dic_restore		: 'Restore', // MISSING
-		dic_delete		: 'Delete', // MISSING
-		dic_rename		: 'Rename', // MISSING
-		dic_info		: 'Initially the User Dictionary is stored in a Cookie. However, Cookies are limited in size. When the User Dictionary grows to a point where it cannot be stored in a Cookie, then the dictionary may be stored on our server. To store your personal dictionary on our server you should specify a name for your dictionary. If you already have a stored dictionary, please type it\'s name and click the Restore button.', // MISSING
+		dic_field_name	: 'שם המילון',
+		dic_create		: 'יצירה',
+		dic_restore		: 'שחזור',
+		dic_delete		: 'מחיקה',
+		dic_rename		: 'שינוי שם',
+		dic_info		: 'בהתחלה מילון המשתמש מאוחסן בעוגיה, אך עוגיות מוגבלות במקום. כאשר המילון מגיע לגודל בו הוא אינו יכול להתאכסן בעוגיה, המילון צריך להתאכסן בשרתנו. לשם כך עליך לתת שם למילון. אם כבר יש לך מילון מאוחסן, יש להכניס את שמו וללחוץ על כפתור השחזור.',
 		
 		aboutTab		: 'אודות'
Index: CKEditor/branches/versions/3.3.x/_source/lang/nl.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/lang/nl.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/lang/nl.js	(revision 5488)
@@ -32,9 +32,9 @@
 	 * of reading non-English words. So be careful while translating it.
 	 */
-	editorTitle : 'Rich text editor, %1, press ALT 0 for help.', // MISSING
+	editorTitle : 'Tekstverwerker, %1, druk op ALT 0 voor hulp.',
 
 	// ARIA descriptions.
-	toolbar	: 'Toolbar', // MISSING
-	editor	: 'Rich Text Editor', // MISSING
+	toolbar	: 'Werkbalk',
+	editor	: 'Tekstverwerker',
 
 	// Toolbar buttons without dialogs.
@@ -93,6 +93,6 @@
 		ok				: 'OK',
 		cancel			: 'Annuleren',
-		close			: 'Close', // MISSING
-		preview			: 'Preview', // MISSING
+		close			: 'Sluiten',
+		preview			: 'Voorbeeld',
 		generalTab		: 'Algemeen',
 		advancedTab		: 'Geavanceerd',
@@ -100,10 +100,10 @@
 		confirmNewPage	: 'Alle aangebrachte wijzigingen gaan verloren. Weet u zeker dat u een nieuwe pagina wilt openen?',
 		confirmCancel	: 'Enkele opties zijn gewijzigd. Weet u zeker dat u dit dialoogvenster wilt sluiten?',
-		options			: 'Options', // MISSING
-		target			: 'Target', // MISSING
-		targetNew		: 'New Window (_blank)', // MISSING
-		targetTop		: 'Topmost Window (_top)', // MISSING
-		targetSelf		: 'Same Window (_self)', // MISSING
-		targetParent	: 'Parent Window (_parent)', // MISSING
+		options			: 'Opties',
+		target			: 'Doel',
+		targetNew		: 'Nieuw venster (_blank)',
+		targetTop		: 'Hele venster (_top)',
+		targetSelf		: 'Zelfde venster (_self)',
+		targetParent	: 'Origineel venster (_parent)',
 
 		// Put the voice-only part of the label in the span.
@@ -113,5 +113,5 @@
 	contextmenu :
 	{
-		options : 'Context Menu Options' // MISSING
+		options : 'Context menu opties'
 	},
 
@@ -121,5 +121,5 @@
 		toolbar		: 'Speciaal teken invoegen',
 		title		: 'Selecteer speciaal teken',
-		options : 'Special Character Options' // MISSING
+		options : 'Speciale tekens opties'
 	},
 
@@ -136,5 +136,5 @@
 		advanced	: 'Geavanceerd',
 		type		: 'Linktype',
-		toUrl		: 'URL', // MISSING
+		toUrl		: 'URL',
 		toAnchor	: 'Interne link in pagina',
 		toEmail		: 'E-mail',
@@ -246,5 +246,5 @@
 		widthPx		: 'pixels',
 		widthPc		: 'procent',
-		widthUnit	: 'width unit', // MISSING
+		widthUnit	: 'eenheid breedte',
 		height		: 'Hoogte',
 		cellSpace	: 'Afstand tussen cellen',
@@ -409,5 +409,5 @@
 		height		: 'Hoogte',
 		lockRatio	: 'Afmetingen vergrendelen',
-		unlockRatio	: 'Unlock Ratio', // MISSING
+		unlockRatio	: 'Afmetingen ontgrendelen',
 		resetSize	: 'Afmetingen resetten',
 		border		: 'Rand',
@@ -422,9 +422,9 @@
 		img2Button	: 'Wilt u de geselecteerde afbeelding vervangen door een afbeeldingsknop?',
 		urlMissing	: 'De URL naar de afbeelding ontbreekt.',
-		validateWidth	: 'Width must be a whole number.', // MISSING
-		validateHeight	: 'Height must be a whole number.', // MISSING
-		validateBorder	: 'Border must be a whole number.', // MISSING
-		validateHSpace	: 'HSpace must be a whole number.', // MISSING
-		validateVSpace	: 'VSpace must be a whole number.' // MISSING
+		validateWidth	: 'Breedte moet een heel nummer zijn.',
+		validateHeight	: 'Hoogte moet een heel nummer zijn.',
+		validateBorder	: 'Rand moet een heel nummer zijn.',
+		validateHSpace	: 'HSpace moet een heel nummer zijn.',
+		validateVSpace	: 'VSpace moet een heel nummer zijn.'
 	},
 
@@ -508,10 +508,10 @@
 		toolbar	: 'Smiley',
 		title	: 'Smiley invoegen',
-		options : 'Smiley Options' // MISSING
+		options : 'Smiley opties'
 	},
 
 	elementsPath :
 	{
-		eleLabel : 'Elements path', // MISSING
+		eleLabel : 'Elementenpad',
 		eleTitle : '%1 element'
 	},
@@ -539,5 +539,5 @@
 		pasteMsg	: 'Plak de tekst in het volgende vak gebruik makend van uw toetsenbord (<strong>Ctrl/Cmd+V</strong>) en klik op <strong>OK</strong>.',
 		securityMsg	: 'Door de beveiligingsinstellingen van uw browser is het niet mogelijk om direct vanuit het klembord in de editor te plakken. Middels opnieuw plakken in dit venster kunt u de tekst alsnog plakken in de editor.',
-		pasteArea	: 'Paste Area' // MISSING
+		pasteArea	: 'Plakgebied'
 	},
 
@@ -560,5 +560,5 @@
 		button			: 'Sjablonen',
 		title			: 'Inhoud sjabonen',
-		options : 'Template Options', // MISSING
+		options : 'Template opties',
 		insertOption	: 'Vervang de huidige inhoud',
 		selectPromptMsg	: 'Selecteer het sjabloon dat in de editor geopend moet worden (de actuele inhoud gaat verloren):',
@@ -571,5 +571,5 @@
 	{
 		label		: 'Stijl',
-		panelTitle	: 'Formatting Styles', // MISSING
+		panelTitle	: 'Opmaakstijlen',
 		panelTitle1	: 'Blok stijlen',
 		panelTitle2	: 'In-line stijlen',
@@ -629,5 +629,5 @@
 		textColorTitle	: 'Tekstkleur',
 		bgColorTitle	: 'Achtergrondkleur',
-		panelTitle		: 'Colors', // MISSING
+		panelTitle		: 'Kleuren',
 		auto			: 'Automatisch',
 		more			: 'Meer kleuren...'
Index: CKEditor/branches/versions/3.3.x/_source/plugins/button/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/button/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/button/plugin.js	(revision 5488)
@@ -271,2 +271,7 @@
 	this.add( name, CKEDITOR.UI_BUTTON, definition );
 };
+
+CKEDITOR.on( 'reset', function()
+	{
+		CKEDITOR.ui.button._.instances = [];
+	});
Index: CKEditor/branches/versions/3.3.x/_source/plugins/clipboard/dialogs/paste.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/clipboard/dialogs/paste.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/clipboard/dialogs/paste.js	(revision 5488)
@@ -61,8 +61,12 @@
 			this.parts.dialog.$.offsetHeight;
 
-			var htmlToLoad = '<!doctype html><html><head><style>body { margin: 3px; height: 95%; } </style></head><body>' +
-							 '<script id="cke_actscrpt" type="text/javascript">' +
-							 'window.parent.CKEDITOR.tools.callFunction( ' + CKEDITOR.tools.addFunction( onPasteFrameLoad, this ) + ', this );' +
-							 '</script></body></html>';
+			var htmlToLoad =
+				'<!doctype html><html dir="' + editor.config.contentsLangDirection + '"' +
+				' lang="' + ( editor.config.contentsLanguage || editor.langCode ) + '">' +
+					'<head><style>body { margin: 3px; height: 95%; } </style></head><body>' +
+					'<script id="cke_actscrpt" type="text/javascript">' +
+					'window.parent.CKEDITOR.tools.callFunction( ' + CKEDITOR.tools.addFunction( onPasteFrameLoad, this ) + ', this );' +
+					'</script></body>' +
+				'</html>';
 
 			var iframe = CKEDITOR.dom.element.createFromHtml(
Index: CKEditor/branches/versions/3.3.x/_source/plugins/contextmenu/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/contextmenu/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/contextmenu/plugin.js	(revision 5488)
@@ -209,11 +209,4 @@
 						return;
 
-					// Selection will be unavailable after context menu shows up
-					// in IE, lock it now.
-					if ( CKEDITOR.env.ie )
-					{
-						var selection = this.editor.getSelection();
-						selection && selection.lock();
-					}
 
 					// Cancel the browser context menu.
@@ -258,4 +251,13 @@
 		{
 			this.editor.focus();
+
+			// Selection will be unavailable after context menu shows up
+			// in IE, lock it now.
+			if ( CKEDITOR.env.ie )
+			{
+				var selection = this.editor.getSelection();
+				selection && selection.lock();
+			}
+
 			this._.onMenu( offsetParent || CKEDITOR.document.getDocumentElement(), corner, offsetX || 0, offsetY || 0 );
 		}
Index: CKEditor/branches/versions/3.3.x/_source/plugins/dialog/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/dialog/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/dialog/plugin.js	(revision 5488)
@@ -546,4 +546,5 @@
 		destroy : function()
 		{
+			this.hide();
 			this._.element.remove();
 		},
@@ -699,5 +700,5 @@
 				CKEDITOR.dialog._.currentTop = this;
 				this._.parentDialog = null;
-				addCover( this._.editor );
+				showCover( this._.editor );
 
 				element.on( 'keydown', accessKeyDownHandler );
@@ -803,4 +804,7 @@
 		hide : function()
 		{
+			if ( !this.parts.dialog.isVisible() )
+				return;
+
 			this.fire( 'hide', {} );
 			this._.editor.fire( 'dialogHide', this );
@@ -811,7 +815,11 @@
 			unregisterAccessKey( this );
 
+			// Close any child(top) dialogs first.
+			while( CKEDITOR.dialog._.currentTop != this )
+				CKEDITOR.dialog._.currentTop.hide();
+
 			// Maintain dialog ordering and remove cover if needed.
 			if ( !this._.parentDialog )
-				removeCover();
+				hideCover();
 			else
 			{
@@ -846,5 +854,5 @@
 				CKEDITOR.dialog._.currentZIndex -= 10;
 
-
+			delete this._.parentDialog;
 			// Reset the initial values of the dialog.
 			this.foreach( function( contentObj ) { contentObj.resetInitValue && contentObj.resetInitValue(); } );
@@ -1750,22 +1758,30 @@
 
 	var resizeCover;
-	var coverElement;
-
-	var addCover = function( editor )
+	// Caching resuable covers and allowing only one cover
+	// on screen.
+	var covers = {},
+		currentCover;
+
+	function showCover( editor )
 	{
 		var win = CKEDITOR.document.getWindow();
+		var backgroundColorStyle = editor.config.dialog_backgroundCoverColor || 'white',
+			backgroundCoverOpacity = editor.config.dialog_backgroundCoverOpacity,
+			baseFloatZIndex = editor.config.baseFloatZIndex,
+			coverKey = CKEDITOR.tools.genKey(
+					backgroundColorStyle,
+					backgroundCoverOpacity,
+					baseFloatZIndex ),
+			coverElement = covers[ coverKey ];
 
 		if ( !coverElement )
 		{
-			var backgroundColorStyle = editor.config.dialog_backgroundCoverColor || 'white';
-
 			var html = [
 					'<div style="position: ', ( CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed' ),
-					'; z-index: ', editor.config.baseFloatZIndex,
+					'; z-index: ', baseFloatZIndex,
 					'; top: 0px; left: 0px; ',
 					( !CKEDITOR.env.ie6Compat ? 'background-color: ' + backgroundColorStyle : '' ),
-					'" id="cke_dialog_background_cover">'
+					'" class="cke_dialog_background_cover">'
 				];
-
 
 			if ( CKEDITOR.env.ie6Compat )
@@ -1804,12 +1820,17 @@
 
 			coverElement = CKEDITOR.dom.element.createFromHtml( html.join( '' ) );
-		}
-
-		var element = coverElement;
-
+			coverElement.setOpacity( backgroundCoverOpacity != undefined ? backgroundCoverOpacity : 0.5 );
+
+			coverElement.appendTo( CKEDITOR.document.getBody() );
+			covers[ coverKey ] = coverElement;
+		}
+		else
+			coverElement.	show();
+
+		currentCover = coverElement;
 		var resizeFunc = function()
 		{
 			var size = win.getViewPaneSize();
-			element.setStyles(
+			coverElement.setStyles(
 				{
 					width : size.width + 'px',
@@ -1822,5 +1843,5 @@
 			var pos = win.getScrollPosition(),
 				cursor = CKEDITOR.dialog._.currentTop;
-			element.setStyles(
+			coverElement.setStyles(
 					{
 						left : pos.x + 'px',
@@ -1854,18 +1875,13 @@
 			scrollFunc();
 		}
-
-		var opacity = editor.config.dialog_backgroundCoverOpacity;
-		element.setOpacity( typeof opacity != 'undefined' ? opacity : 0.5 );
-
-		element.appendTo( CKEDITOR.document.getBody() );
 	};
 
-	var removeCover = function()
-	{
-		if ( !coverElement )
+	function hideCover()
+	{
+		if ( !currentCover )
 			return;
 
 		var win = CKEDITOR.document.getWindow();
-		coverElement.remove();
+		currentCover.hide();
 		win.removeListener( 'resize', resizeCover );
 
@@ -1880,4 +1896,11 @@
 		resizeCover = null;
 	};
+	
+	function removeCovers()
+	{
+		for ( var coverId in covers )
+			covers[ coverId ].remove();
+		covers = {};
+	}
 
 	var accessKeyProcessors = {};
@@ -2782,11 +2805,17 @@
 	CKEDITOR.on( 'instanceDestroyed', function( evt )
 	{
+		// Remove dialog cover on last instance destroy.
+		if ( CKEDITOR.tools.isEmpty( CKEDITOR.instances ) )
+		{
+			var currentTopDialog;
+			while ( currentTopDialog = CKEDITOR.dialog._.currentTop )
+				currentTopDialog.hide();
+			removeCovers();
+		}
+
 		var dialogs = evt.editor._.storedDialogs;
 		for ( var name in dialogs )
 			dialogs[ name ].destroy();
 
-		// Remove dialog cover on last instance destroy.
-		if ( CKEDITOR.tools.isEmpty( CKEDITOR.instances ) );
-			coverElement.remove();
 	});
 
Index: CKEditor/branches/versions/3.3.x/_source/plugins/enterkey/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/enterkey/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/enterkey/plugin.js	(revision 5488)
@@ -33,5 +33,5 @@
 						block = path.block;
 
-				if ( block.is( 'li' ) || block.getParent().is( 'li' ) )
+				if ( block && ( block.is( 'li' ) || block.getParent().is( 'li' ) ) )
 				{
 					editor.execCommand( 'outdent' );
Index: CKEditor/branches/versions/3.3.x/_source/plugins/link/dialogs/link.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/link/dialogs/link.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/link/dialogs/link.js	(revision 5488)
@@ -412,11 +412,11 @@
 										label : editor.lang.common.protocol,
 										'default' : 'http://',
-										style : 'width : 100%;',
 										items :
 										[
-											[ 'http://' ],
-											[ 'https://' ],
-											[ 'ftp://' ],
-											[ 'news://' ],
+											// Force 'ltr' for protocol names in BIDI. (#5433) 
+											[ 'http://\u200E', 'http://' ],
+											[ 'https://\u200E', 'https://' ],
+											[ 'ftp://\u200E', 'ftp://' ],
+											[ 'news://\u200E', 'news://' ],
 											[ editor.lang.link.other , '' ]
 										],
Index: CKEditor/branches/versions/3.3.x/_source/plugins/list/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/list/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/list/plugin.js	(revision 5488)
@@ -235,4 +235,6 @@
 	}
 
+	var headerTagRegex = /^h[1-6]$/;
+
 	function createList( editor, groupObj, listsCreated )
 	{
@@ -286,6 +288,15 @@
 			var contentBlock = listContents.shift(),
 				listItem = doc.createElement( 'li' );
-			contentBlock.moveChildren( listItem );
-			contentBlock.remove();
+
+			// Preserve heading structure when converting to list item. (#5271)
+			if ( headerTagRegex.test( contentBlock.getName() ) )
+				contentBlock.appendTo( listItem );
+			else
+			{
+				contentBlock.copyAttributes( listItem );
+				contentBlock.moveChildren( listItem );
+				contentBlock.remove();
+			}
+
 			listItem.appendTo( listNode );
 
Index: CKEditor/branches/versions/3.3.x/_source/plugins/maximize/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/maximize/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/maximize/plugin.js	(revision 5488)
@@ -89,13 +89,6 @@
 		if ( editor.focusManager.hasFocus )
 		{
-			var focusGrabber = editor.container.append( CKEDITOR.dom.element.createFromHtml(
-				'<span tabindex="-1" style="position:absolute; left:-10000" role="presentation"></span>' ) );
-
-			focusGrabber.on( 'focus', function()
-				{
-					editor.focus();
-				} );
-			focusGrabber.focus();
-			focusGrabber.remove();
+			editor.toolbox.focus();
+			editor.focus();
 		}
 	}
Index: CKEditor/branches/versions/3.3.x/_source/plugins/pagebreak/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/pagebreak/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/pagebreak/plugin.js	(revision 5488)
@@ -85,4 +85,6 @@
 		var ranges = editor.getSelection().getRanges();
 
+		editor.fire( 'saveSnapshot' );
+
 		for ( var range, i = 0 ; i < ranges.length ; i++ )
 		{
@@ -100,4 +102,6 @@
 			}
 		}
+
+		editor.fire( 'saveSnapshot' );
 	}
 };
Index: CKEditor/branches/versions/3.3.x/_source/plugins/pastetext/dialogs/pastetext.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/pastetext/dialogs/pastetext.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/pastetext/dialogs/pastetext.js	(revision 5488)
@@ -1,3 +1,3 @@
-﻿/*
+/*
 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.html or http://ckeditor.com/license
@@ -53,4 +53,5 @@
 										'height:170px;' +
 										'resize: none;' +
+										'dir=' + editor.config.contentsLangDirection + ';' +
 										'border:1px solid black;' +
 										'background-color:white">' +
Index: CKEditor/branches/versions/3.3.x/_source/plugins/removeformat/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/removeformat/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/removeformat/plugin.js	(revision 5488)
@@ -16,4 +16,6 @@
 				command : 'removeFormat'
 			});
+
+		editor._.removeFormat = { filters: [] };
 	}
 });
@@ -33,4 +35,5 @@
 					( editor._.removeAttributes = editor.config.removeFormatAttributes.split( ',' ) );
 
+				var filter = CKEDITOR.plugins.removeformat.filter;
 				var ranges = editor.getSelection().getRanges();
 
@@ -71,5 +74,5 @@
 
 							// If this element can be removed (even partially).
-							if ( tagsRegex.test( pathElement.getName() ) )
+							if ( tagsRegex.test( pathElement.getName() ) && filter( editor, pathElement ) )
 								node.breakParent( pathElement );
 						}
@@ -93,5 +96,7 @@
 
 						// This node must not be a fake element.
-						if ( !( currentNode.getName() == 'img' && currentNode.getAttribute( '_cke_realelement' ) ) )
+						if ( !( currentNode.getName() == 'img'
+							&& currentNode.getAttribute( '_cke_realelement' ) )
+							&& filter( editor, currentNode ) )
 						{
 							// Remove elements nodes that match with this style rules.
@@ -111,5 +116,40 @@
 			}
 		}
+	},
+
+	/**
+	 * Perform the remove format filters on the passed element.
+	 * @param {CKEDITOR.editor} editor
+	 * @param {CKEDITOR.dom.element} element
+	 */
+	filter : function ( editor, element )
+	{
+		var filters = editor._.removeFormat.filters;
+		for ( var i = 0; i < filters.length; i++ )
+		{
+			if ( filters[ i ]( element ) === false )
+				return false;
+		}
+		return true;
 	}
+};
+
+/**
+ * Add to a collection of functions to decide whether a specific
+ * element should be considered as formatting element and thus
+ * could be removed during <b>removeFormat</b> command,
+ * Note: Only available with the existence of 'removeformat' plugin.
+ * @since 3.3
+ * @param {Function} func The function to be called, which will be passed a {CKEDITOR.dom.element} element to test.
+ * @example
+ *  // Don't remove empty span
+ *  editor.addRemoveFormatFilter.push( function( element )
+ *		{
+ *			return !( element.is( 'span' ) && CKEDITOR.tools.isEmpty( element.getAttributes() ) );
+ *		});
+ */
+CKEDITOR.editor.prototype.addRemoveFormatFilter = function( func )
+{
+	this._.removeFormat.filters.push( func );
 };
 
Index: CKEditor/branches/versions/3.3.x/_source/plugins/resize/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/resize/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/resize/plugin.js	(revision 5488)
@@ -12,16 +12,28 @@
 		if ( config.resize_enabled )
 		{
-			var container = null;
-			var origin, startSize;
+			var container = null,
+				origin,
+				startSize,
+				resizeHorizontal = ( config.resize_dir == 'both' || config.resize_dir == 'horizontal' ) &&
+					( config.resize_minWidth != config.resize_maxWidth ),
+				resizeVertical = ( config.resize_dir == 'both' || config.resize_dir == 'vertical' ) &&
+					( config.resize_minHeight != config.resize_maxHeight );
 
 			function dragHandler( evt )
 			{
-				var dx = evt.data.$.screenX - origin.x;
-				var dy = evt.data.$.screenY - origin.y;
-				var internalWidth = startSize.width + dx * ( editor.lang.dir == 'rtl' ? -1 : 1 );
-				var internalHeight = startSize.height + dy;
+				var dx = evt.data.$.screenX - origin.x,
+					dy = evt.data.$.screenY - origin.y,
+					width = startSize.width,
+					height = startSize.height,
+					internalWidth = width + dx * ( editor.lang.dir == 'rtl' ? -1 : 1 ),
+					internalHeight = height + dy;
 
-				editor.resize( Math.max( config.resize_minWidth, Math.min( internalWidth, config.resize_maxWidth ) ),
-						Math.max( config.resize_minHeight, Math.min( internalHeight, config.resize_maxHeight ) ) );
+				if ( resizeHorizontal )
+					width =  Math.max( config.resize_minWidth, Math.min( internalWidth, config.resize_maxWidth ) );
+
+				if ( resizeVertical )
+					height =  Math.max( config.resize_minHeight, Math.min( internalHeight, config.resize_maxHeight ) );
+
+				editor.resize( width, height );
 			}
 
@@ -62,5 +74,11 @@
 					if ( event.data.space == 'bottom' )
 					{
-						event.data.html += '<div class="cke_resizer"' +
+						var direction = '';
+						if ( resizeHorizontal && !resizeVertical)
+							direction = ' cke_resizer_horizontal';
+						if ( !resizeHorizontal && resizeVertical)
+							direction = ' cke_resizer_vertical';
+
+						event.data.html += '<div class="cke_resizer' + direction + '"' +
 							' title="' + CKEDITOR.tools.htmlEncode( editor.lang.resize ) + '"' +
 							' onmousedown="CKEDITOR.tools.callFunction(' + mouseDownFn + ', event)"' +
@@ -109,5 +127,5 @@
 
 /**
- * Whether to enable the resizing feature. If disabed the resize handler will not be visible.
+ * Whether to enable the resizing feature. If disabled the resize handler will not be visible.
  * @type Boolean
  * @default true
@@ -116,2 +134,13 @@
  */
 CKEDITOR.config.resize_enabled = true;
+
+/**
+ * The directions where resizing is enabled. It can be 'both', 'vertical' or 'horizontal'
+ * @type String
+ * @default 'both'
+ * @since 3.3
+ * @example
+ * config.resize_dir = 'vertical';
+ */
+
+CKEDITOR.config.resize_dir = 'both';
Index: CKEditor/branches/versions/3.3.x/_source/plugins/scayt/dialogs/options.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/scayt/dialogs/options.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/scayt/dialogs/options.js	(revision 5488)
@@ -244,7 +244,7 @@
 		}
 
-		var about = '<p>' + captions[ 'about_throwt_image' ] + '</p>'+
-					'<p>' + captions[ 'version' ]  + dialog.data.scayt.version.toString() + '</p>' +
-					'<p>' + captions[ 'about_throwt_copy' ] + '</p>';
+		var about = '<p><img src="' + scayt.getAboutInfo().logoURL + '" /></p>' +
+				'<p>' + captions[ 'version' ] + scayt.getAboutInfo().version.toString() + '</p>' +
+				'<p>' + captions[ 'about_throwt_copy' ] + '</p>';
 
 		doc.getById( 'scayt_about' ).setHtml( about );
Index: CKEditor/branches/versions/3.3.x/_source/plugins/scayt/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/scayt/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/scayt/plugin.js	(revision 5488)
@@ -47,4 +47,12 @@
 			oParams.userDictionaryName = editor.config.scayt_userDictionaryName || '';
 			oParams.sLang = editor.config.scayt_sLang || 'en_US';
+			
+			// Introduce SCAYT onLoad callback. (#5632)
+			oParams.onLoad = function()
+				{
+					// Draw down word marker to avoid being covered by background-color style.(#5466)
+					if ( !( CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) )
+						this.addStyle( this.selectorCss(), 'padding-bottom: 2px !important;' );
+				};
 
 			oParams.onBeforeChange = function()
@@ -53,5 +61,5 @@
 					setTimeout( function(){ editor.resetDirty(); } );
 			};
-
+			
 			var scayt_custom_params = window.scayt_custom_params;
 			if ( typeof scayt_custom_params == 'object')
@@ -268,27 +276,32 @@
 			var scaytConfigBaseUrl =  plugin.parseUrl( scaytUrl ).path +  '/';
 
-			CKEDITOR._djScaytConfig =
-			{
-				baseUrl: scaytConfigBaseUrl,
-				addOnLoad:
-				[
-					function()
-					{
-						CKEDITOR.fireOnce( 'scaytReady' );
-					}
-				],
-				isDebug: false
-			};
-			// Append javascript code.
-			CKEDITOR.document.getHead().append(
-				CKEDITOR.document.createElement( 'script',
-					{
-						attributes :
-							{
-								type : 'text/javascript',
-								src : scaytUrl
-							}
-					})
-			);
+			if( window.scayt == undefined )
+			{
+				CKEDITOR._djScaytConfig =
+				{
+					baseUrl: scaytConfigBaseUrl,
+					addOnLoad:
+					[
+						function()
+						{
+							CKEDITOR.fireOnce( 'scaytReady' );
+						}
+					],
+					isDebug: false
+				};
+				// Append javascript code.
+				CKEDITOR.document.getHead().append(
+					CKEDITOR.document.createElement( 'script',
+						{
+							attributes :
+								{
+									type : 'text/javascript',
+									src : scaytUrl
+								}
+						})
+				);
+			}
+			else
+				CKEDITOR.fireOnce( 'scaytReady' );
 
 			return null;
@@ -637,14 +650,16 @@
 		afterInit : function( editor )
 		{
-			// Prevent word marker line from displaying in elements path. (#3570)
-			var elementsPathFilters;
+			// Prevent word marker line from displaying in elements path and been removed when cleaning format. (#3570) (#4125)
+			var elementsPathFilters,
+					scaytFilter = function( element )
+					{
+						if ( element.hasAttribute( 'scaytid' ) )
+							return false;
+					};
+
 			if ( editor._.elementsPath && ( elementsPathFilters = editor._.elementsPath.filters ) )
-			{
-				elementsPathFilters.push( function( element )
-				{
-					if ( element.hasAttribute( 'scaytid' ) )
-						return false;
-				} );
-			}
+				elementsPathFilters.push( scaytFilter );
+
+			editor.addRemoveFormatFilter && editor.addRemoveFormatFilter( scaytFilter );
 
 		}
Index: CKEditor/branches/versions/3.3.x/_source/plugins/selection/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/selection/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/selection/plugin.js	(revision 5488)
@@ -210,5 +210,6 @@
 							{
 								var doc = editor.document,
-									sel = doc && doc.$.selection;
+									sel = editor.getSelection(),
+									nativeSel = sel && sel.getNative();
 
 								// There is a very specific case, when clicking
@@ -220,5 +221,5 @@
 								// such situation we have to test the range, to
 								// be sure it's valid.
-								if ( testIt && sel && sel.type == 'None' )
+								if ( testIt && nativeSel && nativeSel.type == 'None' )
 								{
 									// The "InsertImage" command can be used to
@@ -233,5 +234,5 @@
 								}
 
-								savedRange = sel && sel.createRange();
+								savedRange = nativeSel && sel.getRanges()[ 0 ];
 
 								checkSelectionChangeTimeout.call( editor );
@@ -1010,4 +1011,5 @@
 var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true );
 var fillerTextRegex = /\ufeff|\u00a0/;
+var nonCells = { table:1,tbody:1,tr:1 };
 
 CKEDITOR.dom.range.prototype.select =
@@ -1019,4 +1021,12 @@
 			var isStartMarkerAlone;
 			var dummySpan;
+
+			// IE doesn't support selecting the entire table row/cell, move the selection into cells, e.g.
+			// <table><tbody><tr>[<td>cell</b></td>... => <table><tbody><tr><td>[cell</td>...
+			if ( this.startContainer.type == CKEDITOR.NODE_ELEMENT && this.startContainer.getName() in nonCells
+				|| this.endContainer.type == CKEDITOR.NODE_ELEMENT && this.endContainer.getName() in nonCells )
+			{
+				this.shrink( CKEDITOR.NODE_ELEMENT, true );
+			}
 
 			var bookmark = this.createBookmark();
Index: CKEditor/branches/versions/3.3.x/_source/plugins/styles/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/styles/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/styles/plugin.js	(revision 5488)
@@ -380,37 +380,7 @@
 		// Get the first node to be processed and the last, which concludes the
 		// processing.
-		var boundaryNodes = range.getBoundaryNodes();
-		var firstNode = boundaryNodes.startNode;
-		var lastNode = boundaryNodes.endNode.getNextSourceNode( true );
-
-		// Probably the document end is reached, we need a marker node.
-		if ( !lastNode )
-		{
-				var marker;
-				lastNode = marker = document.createText( '' );
-				lastNode.insertAfter( range.endContainer );
-		}
-		// The detection algorithm below skips the contents inside bookmark nodes, so
-		// we'll need to make sure lastNode isn't the &nbsp; inside a bookmark node.
-		var lastParent = lastNode.getParent();
-		if ( lastParent && lastParent.getAttribute( '_fck_bookmark' ) )
-			lastNode = lastParent;
-
-		if ( lastNode.equals( firstNode ) )
-		{
-			// If the last node is the same as the the first one, we must move
-			// it to the next one, otherwise the first one will not be
-			// processed.
-			lastNode = lastNode.getNextSourceNode( true );
-
-			// It may happen that there are no more nodes after it (the end of
-			// the document), so we must add something there to make our code
-			// simpler.
-			if ( !lastNode )
-			{
-				lastNode = marker = document.createText( '' );
-				lastNode.insertAfter( firstNode );
-			}
-		}
+		var boundaryNodes = range.createBookmark(),
+			firstNode = boundaryNodes.startNode,
+			lastNode = boundaryNodes.endNode;
 
 		var currentNode = firstNode;
@@ -569,6 +539,6 @@
 		}
 
-		// Remove the temporary marking node.(#4111)
-		marker && marker.remove();
+		firstNode.remove();
+		lastNode.remove();
 		range.moveToBookmark( bookmark );
 		// Minimize the result range to exclude empty text nodes. (#5374)
Index: CKEditor/branches/versions/3.3.x/_source/plugins/tabletools/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/tabletools/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/tabletools/plugin.js	(revision 5488)
@@ -276,12 +276,12 @@
 
 		// scan row by row to get the target cell
-		var trs = table.$.getElementsByTagName( 'tr' );
-		for ( i = 0, length = trs.length; i < length ; i++ )
-		{
-			targetCell = trs[ i ].getElementsByTagName( 'td' )[ targetIndex ];
+		var rows = table.$.rows;
+		for ( i = 0, length = rows.length; i < length ; i++ )
+		{
+			targetCell = rows[ i ].cells[ targetIndex ];
 			if ( targetCell )
 				break;
 		}
-
+		
 		return targetCell ?  new CKEDITOR.dom.element( targetCell ) :  table.getPrevious();
 	}
Index: CKEditor/branches/versions/3.3.x/_source/plugins/undo/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/undo/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/undo/plugin.js	(revision 5488)
@@ -115,4 +115,25 @@
 				editor.fire( 'saveSnapshot' );
 			};
+
+			/**
+			 * Update the undo stacks with any subsequent DOM changes after this call.
+			 * @name CKEDITOR.editor#updateUndo
+			 * @example
+			 * function()
+			 * {
+			 * editor.fire( 'updateSnapshot' );
+			 * ...
+			 *  // Ask to include subsequent (in this call stack) DOM changes to be
+			 * // considered as part of the first snapshot.
+			 * 	editor.fire( 'updateSnapshot' );
+			 * 	editor.document.body.append(...);
+			 * ...
+			 * }
+			 */
+			editor.on( 'updateSnapshot', function()
+			{
+				if ( undoManager.currentImage && new Image( editor ).equals( undoManager.currentImage ) )
+					setTimeout( function () { undoManager.update(); }, 0 );
+			});
 		}
 	});
@@ -398,6 +419,5 @@
 			// content, since actualy content may differ from
 			// the original snapshot due to dom change. (#4622)
-			this.snapshots.splice( this.index, 1, ( this.currentImage =  new Image( this.editor ) ) );
-
+			this.update();
 			this.fireChange();
 		},
@@ -498,4 +518,12 @@
 
 			return false;
+		},
+
+		/**
+		 * Update the last snapshot of the undo stack with the current editor content.
+		 */
+		update : function()
+		{
+			this.snapshots.splice( this.index, 1, ( this.currentImage = new Image( this.editor ) ) );
 		}
 	};
Index: CKEditor/branches/versions/3.3.x/_source/plugins/wysiwygarea/plugin.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/plugins/wysiwygarea/plugin.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/plugins/wysiwygarea/plugin.js	(revision 5488)
@@ -171,4 +171,11 @@
 	}
 
+	function isBlankParagraph( block )
+	{
+		return block.getOuterHtml().match( emptyParagraphRegexp );
+	}
+
+	var isNotWhitespace = CKEDITOR.dom.walker.whitespaces( true );
+
 	/**
 	 *  Auto-fixing block-less content by wrapping paragraph (#3190), prevent
@@ -192,4 +199,5 @@
 			 && !path.block )
 		{
+			editor.fire( 'updateSnapshot' );
 			restoreDirty( editor );
 			CKEDITOR.env.ie && restoreSelection( selection );
@@ -205,7 +213,7 @@
 			}
 
-			// If the fixed block is blank and already followed by a exitable
-			// block, we should revert the fix. (#3684)
-			if ( fixedBlock.getOuterHtml().match( emptyParagraphRegexp ) )
+			// If the fixed block is actually blank and is already followed by an exitable blank
+			// block, we should revert the fix and move into the existed one. (#3684)
+			if ( isBlankParagraph( fixedBlock ) )
 			{
 				var previousElement = fixedBlock.getPrevious( isNotWhitespace ),
@@ -214,8 +222,10 @@
 				if ( previousElement && previousElement.getName
 					 && !( previousElement.getName() in nonExitableElementNames )
+					 && isBlankParagraph( previousElement )
 					 && range.moveToElementEditStart( previousElement )
 					 || nextElement && nextElement.getName
-					   && !( nextElement.getName() in nonExitableElementNames )
-					   && range.moveToElementEditStart( nextElement ) )
+						&& !( nextElement.getName() in nonExitableElementNames )
+						&& isBlankParagraph( nextElement )
+						&& range.moveToElementEditStart( nextElement ) )
 				{
 					fixedBlock.remove();
@@ -246,4 +256,5 @@
 		if ( walker.previous() )
 		{
+			editor.fire( 'updateSnapshot' );
 			restoreDirty( editor );
 			CKEDITOR.env.ie && restoreSelection( selection );
@@ -271,4 +282,5 @@
 			var frameLabel = editor.lang.editorTitle.replace( '%1', editor.name );
 
+			var contentDomReadyHandler;
 			editor.on( 'editingBlockReady', function()
 				{
@@ -320,5 +332,6 @@
 								var doc = iframe.getFrameDocument().$;
 
-								doc.open();
+								// Don't leave any history log in IE. (#5657)
+								doc.open( "text/html","replace" );
 								doc.write( data );
 								doc.close();
@@ -330,12 +343,13 @@
 					// The script that launches the bootstrap logic on 'domReady', so the document
 					// is fully editable even before the editing iframe is fully loaded (#4455).
+					contentDomReadyHandler = CKEDITOR.tools.addFunction( contentDomReady );
 					var activationScript =
 						'<script id="cke_actscrpt" type="text/javascript" cke_temp="1">' +
 							( isCustomDomain ? ( 'document.domain="' + document.domain + '";' ) : '' ) +
-							'parent.CKEDITOR._["contentDomReady' + editor.name + '"]( window );' +
+							'window.parent.CKEDITOR.tools.callFunction( ' + contentDomReadyHandler + ', window );' +
 						'</script>';
 
 					// Editing area bootstrap code.
-					var contentDomReady = function( domWindow )
+					function contentDomReady( domWindow )
 					{
 						if ( !frameLoaded )
@@ -351,6 +365,4 @@
 						var script = domDocument.getElementById( "cke_actscrpt" );
 						script.parentNode.removeChild( script );
-
-						delete CKEDITOR._[ 'contentDomReady' + editor.name ];
 
 						body.spellcheck = !editor.config.disableNativeSpellChecker;
@@ -700,5 +712,4 @@
 								data += activationScript;
 
-								CKEDITOR._[ 'contentDomReady' + editor.name ] = contentDomReady;
 
 								// The iframe is recreated on each call of setData, so we need to clear DOM objects
@@ -832,4 +843,5 @@
 				editor.on( 'destroy', function()
 				{
+					CKEDITOR.tools.removeFunction( contentDomReadyHandler );
 					focusGrabber.clearCustomData();
 				} );
@@ -849,22 +861,19 @@
 			else
 			{
-				body.setAttribute( 'onpageshow', body.getAttribute( 'onpageshow' )
-						+ ';event.persisted && CKEDITOR.tools.callFunction(' +
-						CKEDITOR.tools.addFunction( function()
-						{
-							var allInstances = CKEDITOR.instances,
-								editor,
-								doc;
-							for ( var i in allInstances )
-							{
-								editor = allInstances[ i ];
-								doc = editor.document;
-								if ( doc )
-								{
-									doc.$.designMode = 'off';
-									doc.$.designMode = 'on';
-								}
-							}
-						} ) + ')' );
+				var currentHandler = body.getAttribute( 'onpageshow' );
+				body.setAttribute( 'onpageshow', ( currentHandler ? currentHandler + ';' : '') +
+							'event.persisted && (function(){' +
+								'var allInstances = CKEDITOR.instances, editor, doc;' +
+								'for ( var i in allInstances )' +
+								'{' +
+								'	editor = allInstances[ i ];' +
+								'	doc = editor.document;' +
+								'	if ( doc )' +
+								'	{' +
+								'		doc.$.designMode = "off";' +
+								'		doc.$.designMode = "on";' +
+								'	}' +
+								'}' +
+						'})();' );
 			}
 		} )();
Index: CKEditor/branches/versions/3.3.x/_source/skins/kama/dialog.css
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/skins/kama/dialog.css	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/skins/kama/dialog.css	(revision 5488)
@@ -66,10 +66,4 @@
 {
 	margin-bottom: 10px;
-}
-
-.cke_skin_kama .cke_browser_ie.cke_rtl .cke_dialog_title
-{
-	position: static !important;
-	unicode-bidi: bidi-override;
 }
 
Index: CKEditor/branches/versions/3.3.x/_source/skins/kama/mainui.css
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/skins/kama/mainui.css	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/skins/kama/mainui.css	(revision 5488)
@@ -134,4 +134,16 @@
 }
 
+.cke_skin_kama .cke_resizer_horizontal,
+.cke_skin_kama .cke_rtl .cke_resizer_horizontal
+{
+	cursor: e-resize;
+}
+
+.cke_skin_kama .cke_resizer_vertical,
+.cke_skin_kama .cke_rtl .cke_resizer_vertical
+{
+	cursor: n-resize;
+}
+
 .cke_skin_kama .cke_maximized .cke_resizer
 {
Index: CKEditor/branches/versions/3.3.x/_source/skins/office2003/mainui.css
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/skins/office2003/mainui.css	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/skins/office2003/mainui.css	(revision 5488)
@@ -94,9 +94,4 @@
 }
 
-.cke_skin_office2003 .cke_maximized .cke_resizer
-{
-	display: none;
-}
-
 .cke_skin_office2003 .cke_rtl .cke_resizer
 {
@@ -105,4 +100,21 @@
 	background-position: 0 -1115px;
 	float: left;
+}
+
+.cke_skin_office2003 .cke_resizer_horizontal,
+.cke_skin_office2003 .cke_rtl .cke_resizer_horizontal
+{
+	cursor: e-resize;
+}
+
+.cke_skin_office2003 .cke_resizer_vertical,
+.cke_skin_office2003 .cke_rtl .cke_resizer_vertical
+{
+	cursor: n-resize;
+}
+
+.cke_skin_office2003 .cke_maximized .cke_resizer
+{
+	display: none;
 }
 
Index: CKEditor/branches/versions/3.3.x/_source/skins/v2/mainui.css
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/skins/v2/mainui.css	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/skins/v2/mainui.css	(revision 5488)
@@ -111,4 +111,16 @@
 }
 
+.cke_skin_v2 .cke_resizer_horizontal,
+.cke_skin_v2 .cke_rtl .cke_resizer_horizontal
+{
+	cursor: e-resize;
+}
+
+.cke_skin_v2 .cke_resizer_vertical,
+.cke_skin_v2 .cke_rtl .cke_resizer_vertical
+{
+	cursor: n-resize;
+}
+
 .cke_skin_v2 .cke_maximized .cke_resizer
 {
Index: CKEditor/branches/versions/3.3.x/_source/themes/default/theme.js
===================================================================
--- CKEditor/branches/versions/3.3.x/_source/themes/default/theme.js	(revision 5471)
+++ CKEditor/branches/versions/3.3.x/_source/themes/default/theme.js	(revision 5488)
@@ -127,7 +127,7 @@
 						'<span class="cke_wrapper cke_', editor.lang.dir, '" role="presentation">' +
 							'<table class="cke_editor" border="0" cellspacing="0" cellpadding="0" role="presentation"><tbody>' +
-								'<tr', topHtml		? '' : ' style="display:none"', '><td id="cke_top_'		, name, '" class="cke_top" role="presentation">'	, topHtml		, '</td></tr>' +
-								'<tr', contentsHtml	? '' : ' style="display:none"', '><td id="cke_contents_', name, '" class="cke_contents" style="height:', height, '" role="presentation">', contentsHtml, '</td></tr>' +
-								'<tr', bottomHtml	? '' : ' style="display:none"', '><td id="cke_bottom_'	, name, '" class="cke_bottom" role="presentation">'	, bottomHtml	, '</td></tr>' +
+								'<tr', topHtml		? '' : ' style="display:none"', ' role="presentation"><td id="cke_top_'		, name, '" class="cke_top" role="presentation">'	, topHtml		, '</td></tr>' +
+								'<tr', contentsHtml	? '' : ' style="display:none"', ' role="presentation"><td id="cke_contents_', name, '" class="cke_contents" style="height:', height, '" role="presentation">', contentsHtml, '</td></tr>' +
+								'<tr', bottomHtml	? '' : ' style="display:none"', ' role="presentation"><td id="cke_bottom_'	, name, '" class="cke_bottom" role="presentation">'	, bottomHtml	, '</td></tr>' +
 							'</tbody></table>' +
 							//Hide the container when loading skins, later restored by skin css.
Index: CKEditor/branches/versions/3.3.x/ckeditor.asp
===================================================================
--- CKEditor/branches/versions/3.3.x/ckeditor.asp	(revision 5488)
+++ CKEditor/branches/versions/3.3.x/ckeditor.asp	(revision 5488)
@@ -0,0 +1,958 @@
+﻿<%
+ '
+ ' Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+ ' For licensing, see LICENSE.html or http://ckeditor.com/license
+
+' Shared variable for all instances ("static")
+dim CKEDITOR_initComplete
+dim CKEDITOR_returnedEvents
+
+ ''
+ ' \brief CKEditor class that can be used to create editor
+ ' instances in ASP pages on server side.
+ ' @see http://ckeditor.com
+ '
+ ' Sample usage:
+ ' @code
+ ' editor = new CKEditor
+ ' editor.editor "editor1", "<p>Initial value.</p>", empty, empty
+ ' @endcode
+
+Class CKEditor
+
+	''
+	' The version of %CKEditor.
+	private version
+
+	''
+	' A constant string unique for each release of %CKEditor.
+	private mTimeStamp
+
+	''
+	' URL to the %CKEditor installation directory (absolute or relative to document root).
+	' If not set, CKEditor will try to guess it's path.
+	'
+	' Example usage:
+	' @code
+	' editor.basePath = "/ckeditor/"
+	' @endcode
+	Public basePath
+
+	''
+	' A boolean variable indicating whether CKEditor has been initialized.
+	' Set it to true only if you have already included
+	' &lt;script&gt; tag loading ckeditor.js in your website.
+	Public initialized
+
+	''
+	' Boolean variable indicating whether created code should be printed out or returned by a function.
+	'
+	' Example 1: get the code creating %CKEditor instance and print it on a page with the "echo" function.
+	' @code
+	' editor = new CKEditor
+	' editor.returnOutput = true
+	' code = editor.editor("editor1", "<p>Initial value.</p>", empty, empty)
+	' response.write "<p>Editor 1:</p>"
+	' response.write code
+	' @endcode
+	Public returnOutput
+
+	''
+	' A Dictionary with textarea attributes.
+	'
+	' When %CKEditor is created with the editor() method, a HTML &lt;textarea&gt; element is created,
+	' it will be displayed to anyone with JavaScript disabled or with incompatible browser.
+	public textareaAttributes
+
+	''
+	' A string indicating the creation date of %CKEditor.
+	' Do not change it unless you want to force browsers to not use previously cached version of %CKEditor.
+	public timestamp
+
+	''
+	' A dictionary that holds the instance configuration.
+	private oInstanceConfig
+
+	''
+	' A dictionary that holds the configuration for all the instances.
+	private oAllInstancesConfig
+
+	''
+	' A dictionary that holds event listeners for the instance.
+	private oInstanceEvents
+
+	''
+	' A dictionary that holds event listeners for all the instances.
+	private oAllInstancesEvents
+
+	''
+	' A Dictionary that holds global event listeners (CKEDITOR object)
+	private oGlobalEvents
+
+
+	Private Sub Class_Initialize()
+		version = "%VERSION%"
+		timeStamp = "%TIMESTAMP%"
+		mTimeStamp = "%TIMESTAMP%"
+
+		Set oInstanceConfig = CreateObject("Scripting.Dictionary")
+		Set oAllInstancesConfig = CreateObject("Scripting.Dictionary")
+
+		Set oInstanceEvents = CreateObject("Scripting.Dictionary")
+		Set oAllInstancesEvents = CreateObject("Scripting.Dictionary")
+		Set oGlobalEvents = CreateObject("Scripting.Dictionary")
+
+		Set textareaAttributes = CreateObject("Scripting.Dictionary")
+		textareaAttributes.Add "rows", 8
+		textareaAttributes.Add "cols", 60
+	End Sub
+
+	''
+	 ' Creates a %CKEditor instance.
+	 ' In incompatible browsers %CKEditor will downgrade to plain HTML &lt;textarea&gt; element.
+	 '
+	 ' @param name (string) Name of the %CKEditor instance (this will be also the "name" attribute of textarea element).
+	 ' @param value (string) Initial value.
+	 '
+	 ' Example usage:
+	 ' @code
+	 ' set editor = New CKEditor
+	 ' editor.editor "field1", "<p>Initial value.</p>"
+	 ' @endcode
+	 '
+	 ' Advanced example:
+	 ' @code
+	 ' set editor = new CKEditor
+	 ' set config = CreateObject("Scripting.Dictionary")
+	 ' config.Add "toolbar", Array( _
+	 '	Array( "Source", "-", "Bold", "Italic", "Underline", "Strike" ), _
+	 '	Array( "Image", "Link", "Unlink", "Anchor" ) _
+	 ' )
+	 ' set events = CreateObject("Scripting.Dictionary")
+	 ' events.Add "instanceReady", "function (evt) { alert('Loaded second editor: ' + evt.editor.name );}"
+
+	 ' editor.editor "field1", "<p>Initial value.</p>", config, events
+	 ' @endcode
+	 '
+	public function editor(name, value)
+		dim attr, out, js, customConfig, extraConfig
+		dim attribute
+
+		attr = ""
+
+		for each attribute in textareaAttributes
+			attr = attr & " " &  attribute & "=""" & replace( textareaAttributes( attribute ), """", "&quot" ) & """"
+		next
+
+		out = "<textarea name=""" & name & """" & attr & ">" & Server.HtmlEncode(value) & "</textarea>" & vbcrlf
+
+		if not(initialized) then
+			out = out & init()
+		end if
+
+		set customConfig = configSettings()
+		js = returnGlobalEvents()
+
+		extraConfig = (new JSON)( empty, customConfig, false )
+		if extraConfig<>"" then extraConfig = ", " & extraConfig
+		js = js & "CKEDITOR.replace('" & name & "'" & extraConfig & ");"
+
+		out = out & script(js)
+
+		if not(returnOutput) then
+			response.write out
+			out = ""
+		end if
+
+		editor = out
+
+		oInstanceConfig.RemoveAll
+		oInstanceEvents.RemoveAll
+	end function
+
+	''
+	 ' Replaces a &lt;textarea&gt; with a %CKEditor instance.
+	 '
+	 ' @param id (string) The id or name of textarea element.
+	 '
+	 ' Example 1: adding %CKEditor to &lt;textarea name="article"&gt;&lt;/textarea&gt; element:
+	 ' @code
+	 ' set editor = New CKEditor
+	 ' editor.replace "article"
+	 ' @endcode
+	 '
+	public function replaceInstance(id)
+		dim out, js, customConfig, extraConfig
+
+		out = ""
+		if not(initialized) then
+			out = out & init()
+		end if
+
+		set customConfig = configSettings()
+		js = returnGlobalEvents()
+
+		extraConfig = (new JSON)( empty, customConfig, false )
+		if extraConfig<>"" then extraConfig = ", " & extraConfig
+		js = js & "CKEDITOR.replace('" & id & "'" & extraConfig & ");"
+
+		out = out & script(js)
+
+		if not(returnOutput) then
+			response.write out
+			out = ""
+		end if
+
+		replaceInstance = out
+
+		oInstanceConfig.RemoveAll
+		oInstanceEvents.RemoveAll
+	end function
+
+	''
+	 ' Replace all &lt;textarea&gt; elements available in the document with editor instances.
+	 '
+	 ' @param className (string) If set, replace all textareas with class className in the page.
+	 '
+	 ' Example 1: replace all &lt;textarea&gt; elements in the page.
+	 ' @code
+	 ' editor = new CKEditor
+	 ' editor.replaceAll empty
+	 ' @endcode
+	 '
+	 ' Example 2: replace all &lt;textarea class="myClassName"&gt; elements in the page.
+	 ' @code
+	 ' editor = new CKEditor
+	 ' editor.replaceAll 'myClassName'
+	 ' @endcode
+	 '
+	function replaceAll(className)
+		dim out, js, customConfig
+
+		out = ""
+		if not(initialized) then
+			out = out & init()
+		end if
+
+		set customConfig = configSettings()
+		js = returnGlobalEvents()
+
+		if (customConfig.Count=0) then
+			if (isEmpty(className)) then
+				js = js & "CKEDITOR.replaceAll();"
+			else
+				js = js & "CKEDITOR.replaceAll('" & className & "');"
+			end if
+		else
+			js = js & "CKEDITOR.replaceAll( function(textarea, config) {\n"
+			if not(isEmpty(className)) then
+				js = js & "	var classRegex = new RegExp('(?:^| )' + '" & className & "' + '(?:$| )');\n"
+				js = js & "	if (!classRegex.test(textarea.className))\n"
+				js = js & "		return false;\n"
+			end if
+			js = js & "	CKEDITOR.tools.extend(config, " & (new JSON)( empty, customConfig, false ) & ", true);"
+			js = js & "} );"
+		end if
+
+		out = out & script(js)
+
+		if not(returnOutput) then
+			response.write out
+			out = ""
+		end if
+
+		replaceAll = out
+
+		oInstanceConfig.RemoveAll
+		oInstanceEvents.RemoveAll
+	end function
+
+
+	''
+	' A Dictionary that holds the %CKEditor configuration for all instances
+	' For the list of available options, see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
+	'
+	' Example usage:
+	' @code
+	' editor.config("height") = 400
+	' // Use @@ at the beggining of a string to ouput it without surrounding quotes.
+	' editor.config("width") = "@@screen.width * 0.8"
+	' @endcode
+	Public Property Let Config( configKey, configValue )
+		oAllInstancesConfig.Add configKey, configValue
+	End Property
+
+	''
+	' Configuration options for the next instance
+	'
+	Public Property Let instanceConfig( configKey, configValue )
+		oInstanceConfig.Add configKey, configValue
+	End Property
+
+	''
+	 ' Adds event listener.
+	 ' Events are fired by %CKEditor in various situations.
+	 '
+	 ' @param eventName (string) Event name.
+	 ' @param javascriptCode (string) Javascript anonymous function or function name.
+	 '
+	 ' Example usage:
+	 ' @code
+	 ' editor.addEventHandler  "instanceReady", "function (ev) { " & _
+	 '    " alert('Loaded: ' + ev.editor.name); " & _
+	 ' "}"
+	 ' @endcode
+	 '
+	public sub addEventHandler(eventName, javascriptCode)
+		if not(oAllInstancesEvents.Exists( eventName ) ) then
+			oAllInstancesEvents.Add eventName, Array()
+		end if
+
+		dim listeners, size
+		listeners = oAllInstancesEvents( eventName )
+		size = ubound(listeners) + 1
+		redim preserve listeners(size)
+		listeners(size) = javascriptCode
+
+		oAllInstancesEvents( eventName ) = listeners
+'		'' Avoid duplicates. fixme...
+'		if (!in_array($javascriptCode, $this->_events[$event])) {
+'			$this->_events[$event][] = $javascriptCode;
+'		}
+	end sub
+
+	''
+	 ' Clear registered event handlers.
+	 ' Note: this function will have no effect on already created editor instances.
+	 '
+	 ' @param eventName (string) Event name, if set to 'empty' all event handlers will be removed.
+	 '
+	public sub clearEventHandlers( eventName )
+		if not(isEmpty( eventName )) then
+			oAllInstancesEvents.Remove eventName
+		else
+			oAllInstancesEvents.RemoveAll
+		end if
+	end sub
+
+
+	''
+	 ' Adds event listener only for the next instance.
+	 ' Events are fired by %CKEditor in various situations.
+	 '
+	 ' @param eventName (string) Event name.
+	 ' @param javascriptCode (string) Javascript anonymous function or function name.
+	 '
+	 ' Example usage:
+	 ' @code
+	 ' editor.addInstanceEventHandler  "instanceReady", "function (ev) { " & _
+	 '    " alert('Loaded: ' + ev.editor.name); " & _
+	 ' "}"
+	 ' @endcode
+	 '
+	public sub addInstanceEventHandler(eventName, javascriptCode)
+		if not(oInstanceEvents.Exists( eventName ) ) then
+			oInstanceEvents.Add eventName, Array()
+		end if
+
+		dim listeners, size
+		listeners = oInstanceEvents( eventName )
+		size = ubound(listeners) + 1
+		redim preserve listeners(size)
+		listeners(size) = javascriptCode
+
+		oInstanceEvents( eventName ) = listeners
+'		'' Avoid duplicates. fixme...
+'		if (!in_array($javascriptCode, $this->_events[$event])) {
+'			$this->_events[$event][] = $javascriptCode;
+'		}
+	end sub
+
+	''
+	 ' Clear registered event handlers.
+	 ' Note: this function will have no effect on already created editor instances.
+	 '
+	 ' @param eventName (string) Event name, if set to 'empty' all event handlers will be removed.
+	 '
+	public sub clearInstanceEventHandlers( eventName )
+		if not(isEmpty( eventName )) then
+			oInstanceEvents.Remove eventName
+		else
+			oInstanceEvents.RemoveAll
+		end if
+	end sub
+
+	''
+	 ' Adds global event listener.
+	 '
+	 ' @param event (string) Event name.
+	 ' @param javascriptCode (string) Javascript anonymous function or function name.
+	 '
+	 ' Example usage:
+	 ' @code
+	 ' editor.addGlobalEventHandler "dialogDefinition", "function (ev) { " & _
+	 '   "  alert('Loading dialog: ' + ev.data.name); " & _
+	 ' "}"
+	 ' @endcode
+	 '
+	public sub addGlobalEventHandler( eventName, javascriptCode)
+		if not(oGlobalEvents.Exists( eventName ) ) then
+			oGlobalEvents.Add eventName, Array()
+		end if
+
+		dim listeners, size
+		listeners = oGlobalEvents( eventName )
+		size = ubound(listeners) + 1
+		redim preserve listeners(size)
+		listeners(size) = javascriptCode
+
+		oGlobalEvents( eventName ) = listeners
+
+'		// Avoid duplicates.
+'		if (!in_array($javascriptCode, $this->_globalEvents[$event])) {
+'			$this->_globalEvents[$event][] = $javascriptCode;
+'		}
+	end sub
+
+	''
+	 ' Clear registered global event handlers.
+	 ' Note: this function will have no effect if the event handler has been already printed/returned.
+	 '
+	 ' @param eventName (string) Event name, if set to 'empty' all event handlers will be removed .
+	 '
+	public sub clearGlobalEventHandlers( eventName )
+		if not(isEmpty( eventName )) then
+			oGlobalEvents.Remove eventName
+		else
+			oGlobalEvents.RemoveAll
+		end if
+	end sub
+
+	''
+	 ' Prints javascript code.
+	 '
+	 ' @param string js
+	 '
+	private function script(js)
+		script = "<script type=""text/javascript"">" & _
+			"//<![CDATA[" & vbcrlf & _
+			js & vbcrlf & _
+			"//]]>" & _
+			"</script>" & vbcrlf
+	end function
+
+	''
+	 ' Returns the configuration array (global and instance specific settings are merged into one array).
+	 '
+	 ' @param instanceConfig (Dictionary) The specific configurations to apply to editor instance.
+	 ' @param instanceEvents (Dictionary) Event listeners for editor instance.
+	 '
+	private function configSettings()
+		dim mergedConfig, mergedEvents
+		set mergedConfig = cloneDictionary(oAllInstancesConfig)
+		set mergedEvents = cloneDictionary(oAllInstancesEvents)
+
+		if not(isEmpty(oInstanceConfig)) then
+			set mergedConfig = mergeDictionary(mergedConfig, oInstanceConfig)
+		end if
+
+		if not(isEmpty(oInstanceEvents)) then
+			for each eventName in oInstanceEvents
+				code = oInstanceEvents( eventName )
+
+				if not(mergedEvents.Exists( eventName)) then
+					mergedEvents.Add eventName, code
+				else
+
+					dim listeners, size
+					listeners = mergedEvents( eventName )
+					size = ubound(listeners)
+					if isArray( code ) then
+						addedCount = ubound(code)
+						redim preserve listeners( size + addedCount + 1 )
+						for i = 0 to addedCount
+							listeners(size + i + 1) = code (i)
+						next
+					else
+						size = size + 1
+						redim preserve listeners(size)
+						listeners(size) = code
+					end if
+
+					mergedEvents( eventName ) = listeners
+				end if
+			next
+
+		end if
+
+		dim i, eventName, handlers, configON, ub, code
+
+		if mergedEvents.Count>0 then
+			if mergedConfig.Exists( "on" ) then
+				set configON = mergedConfig.items( "on" )
+			else
+				set configON = CreateObject("Scripting.Dictionary")
+				mergedConfig.Add "on", configOn
+			end if
+
+			for each eventName in mergedEvents
+				handlers = mergedEvents( eventName )
+				code = ""
+
+				if isArray(handlers) then
+					uB = ubound(handlers)
+					if (uB = 0) then
+						code = handlers(0)
+					else
+						code = "function (ev) {"
+						for i=0 to uB
+							code = code & "(" & handlers(i) & ")(ev);"
+						next
+						code = code & "}"
+					end if
+				else
+					code = handlers
+				end if
+				' Using @@ at the beggining to signal JSON that we don't want this quoted.
+				configON.Add eventName, "@@" & code
+			next
+
+'			set mergedConfig.Item("on") = configOn
+		end if
+
+		set configSettings = mergedConfig
+	end function
+
+	 ''
+		' Returns a copy of a scripting.dictionary object
+		'
+	private function cloneDictionary( base )
+		dim newOne, tmpKey
+
+		Set newOne = CreateObject("Scripting.Dictionary")
+		for each tmpKey in base
+			newOne.Add tmpKey , base( tmpKey )
+		next
+
+		set cloneDictionary = newOne
+	end function
+
+	 ''
+		' Combines two scripting.dictionary objects
+		' The base object isn't modified, and extra gets all the properties in base
+		'
+	private function mergeDictionary(base, extra)
+		dim newOne, tmpKey
+
+		for each tmpKey in base
+			if not(extra.Exists( tmpKey )) then
+				extra.Add tmpKey, base( tmpKey )
+			end if
+		next
+
+		set mergeDictionary = extra
+	end function
+
+	''
+	 ' Return global event handlers.
+	 '
+	private function returnGlobalEvents()
+		dim out, eventName, handlers
+		dim handlersForEvent, handler, code, i
+		out = ""
+
+		if (isempty(CKEDITOR_returnedEvents)) then
+			set CKEDITOR_returnedEvents = CreateObject("Scripting.Dictionary")
+		end if
+
+		for each eventName in oGlobalEvents
+			handlers = oGlobalEvents( eventName )
+
+			if not(CKEDITOR_returnedEvents.Exists(eventName)) then
+				CKEDITOR_returnedEvents.Add eventName, CreateObject("Scripting.Dictionary")
+			end if
+
+				set handlersForEvent = CKEDITOR_returnedEvents.Item( eventName )
+
+				' handlersForEvent is another dictionary
+				' and handlers is an array
+
+				for i = 0 to ubound(handlers)
+					code = handlers( i )
+
+					' Return only new events
+					if not(handlersForEvent.Exists( code )) then
+						if (out <> "") then out = out & vbcrlf
+						out = out & "CKEDITOR.on('" &  eventName & "', " & code & ");"
+						handlersForEvent.Add code, code
+					end if
+				next
+		next
+
+		returnGlobalEvents = out
+	end function
+
+	''
+	 ' Initializes CKEditor (executed only once).
+	 '
+	private function init()
+		dim out, args, path, extraCode, file
+		out = ""
+
+		if (CKEDITOR_initComplete) then
+			init = ""
+			exit function
+		end if
+
+		if (initialized) then
+			CKEDITOR_initComplete = true
+			init = ""
+			exit function
+		end if
+
+		args = ""
+		path = ckeditorPath()
+
+		if (timestamp <> "") and (timestamp <> "%" & "TIMESTAMP%") then
+			args = "?t=" & timestamp
+		end if
+
+		' Skip relative paths...
+		if (instr(path, "..") <> 0) then
+			out = out & script("window.CKEDITOR_BASEPATH='" &  path  & "';")
+		end if
+
+		out = out & "<scr" & "ipt type=""text/javascript"" src=""" & path & ckeditorFileName() & args & """></scr" & "ipt>" & vbcrlf
+
+		extraCode = ""
+		if (timestamp <> mTimeStamp) then
+			extraCode = extraCode & "CKEDITOR.timestamp = '" & timestamp & "';"
+		end if
+		if (extraCode <> "") then
+			out = out & script(extraCode)
+		end if
+
+		CKEDITOR_initComplete = true
+		initialized = true
+
+		init = out
+	end function
+
+	private function ckeditorFileName()
+		ckeditorFileName = "ckeditor.js"
+		' CKReleaser %REMOVE_START%
+		ckeditorFileName = "ckeditor_source.js"
+		' CKReleaser %REMOVE_END%
+	end function
+
+	''
+	 ' Return path to ckeditor.js.
+	 '
+	private function ckeditorPath()
+		if (basePath <> "") then
+			ckeditorPath = basePath
+		else
+			' In classic ASP we can't get the location of this included script
+			ckeditorPath = "/ckeditor/"
+		end if
+
+		' Try to check if that folder contains the CKEditor files:
+		' If it's a full URL avoid checking it as it might point to an external server.
+		if (instr(ckeditorPath, "://") <> 0) then exit function
+
+		dim filename, oFSO, exists
+		filename = server.mapPath(basePath & ckeditorFileName())
+		set oFSO = Server.CreateObject("Scripting.FileSystemObject")
+		exists = oFSO.FileExists(filename)
+		set oFSO = nothing
+
+		if not(exists) then
+			response.clear
+			response.write "<h1>CKEditor path validation failed</h1>"
+			response.write "<p>The path &quot;" & ckeditorPath & "&quot; doesn't include the CKEditor main file (" & ckeditorFileName() & ")</p>"
+			response.write "<p>Please, verify that you have set it correctly and/or adjust the 'basePath' property</p>"
+			response.write "<p>Checked for physical file: &quot;" & filename & "&quot;</p>"
+			response.end
+		end if
+	end function
+
+End Class
+
+
+
+' URL: http://www.webdevbros.net/2007/04/26/generate-json-from-asp-datatypes/
+'**************************************************************************************************************
+'' @CLASSTITLE:		JSON
+'' @CREATOR:		Michal Gabrukiewicz (gabru at grafix.at), Michael Rebec
+'' @CONTRIBUTORS:	- Cliff Pruitt (opensource at crayoncowboy.com)
+''					- Sylvain Lafontaine
+''					- Jef Housein
+''					- Jeremy Brown
+'' @CREATEDON:		2007-04-26 12:46
+'' @CDESCRIPTION:	Comes up with functionality for JSON (http://json.org) to use within ASP.
+''					Correct escaping of characters, generating JSON Grammer out of ASP datatypes and structures
+''					Some examples (all use the <em>toJSON()</em> method but as it is the class' default method it can be left out):
+''					<code>
+''					<%
+''					'simple number
+''					output = (new JSON)("myNum", 2, false)
+''					'generates {"myNum": 2}
+''
+''					'array with different datatypes
+''					output = (new JSON)("anArray", array(2, "x", null), true)
+''					'generates "anArray": [2, "x", null]
+''					'(note: the last parameter was true, thus no surrounding brackets in the result)
+''					% >
+''					</code>
+'' @REQUIRES:		-
+'' @OPTIONEXPLICIT:	yes
+'' @VERSION:		1.5.1
+
+'**************************************************************************************************************
+class JSON
+
+	'private members
+	private output, innerCall
+
+	'**********************************************************************************************************
+	'* constructor
+	'**********************************************************************************************************
+	public sub class_initialize()
+		newGeneration()
+	end sub
+
+	'******************************************************************************************
+	'' @SDESCRIPTION:	STATIC! takes a given string and makes it JSON valid
+	'' @DESCRIPTION:	all characters which needs to be escaped are beeing replaced by their
+	''					unicode representation according to the
+	''					RFC4627#2.5 - http://www.ietf.org/rfc/rfc4627.txt?number=4627
+	'' @PARAM:			val [string]: value which should be escaped
+	'' @RETURN:			[string] JSON valid string
+	'******************************************************************************************
+	public function escape(val)
+		dim cDoubleQuote, cRevSolidus, cSolidus
+		cDoubleQuote = &h22
+		cRevSolidus = &h5C
+		cSolidus = &h2F
+		dim i, currentDigit
+		for i = 1 to (len(val))
+			currentDigit = mid(val, i, 1)
+			if ascw(currentDigit) > &h00 and ascw(currentDigit) < &h1F then
+				currentDigit = escapequence(currentDigit)
+			elseif ascw(currentDigit) >= &hC280 and ascw(currentDigit) <= &hC2BF then
+				currentDigit = "\u00" + right(padLeft(hex(ascw(currentDigit) - &hC200), 2, 0), 2)
+			elseif ascw(currentDigit) >= &hC380 and ascw(currentDigit) <= &hC3BF then
+				currentDigit = "\u00" + right(padLeft(hex(ascw(currentDigit) - &hC2C0), 2, 0), 2)
+			else
+				select case ascw(currentDigit)
+					case cDoubleQuote: currentDigit = escapequence(currentDigit)
+					case cRevSolidus: currentDigit = escapequence(currentDigit)
+					case cSolidus: currentDigit = escapequence(currentDigit)
+				end select
+			end if
+			escape = escape & currentDigit
+		next
+	end function
+
+	'******************************************************************************************************************
+	'' @SDESCRIPTION:	generates a representation of a name value pair in JSON grammer
+	'' @DESCRIPTION:	It generates a name value pair which is represented as <em>{"name": value}</em> in JSON.
+	''					the generation is fully recursive. Thus the value can also be a complex datatype (array in dictionary, etc.) e.g.
+	''					<code>
+	''					<%
+	''					set j = new JSON
+	''					j.toJSON "n", array(RS, dict, false), false
+	''					j.toJSON "n", array(array(), 2, true), false
+	''					% >
+	''					</code>
+	'' @PARAM:			name [string]: name of the value (accessible with javascript afterwards). leave empty to get just the value
+	'' @PARAM:			val [variant], [int], [float], [array], [object], [dictionary]: value which needs
+	''					to be generated. Conversation of the data types is as follows:<br>
+	''					- <strong>ASP datatype -> JavaScript datatype</strong>
+	''					- NOTHING, NULL -> null
+	''					- INT, DOUBLE -> number
+	''					- STRING -> string
+	''					- BOOLEAN -> bool
+	''					- ARRAY -> array
+	''					- DICTIONARY -> Represents it as name value pairs. Each key is accessible as property afterwards. json will look like <code>"name": {"key1": "some value", "key2": "other value"}</code>
+	''					- <em>multidimensional array</em> -> Generates a 1-dimensional array (flat) with all values of the multidimensional array
+	''					- <em>request</em> object -> every property and collection (cookies, form, querystring, etc) of the asp request object is exposed as an item of a dictionary. Property names are <strong>lowercase</strong>. e.g. <em>servervariables</em>.
+	''					- OBJECT -> name of the type (if unknown type) or all its properties (if class implements <em>reflect()</em> method)
+	''					Implement a <strong>reflect()</strong> function if you want your custom classes to be recognized. The function must return
+	''					a dictionary where the key holds the property name and the value its value. Example of a reflect function within a User class which has firstname and lastname properties
+	''					<code>
+	''					<%
+	''					function reflect()
+	''					.	set reflect = server.createObject("scripting.dictionary")
+	''					.	reflect.add "firstname", firstname
+	''					.	reflect.add "lastname", lastname
+	''					end function
+	''					% >
+	''					</code>
+	''					Example of how to generate a JSON representation of the asp request object and access the <em>HTTP_HOST</em> server variable in JavaScript:
+	''					<code>
+	''					<script>alert(<%= (new JSON)(empty, request, false) % >.servervariables.HTTP_HOST);</script>
+	''					</code>
+	'' @PARAM:			nested [bool]: indicates if the name value pair is already nested within another? if yes then the <em>{}</em> are left out.
+	'' @RETURN:			[string] returns a JSON representation of the given name value pair
+	'******************************************************************************************************************
+	public default function toJSON(name, val, nested)
+		if not nested and not isEmpty(name) then write("{")
+		if not isEmpty(name) then write("""" & escape(name) & """: ")
+		generateValue(val)
+		if not nested and not isEmpty(name) then write("}")
+		toJSON = output
+
+		if innerCall = 0 then newGeneration()
+	end function
+
+	'******************************************************************************************************************
+	'* generate
+	'******************************************************************************************************************
+	private function generateValue(val)
+		if isNull(val) then
+			write("null")
+		elseif isArray(val) then
+			generateArray(val)
+		elseif isObject(val) then
+			dim tName : tName = typename(val)
+			if val is nothing then
+				write("null")
+			elseif tName = "Dictionary" or tName = "IRequestDictionary" then
+				generateDictionary(val)
+			elseif tName = "IRequest" then
+				set req = server.createObject("scripting.dictionary")
+				req.add "clientcertificate", val.ClientCertificate
+				req.add "cookies", val.cookies
+				req.add "form", val.form
+				req.add "querystring", val.queryString
+				req.add "servervariables", val.serverVariables
+				req.add "totalbytes", val.totalBytes
+				generateDictionary(req)
+			elseif tName = "IStringList" then
+				if val.count = 1 then
+					toJSON empty, val(1), true
+				else
+					generateArray(val)
+				end if
+			else
+				generateObject(val)
+			end if
+		else
+			'bool
+			dim varTyp
+			varTyp = varType(val)
+			if varTyp = 11 then
+				if val then write("true") else write("false")
+			'int, long, byte
+			elseif varTyp = 2 or varTyp = 3 or varTyp = 17 or varTyp = 19 then
+				write(cLng(val))
+			'single, double, currency
+			elseif varTyp = 4 or varTyp = 5 or varTyp = 6 or varTyp = 14 then
+				write(replace(cDbl(val), ",", "."))
+			else
+				' Using @@ at the beggining to signal JSON that we don't want this quoted.
+				if left(val, 2) = "@@" then
+					write( mid( val, 3 ) )
+				else
+					write("""" & escape(val & "") & """")
+				end if
+			end if
+		end if
+		generateValue = output
+	end function
+
+	'******************************************************************************************************************
+	'* generateArray
+	'******************************************************************************************************************
+	private sub generateArray(val)
+		dim item, i
+		write("[")
+		i = 0
+		'the for each allows us to support also multi dimensional arrays
+		for each item in val
+			if i > 0 then write(",")
+			generateValue(item)
+			i = i + 1
+		next
+		write("]")
+	end sub
+
+	'******************************************************************************************************************
+	'* generateDictionary
+	'******************************************************************************************************************
+	private sub generateDictionary(val)
+		innerCall = innerCall + 1
+		if val.count = 0 then
+			toJSON empty, null, true
+			exit sub
+		end if
+		dim key, i
+		write("{")
+		i = 0
+		for each key in val
+			if i > 0 then write(",")
+			toJSON key, val(key), true
+			i = i + 1
+		next
+		write("}")
+		innerCall = innerCall - 1
+	end sub
+
+	'******************************************************************************************************************
+	'* generateObject
+	'******************************************************************************************************************
+	private sub generateObject(val)
+		dim props
+		on error resume next
+		set props = val.reflect()
+		if err = 0 then
+			on error goto 0
+			innerCall = innerCall + 1
+			toJSON empty, props, true
+			innerCall = innerCall - 1
+		else
+			on error goto 0
+			write("""" & escape(typename(val)) & """")
+		end if
+	end sub
+
+	'******************************************************************************************************************
+	'* newGeneration
+	'******************************************************************************************************************
+	private sub newGeneration()
+		output = empty
+		innerCall = 0
+	end sub
+
+	'******************************************************************************************
+	'* JsonEscapeSquence
+	'******************************************************************************************
+	private function escapequence(digit)
+		escapequence = "\u00" + right(padLeft(hex(ascw(digit)), 2, 0), 2)
+	end function
+
+	'******************************************************************************************
+	'* padLeft
+	'******************************************************************************************
+	private function padLeft(value, totalLength, paddingChar)
+		padLeft = right(clone(paddingChar, totalLength) & value, totalLength)
+	end function
+
+	'******************************************************************************************
+	'* clone
+	'******************************************************************************************
+	private function clone(byVal str, n)
+		dim i
+		for i = 1 to n : clone = clone & str : next
+	end function
+
+	'******************************************************************************************
+	'* write
+	'******************************************************************************************
+	private sub write(val)
+		output = output & val
+	end sub
+
+end class
+%>
