src/crypto.c: possible fix for memory leak related
[citadel.git] / webcit / tiny_mce / tiny_mce_src.js
index 05017bd269b74664662b6abd4147818e1708522c..09fa85c8f460332000acc9dc6affe20b03c096a6 100644 (file)
@@ -1,7 +1,7 @@
 /**\r
  * $RCSfile: tiny_mce_src.js,v $\r
- * $Revision: 1.2 $\r
- * $Date: 2005/09/26 18:00:52 $\r
+ * $Revision: 1.281 $\r
+ * $Date: 2005/12/02 08:12:07 $\r
  *\r
  * @author Moxiecode\r
  * @copyright Copyright © 2004, Moxiecode Systems AB, All rights reserved.\r
@@ -9,8 +9,8 @@
 \r
 function TinyMCE() {\r
        this.majorVersion = "2";\r
-       this.minorVersion = "0RC3";\r
-       this.releaseDate = "2005-09-26";\r
+       this.minorVersion = "0";\r
+       this.releaseDate = "2005-12-01";\r
 \r
        this.instances = new Array();\r
        this.stickyClassesLookup = new Array();\r
@@ -21,14 +21,25 @@ function TinyMCE() {
        this.eventHandlers = new Array();\r
 \r
        // Browser check\r
+       var ua = navigator.userAgent;\r
        this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");\r
-       this.isMSIE5 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5') != -1);\r
-       this.isMSIE5_0 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1);\r
-       this.isGecko = navigator.userAgent.indexOf('Gecko') != -1;\r
-       this.isSafari = navigator.userAgent.indexOf('Safari') != -1;\r
-       this.isMac = navigator.userAgent.indexOf('Mac') != -1;\r
+       this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);\r
+       this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);\r
+       this.isGecko = ua.indexOf('Gecko') != -1;\r
+       this.isSafari = ua.indexOf('Safari') != -1;\r
+       this.isOpera = ua.indexOf('Opera') != -1;\r
+       this.isMac = ua.indexOf('Mac') != -1;\r
+       this.isNS7 = ua.indexOf('Netscape/7') != -1;\r
+       this.isNS71 = ua.indexOf('Netscape/7.1') != -1;\r
        this.dialogCounter = 0;\r
 \r
+       // Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those\r
+       if (this.isOpera) {\r
+               this.isMSIE = true;\r
+               this.isGecko = false;\r
+               this.isSafari =  false;\r
+       }\r
+\r
        // TinyMCE editor id instance counter\r
        this.idCounter = 0;\r
 };\r
@@ -51,7 +62,7 @@ TinyMCE.prototype.init = function(settings) {
                var elements = document.getElementsByTagName('script');\r
 \r
                for (var i=0; i<elements.length; i++) {\r
-                       if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip.php") != -1)) {\r
+                       if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip") != -1)) {\r
                                var src = elements[i].src;\r
 \r
                                tinyMCE.srcMode = (src.indexOf('_src') != -1) ? '_src' : '';\r
@@ -86,7 +97,7 @@ TinyMCE.prototype.init = function(settings) {
        this.defParam("textarea_trigger", "mce_editable");\r
        this.defParam("editor_selector", "");\r
        this.defParam("editor_deselector", "mceNoEditor");\r
-       this.defParam("valid_elements", "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/b[class|style],-em/i[class|style],-strike[class|style],-u[class|style],+p[style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border=0|alt|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],-td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[style|dir|class|align],-h2[style|dir|class|align],-h3[style|dir|class|align],-h4[style|dir|class|align],-h5[style|dir|class|align],-h6[style|dir|class|align],hr[class|style]");\r
+       this.defParam("valid_elements", "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/b[class|style],-em/i[class|style],-strike[class|style],-u[class|style],+p[style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border=0|alt|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],-td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[style|dir|class|align],-h2[style|dir|class|align],-h3[style|dir|class|align],-h4[style|dir|class|align],-h5[style|dir|class|align],-h6[style|dir|class|align],hr[class|style],font[face|size|style|id|class|dir|color]");\r
        this.defParam("extended_valid_elements", "");\r
        this.defParam("invalid_elements", "");\r
        this.defParam("encoding", "");\r
@@ -127,10 +138,20 @@ TinyMCE.prototype.init = function(settings) {
        this.defParam("remove_linebreaks", true);\r
        this.defParam("button_tile_map", false);\r
        this.defParam("submit_patch", true);\r
-       this.defParam("browsers", "msie,safari,gecko");\r
+       this.defParam("browsers", "msie,safari,gecko,opera");\r
        this.defParam("dialog_type", "window");\r
-       this.defParam("convert_fonts_to_styles", true);\r
        this.defParam("accessibility_warnings", true);\r
+       this.defParam("merge_styles_invalid_parents", "");\r
+       this.defParam("force_hex_style_colors", true);\r
+       this.defParam("trim_span_elements", true);\r
+       this.defParam("convert_fonts_to_spans", false);\r
+       this.defParam("doctype", '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');\r
+       this.defParam("font_size_classes", '');\r
+       this.defParam("font_size_style_values", 'xx-small,x-small,small,medium,large,x-large,xx-large');\r
+       this.defParam("event_elements", 'a,img');\r
+       this.defParam("convert_urls", true);\r
+       this.defParam("table_inline_editing", false);\r
+       this.defParam("object_resizing", true);\r
 \r
        // Browser check IE\r
        if (this.isMSIE && this.settings['browsers'].indexOf('msie') == -1)\r
@@ -144,16 +165,36 @@ TinyMCE.prototype.init = function(settings) {
        if (this.isSafari && this.settings['browsers'].indexOf('safari') == -1)\r
                return;\r
 \r
-       // Setup baseHREF\r
+       // Browser check Opera\r
+       if (this.isOpera && this.settings['browsers'].indexOf('opera') == -1)\r
+               return;\r
+\r
+       // If not super absolute make it so\r
        var baseHREF = tinyMCE.settings['document_base_url'];\r
+       var h = document.location.href;\r
+       var p = h.indexOf('://');\r
+       if (p > 0 && document.location.protocol != "file:") {\r
+               p = h.indexOf('/', p + 3);\r
+               h = h.substring(0, p);\r
+\r
+               if (baseHREF.indexOf('://') == -1)\r
+                       baseHREF = h + baseHREF;\r
+\r
+               tinyMCE.settings['document_base_url'] = baseHREF;\r
+               tinyMCE.settings['document_base_prefix'] = h;\r
+       }\r
+\r
+       // Trim away query part\r
        if (baseHREF.indexOf('?') != -1)\r
                baseHREF = baseHREF.substring(0, baseHREF.indexOf('?'));\r
+\r
        this.settings['base_href'] = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/";\r
 \r
        theme = this.settings['theme'];\r
-\r
-       this.blockRegExp = new RegExp("^(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td)$", "i");\r
+       this.blockRegExp = new RegExp("^(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|blockquote|center|dl|dir|fieldset|form|noscript|noframes|menu|isindex)$", "i");\r
        this.posKeyCodes = new Array(13,45,36,35,33,34,37,38,39,40);\r
+       this.uniqueURL = 'http://tinymce.moxiecode.cp/mce_temp_url'; // Make unique URL non real URL\r
+       this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>';\r
 \r
        // Theme url\r
        this.settings['theme_href'] = tinyMCE.baseURL + "/themes/" + theme;\r
@@ -213,7 +254,7 @@ TinyMCE.prototype.init = function(settings) {
        if (this.configs.length == 0) {\r
                // Is Safari enabled\r
                if (this.isSafari && this.getParam('safari_warning', true))\r
-                       alert("Safari support is very limited and should be considered experimental.\nSo there is no need to even submit bugreports on this early version.");\r
+                       alert("Safari support is very limited and should be considered experimental.\nSo there is no need to even submit bugreports on this early version.\nYou can disable this message by setting: safari_warning option to false");\r
 \r
                tinyMCE.addEvent(window, "load", TinyMCE.prototype.onLoad);\r
 \r
@@ -232,13 +273,19 @@ TinyMCE.prototype.init = function(settings) {
        this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings['language'] +  '.js');\r
        this.loadCSS(this.settings['editor_css']);\r
 \r
-       // Add theme plugins\r
+       // Add plugins\r
        var themePlugins = tinyMCE.getParam('plugins', '', true, ',');\r
        if (this.settings['plugins'] != '') {\r
                for (var i=0; i<themePlugins.length; i++)\r
                        this.loadScript(tinyMCE.baseURL + '/plugins/' + themePlugins[i] + '/editor_plugin' + tinyMCE.srcMode + '.js');\r
        }\r
 \r
+       // Setup entities\r
+       settings['cleanup_entities'] = new Array();\r
+       var entities = tinyMCE.getParam('entities', '', true, ',');\r
+       for (var i=0; i<entities.length; i+=2)\r
+               settings['cleanup_entities']['c' + entities[i]] = entities[i+1];\r
+\r
        // Save away this config\r
        settings['index'] = this.configs.length;\r
        this.configs[this.configs.length] = settings;\r
@@ -270,17 +317,16 @@ TinyMCE.prototype.importCSS = function(doc, css_file) {
        if (css_file == '')\r
                return;\r
 \r
-       if (tinyMCE.isMSIE)\r
-               var styleSheet = doc.createStyleSheet(css_file);\r
-       else {\r
+       if (typeof(doc.createStyleSheet) == "undefined") {\r
                var elm = doc.createElement("link");\r
 \r
                elm.rel = "stylesheet";\r
                elm.href = css_file;\r
 \r
-               if (headArr = doc.getElementsByTagName("head"))\r
+               if ((headArr = doc.getElementsByTagName("head")) != null && headArr.length > 0)\r
                        headArr[0].appendChild(elm);\r
-       }\r
+       } else\r
+               var styleSheet = doc.createStyleSheet(css_file);\r
 };\r
 \r
 TinyMCE.prototype.confirmAdd = function(e, settings) {\r
@@ -300,7 +346,7 @@ TinyMCE.prototype.updateContent = function(form_element_name) {
        var formElement = document.getElementById(form_element_name);\r
        for (var n in tinyMCE.instances) {\r
                var inst = tinyMCE.instances[n];\r
-               if (typeof(inst) == 'function')\r
+               if (!tinyMCE.isInstance(inst))\r
                        continue;\r
 \r
                inst.switchSettings();\r
@@ -330,7 +376,7 @@ TinyMCE.prototype.triggerSave = function(skip_cleanup, skip_callback) {
        // Cleanup and set all form fields\r
        for (var n in tinyMCE.instances) {\r
                var inst = tinyMCE.instances[n];\r
-               if (typeof(inst) == 'function')\r
+               if (!tinyMCE.isInstance(inst))\r
                        continue;\r
 \r
                inst.switchSettings();\r
@@ -350,7 +396,7 @@ TinyMCE.prototype.triggerSave = function(skip_cleanup, skip_callback) {
                // Remove visual aids when cleanup is disabled\r
                if (inst.settings['cleanup'] == false) {\r
                        tinyMCE.handleVisualAid(inst.getBody(), true, false, inst);\r
-                       tinyMCE._setEventsEnabled(inst.getBody(), false);\r
+                       tinyMCE._setEventsEnabled(inst.getBody(), true);\r
                }\r
 \r
                tinyMCE._customCleanup(inst, "submit_content_dom", inst.contentWindow.document.body);\r
@@ -384,21 +430,24 @@ TinyMCE.prototype._setEventsEnabled = function(node, state) {
                                'onmousedown','onmouseup','onmouseover','onmousemove',\r
                                'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup');\r
 \r
-       var elms = node.getElementsByTagName("a");\r
-       for (var i=0; i<elms.length; i++) {\r
-               var event = "";\r
+       var evs = tinyMCE.settings['event_elements'].split(',');\r
+    for (var y=0; y<evs.length; y++){\r
+               var elms = node.getElementsByTagName(evs[y]);\r
+               for (var i=0; i<elms.length; i++) {\r
+                       var event = "";\r
 \r
-               for (var x=0; x<events.length; x++) {\r
-                       if ((event = tinyMCE.getAttrib(elms[i], events[x])) != '') {\r
-                               event = tinyMCE.cleanupEventStr("" + event);\r
+                       for (var x=0; x<events.length; x++) {\r
+                               if ((event = tinyMCE.getAttrib(elms[i], events[x])) != '') {\r
+                                       event = tinyMCE.cleanupEventStr("" + event);\r
 \r
-                               if (state)\r
-                                       event = "return true;" + event;\r
-                               else\r
-                                       event = event.replace(/^return true;/gi, '');\r
+                                       if (!state)\r
+                                               event = "return true;" + event;\r
+                                       else\r
+                                               event = event.replace(/^return true;/gi, '');\r
 \r
-                               elms[i].removeAttribute(events[x]);\r
-                               elms[i].setAttribute(events[x], event);\r
+                                       elms[i].removeAttribute(events[x]);\r
+                                       elms[i].setAttribute(events[x], event);\r
+                               }\r
                        }\r
                }\r
        }\r
@@ -409,16 +458,14 @@ TinyMCE.prototype.resetForm = function(form_index) {
 \r
        for (var n in tinyMCE.instances) {\r
                var inst = tinyMCE.instances[n];\r
-               if (typeof(inst) == 'function')\r
+               if (!tinyMCE.isInstance(inst))\r
                        continue;\r
 \r
                inst.switchSettings();\r
 \r
                for (var i=0; i<formObj.elements.length; i++) {\r
-                       if (inst.formTargetElementId == formObj.elements[i].name) {\r
-                               inst.getBody().innerHTML = formObj.elements[i].value;\r
-                               return;\r
-                       }\r
+                       if (inst.formTargetElementId == formObj.elements[i].name)\r
+                               inst.getBody().innerHTML = inst.startContent;\r
                }\r
        }\r
 };\r
@@ -438,6 +485,10 @@ TinyMCE.prototype.execInstanceCommand = function(editor_id, command, user_interf
                this.selectedElement = inst.getFocusElement();\r
                this.selectedInstance = inst;\r
                tinyMCE.execCommand(command, user_interface, value);\r
+\r
+               // Cancel event so it doesn't call onbeforeonunlaod\r
+               if (tinyMCE.isMSIE && window.event != null)\r
+                       tinyMCE.cancelEvent(window.event);\r
        }\r
 };\r
 \r
@@ -488,7 +539,7 @@ TinyMCE.prototype.execCommand = function(command, user_interface, value) {
                        // Resets the designmode state of the editors in Gecko\r
                        if (!tinyMCE.isMSIE) {\r
                                for (var n in tinyMCE.instances) {\r
-                                       if (typeof(tinyMCE.instances[n]) == 'function')\r
+                                       if (!tinyMCE.isInstance(tinyMCE.instances[n]))\r
                                                continue;\r
 \r
                                        try {\r
@@ -502,9 +553,9 @@ TinyMCE.prototype.execCommand = function(command, user_interface, value) {
                        return;\r
        }\r
 \r
-       if (this.selectedInstance)\r
+       if (this.selectedInstance) {\r
                this.selectedInstance.execCommand(command, user_interface, value);\r
-       else if (tinyMCE.settings['focus_alert'])\r
+       else if (tinyMCE.settings['focus_alert'])\r
                alert(tinyMCELang['lang_focus_alert']);\r
 };\r
 \r
@@ -518,7 +569,8 @@ TinyMCE.prototype.eventPatch = function(editor_id) {
                        if (document.frames[i].event) {\r
                                var event = document.frames[i].event;\r
 \r
-                               event.target = event.srcElement;\r
+                               if (!event.target)\r
+                                       event.target = event.srcElement;\r
 \r
                                TinyMCE.prototype.handleEvent(event);\r
                                return;\r
@@ -565,6 +617,22 @@ TinyMCE.prototype.addEventHandlers = function(editor_id) {
 TinyMCE.prototype._createIFrame = function(replace_element) {\r
        var iframe = document.createElement("iframe");\r
        var id = replace_element.getAttribute("id");\r
+       var aw, ah;\r
+\r
+       aw = "" + tinyMCE.settings['area_width'];\r
+       ah = "" + tinyMCE.settings['area_height'];\r
+\r
+       if (aw.indexOf('%') == -1) {\r
+               aw = parseInt(aw);\r
+               aw = aw < 0 ? 300 : aw;\r
+               aw = aw + "px";\r
+       }\r
+\r
+       if (ah.indexOf('%') == -1) {\r
+               ah = parseInt(ah);\r
+               ah = ah < 0 ? 240 : ah;\r
+               ah = ah + "px";\r
+       }\r
 \r
        iframe.setAttribute("id", id);\r
        //iframe.setAttribute("className", "mceEditorArea");\r
@@ -574,22 +642,22 @@ TinyMCE.prototype._createIFrame = function(replace_element) {
        iframe.setAttribute("marginHeight", "0");\r
        iframe.setAttribute("leftMargin", "0");\r
        iframe.setAttribute("topMargin", "0");\r
-       iframe.setAttribute("width", tinyMCE.settings['area_width']);\r
-       iframe.setAttribute("height", tinyMCE.settings['area_height']);\r
+       iframe.setAttribute("width", aw);\r
+       iframe.setAttribute("height", ah);\r
        iframe.setAttribute("allowtransparency", "true");\r
 \r
        if (tinyMCE.settings["auto_resize"])\r
                iframe.setAttribute("scrolling", "no");\r
 \r
        // Must have a src element in MSIE HTTPs breaks aswell as absoute URLs\r
-       if (tinyMCE.isMSIE)\r
+       if (tinyMCE.isMSIE && !tinyMCE.isOpera)\r
                iframe.setAttribute("src", this.settings['default_document']);\r
 \r
-       iframe.style.width = tinyMCE.settings['area_width'];\r
-       iframe.style.height = tinyMCE.settings['area_height'];\r
+       iframe.style.width = aw;\r
+       iframe.style.height = ah;\r
 \r
        // MSIE 5.0 issue\r
-       if (tinyMCE.isMSIE)\r
+       if (tinyMCE.isMSIE && !tinyMCE.isOpera)\r
                replace_element.outerHTML = iframe.outerHTML;\r
        else\r
                replace_element.parentNode.replaceChild(iframe, replace_element);\r
@@ -606,12 +674,15 @@ TinyMCE.prototype.setupContent = function(editor_id) {
        var head = doc.getElementsByTagName('head').item(0);\r
        var content = inst.startContent;\r
 \r
+       tinyMCE.operaOpacityCounter = 100 * tinyMCE.idCounter;\r
+\r
        inst.switchSettings();\r
 \r
        // Not loaded correctly hit it again, Mozilla bug #997860\r
-       if (!tinyMCE.isMSIE && doc.title != "blank_page") {\r
+       if (!tinyMCE.isMSIE && tinyMCE.getParam("setupcontent_reload", false) && doc.title != "blank_page") {\r
                // This part will remove the designMode status\r
-               doc.location.href = tinyMCE.baseURL + "/blank.htm";\r
+               // Failes first time in Firefox 1.5b2 on Mac\r
+               try {doc.location.href = tinyMCE.baseURL + "/blank.htm";} catch (ex) {}\r
                window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000);\r
                return;\r
        }\r
@@ -626,6 +697,10 @@ TinyMCE.prototype.setupContent = function(editor_id) {
        tinyMCE.importCSS(inst.getDoc(), inst.settings['content_css']);\r
        tinyMCE.executeCallback('init_instance_callback', '_initInstance', 0, inst);\r
 \r
+       // Setup span styles\r
+       if (tinyMCE.getParam("convert_fonts_to_spans"))\r
+               inst.getDoc().body.setAttribute('id', 'mceSpanFonts');\r
+\r
        if (tinyMCE.settings['nowrap'])\r
                doc.body.style.whiteSpace = "nowrap";\r
 \r
@@ -649,10 +724,10 @@ TinyMCE.prototype.setupContent = function(editor_id) {
        }\r
 \r
        // Open closed anchors\r
-       content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');\r
-       content = content.replace(new RegExp('<a(.*?)name="(.*?)"(.*?)>(.*?)</a>', 'gi'), '<a$1name="$2"$3></a>$4');\r
+//     content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');\r
 \r
        // Call custom cleanup code\r
+       content = tinyMCE.storeAwayURLs(content);\r
        content = tinyMCE._customCleanup(inst, "insert_to_editor", content);\r
 \r
        if (tinyMCE.isMSIE) {\r
@@ -670,6 +745,8 @@ TinyMCE.prototype.setupContent = function(editor_id) {
                body.editorId = editor_id;\r
        }\r
 \r
+       content = tinyMCE.cleanupHTMLCode(content);\r
+\r
        // Fix for bug #958637\r
        if (!tinyMCE.isMSIE) {\r
                var contentElement = inst.getDoc().createElement("body");\r
@@ -678,11 +755,11 @@ TinyMCE.prototype.setupContent = function(editor_id) {
                contentElement.innerHTML = content;\r
 \r
                // Remove weridness!\r
-               if (tinyMCE.settings['force_p_newlines'])\r
+               if (tinyMCE.isGecko && tinyMCE.settings['remove_lt_gt'])\r
                        content = content.replace(new RegExp('&lt;&gt;', 'g'), "");\r
 \r
                if (tinyMCE.settings['cleanup_on_startup'])\r
-                       inst.getBody().innerHTML = tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement);\r
+                       tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement));\r
                else {\r
                        // Convert all strong/em to b/i\r
                        content = tinyMCE.regexpReplace(content, "<strong", "<b", "gi");\r
@@ -690,7 +767,7 @@ TinyMCE.prototype.setupContent = function(editor_id) {
                        content = tinyMCE.regexpReplace(content, "<em ", "<i ", "gi");\r
                        content = tinyMCE.regexpReplace(content, "</strong>", "</b>", "gi");\r
                        content = tinyMCE.regexpReplace(content, "</em>", "</i>", "gi");\r
-                       inst.getBody().innerHTML = content;\r
+                       tinyMCE.setInnerHTML(inst.getBody(), content);\r
                }\r
 \r
                inst.convertAllRelativeURLs();\r
@@ -699,7 +776,7 @@ TinyMCE.prototype.setupContent = function(editor_id) {
                        tinyMCE._setHTML(inst.getDoc(), content);\r
 \r
                        // Produces permission denied error in MSIE 5.5\r
-                       eval('try {inst.getBody().innerHTML = tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody());} catch(e) {}');\r
+                       eval('try {tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));} catch(e) {}');\r
                } else\r
                        tinyMCE._setHTML(inst.getDoc(), content);\r
        }\r
@@ -709,10 +786,10 @@ TinyMCE.prototype.setupContent = function(editor_id) {
 \r
        // Setup element references\r
        var parentElm = document.getElementById(inst.editorId + '_parent');\r
-       if (parentElm.lastChild.nodeName.toLowerCase() == "input")\r
-               inst.formElement = parentElm.lastChild;\r
+       if (parentElm.lastChild.nodeName == "INPUT")\r
+               inst.formElement = tinyMCE.isGecko ? parentElm.firstChild : parentElm.lastChild;\r
        else\r
-               inst.formElement = parentElm.nextSibling;\r
+               inst.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling;\r
 \r
        tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual'], inst);\r
        tinyMCE.executeCallback('setupcontent_callback', '_setupContent', 0, editor_id, inst.getBody(), inst.getDoc());\r
@@ -728,15 +805,58 @@ TinyMCE.prototype.setupContent = function(editor_id) {
        // Trigger node change, this call locks buttons for tables and so forth\r
        tinyMCE.selectedInstance = inst;\r
        tinyMCE.selectedElement = inst.contentWindow.document.body;\r
-       tinyMCE.triggerNodeChange(false, true);\r
+\r
+       if (!inst.isHidden())\r
+               tinyMCE.triggerNodeChange(false, true);\r
 \r
        // Call custom DOM cleanup\r
        tinyMCE._customCleanup(inst, "insert_to_editor_dom", inst.getBody());\r
        tinyMCE._customCleanup(inst, "setup_content_dom", inst.getBody());\r
-       tinyMCE._setEventsEnabled(inst.getBody(), true);\r
+       tinyMCE._setEventsEnabled(inst.getBody(), false);\r
+       tinyMCE.cleanupAnchors(inst.getDoc());\r
+\r
+       if (tinyMCE.getParam("convert_fonts_to_spans"))\r
+               tinyMCE.convertSpansToFonts(inst.getDoc());\r
 \r
        inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);\r
        inst.undoLevels[inst.undoLevels.length] = inst.startContent;\r
+\r
+       tinyMCE.operaOpacityCounter = -1;\r
+};\r
+\r
+TinyMCE.prototype.cleanupHTMLCode = function(s) {\r
+       s = s.replace(/<p \/>/gi, '<p>&nbsp;</p>');\r
+       s = s.replace(/<p>\s*<\/p>/gi, '<p>&nbsp;</p>');\r
+\r
+       // Open closed tags like <b/> to <b></b>\r
+//     tinyMCE.debug("f:" + s);\r
+       s = s.replace(/<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\|>]*?)\/>/gi, '<$1$2$3></$1$2>');\r
+//     tinyMCE.debug("e:" + s);\r
+\r
+       // Remove trailing space <b > to <b>\r
+       s = s.replace(new RegExp('\\s+></', 'gi'), '></');\r
+\r
+       // Close tags <img></img> to <img/>\r
+       s = s.replace(/<(img|br|hr)(.*?)><\/(img|br|hr)>/gi, '<$1$2 />');\r
+\r
+       // Weird MSIE bug, <p><hr /></p> breaks runtime?\r
+       if (tinyMCE.isMSIE)\r
+               s = s.replace(/<p><hr \/><\/p>/gi, "<hr>");\r
+\r
+       // Convert relative anchors to absolute URLs ex: #something to file.htm#something\r
+       s = s.replace(new RegExp('(href=\"?)(\\s*?#)', 'gi'), '$1' + tinyMCE.settings['document_base_url'] + "#");\r
+\r
+       return s;\r
+};\r
+\r
+TinyMCE.prototype.storeAwayURLs = function(s) {\r
+       // Remove all mce_src, mce_href and replace them with new ones\r
+       s = s.replace(new RegExp('mce_src\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');\r
+       s = s.replace(new RegExp('mce_href\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');\r
+       s = s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'src="$1" mce_src="$1"');\r
+       s = s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'href="$1" mce_href="$1"');\r
+\r
+       return s;\r
 };\r
 \r
 TinyMCE.prototype.cancelEvent = function(e) {\r
@@ -748,6 +868,22 @@ TinyMCE.prototype.cancelEvent = function(e) {
 };\r
 \r
 TinyMCE.prototype.removeTinyMCEFormElements = function(form_obj) {\r
+       // Check if form is valid\r
+       if (typeof(form_obj) == "undefined" || form_obj == null)\r
+               return;\r
+\r
+       // If not a form, find the form\r
+       if (form_obj.nodeName != "FORM") {\r
+               if (form_obj.form)\r
+                       form_obj = form_obj.form;\r
+               else\r
+                       form_obj = tinyMCE.getParentElement(form_obj, "form");\r
+       }\r
+\r
+       // Still nothing\r
+       if (form_obj == null)\r
+               return;\r
+\r
        // Disable all UI form elements that TinyMCE created\r
        for (var i=0; i<form_obj.elements.length; i++) {\r
                var elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id;\r
@@ -853,52 +989,42 @@ TinyMCE.prototype.handleEvent = function(e) {
                                if (tinyMCE.selectedInstance._handleBackSpace(e.type)) {\r
                                        // Cancel event\r
                                        tinyMCE.execCommand("mceAddUndoLevel");\r
-                                       e.preventDefault();\r
+                                       tinyMCE.cancelEvent(e);\r
                                        return false;\r
                                }\r
                        }\r
 \r
                        // Mozilla custom key handling\r
-                       if (tinyMCE.isGecko && e.ctrlKey && tinyMCE.settings['custom_undo_redo']) {\r
+                       if (tinyMCE.isGecko && (e.ctrlKey && !e.altKey) && tinyMCE.settings['custom_undo_redo']) {\r
                                if (tinyMCE.settings['custom_undo_redo_keyboard_shortcuts']) {\r
                                        if (e.charCode == 122) { // Ctrl+Z\r
                                                tinyMCE.selectedInstance.execCommand("Undo");\r
-\r
-                                               // Cancel event\r
-                                               e.preventDefault();\r
+                                               tinyMCE.cancelEvent(e);\r
                                                return false;\r
                                        }\r
 \r
                                        if (e.charCode == 121) { // Ctrl+Y\r
                                                tinyMCE.selectedInstance.execCommand("Redo");\r
-\r
-                                               // Cancel event\r
-                                               e.preventDefault();\r
+                                               tinyMCE.cancelEvent(e);\r
                                                return false;\r
                                        }\r
                                }\r
 \r
                                if (e.charCode == 98) { // Ctrl+B\r
                                        tinyMCE.selectedInstance.execCommand("Bold");\r
-\r
-                                       // Cancel event\r
-                                       e.preventDefault();\r
+                                       tinyMCE.cancelEvent(e);\r
                                        return false;\r
                                }\r
 \r
                                if (e.charCode == 105) { // Ctrl+I\r
                                        tinyMCE.selectedInstance.execCommand("Italic");\r
-\r
-                                       // Cancel event\r
-                                       e.preventDefault();\r
+                                       tinyMCE.cancelEvent(e);\r
                                        return false;\r
                                }\r
 \r
                                if (e.charCode == 117) { // Ctrl+U\r
                                        tinyMCE.selectedInstance.execCommand("Underline");\r
-\r
-                                       // Cancel event\r
-                                       e.preventDefault();\r
+                                       tinyMCE.cancelEvent(e);\r
                                        return false;\r
                                }\r
                        }\r
@@ -975,10 +1101,6 @@ TinyMCE.prototype.handleEvent = function(e) {
                        if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9)\r
                                tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);\r
 \r
-                       // Run image/link fix on Gecko if diffrent document base on paste\r
-                       if (tinyMCE.isGecko && tinyMCE.settings['document_base_url'] != "" + document.location.href && e.type == "keyup" && e.ctrlKey && e.keyCode == 86)\r
-                               tinyMCE.selectedInstance.fixBrokenURLs();\r
-\r
                        // Fix empty elements on return/enter, check where enter occured\r
                        if (tinyMCE.isMSIE && e.type == "keydown" && e.keyCode == 13)\r
                                tinyMCE.enterKeyElement = tinyMCE.selectedInstance.getFocusElement();\r
@@ -1009,8 +1131,6 @@ TinyMCE.prototype.handleEvent = function(e) {
                                }\r
                        }\r
 \r
-                       //tinyMCE.debug(e.keyCode);\r
-\r
                        // MSIE custom key handling\r
                        if (tinyMCE.isMSIE && tinyMCE.settings['custom_undo_redo']) {\r
                                var keys = new Array(8,46); // Backspace,Delete\r
@@ -1022,17 +1142,17 @@ TinyMCE.prototype.handleEvent = function(e) {
                                }\r
 \r
                                if (tinyMCE.settings['custom_undo_redo_keyboard_shortcuts']) {\r
-                                       if (e.keyCode == 90 && e.ctrlKey && e.type == "keydown") { // Ctrl+Z\r
+                                       if (e.keyCode == 90 && (e.ctrlKey && !e.altKey) && e.type == "keydown") { // Ctrl+Z\r
                                                tinyMCE.selectedInstance.execCommand("Undo");\r
                                                tinyMCE.triggerNodeChange(false);\r
                                        }\r
 \r
-                                       if (e.keyCode == 89 && e.ctrlKey && e.type == "keydown") { // Ctrl+Y\r
+                                       if (e.keyCode == 89 && (e.ctrlKey && !e.altKey) && e.type == "keydown") { // Ctrl+Y\r
                                                tinyMCE.selectedInstance.execCommand("Redo");\r
                                                tinyMCE.triggerNodeChange(false);\r
                                        }\r
 \r
-                                       if ((e.keyCode == 90 || e.keyCode == 89) && e.ctrlKey) {\r
+                                       if ((e.keyCode == 90 || e.keyCode == 89) && (e.ctrlKey && !e.altKey)) {\r
                                                // Cancel event\r
                                                e.returnValue = false;\r
                                                e.cancelBubble = true;\r
@@ -1041,6 +1161,14 @@ TinyMCE.prototype.handleEvent = function(e) {
                                }\r
                        }\r
 \r
+                       // If undo/redo key\r
+                       if ((e.keyCode == 90 || e.keyCode == 89) && (e.ctrlKey && !e.altKey))\r
+                               return true;\r
+\r
+                       // If Ctrl key\r
+                       if (e.keyCode == 17)\r
+                               return true;\r
+\r
                        // Handle Undo/Redo when typing content\r
 \r
                        // Start typing (non position key)\r
@@ -1053,6 +1181,9 @@ TinyMCE.prototype.handleEvent = function(e) {
 \r
                        if (posKey && e.type == "keyup")\r
                                tinyMCE.triggerNodeChange(false);\r
+\r
+                       if (tinyMCE.isMSIE && e.ctrlKey)\r
+                               window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
                break;\r
 \r
                case "mousedown":\r
@@ -1065,7 +1196,7 @@ TinyMCE.prototype.handleEvent = function(e) {
                        // Check instance event trigged on\r
                        var targetBody = tinyMCE.getParentElement(e.target, "body");\r
                        for (var instanceName in tinyMCE.instances) {\r
-                               if (typeof(tinyMCE.instances[instanceName]) == 'function')\r
+                               if (!tinyMCE.isInstance(tinyMCE.instances[instanceName]))\r
                                        continue;\r
 \r
                                var inst = tinyMCE.instances[instanceName];\r
@@ -1117,10 +1248,6 @@ TinyMCE.prototype.handleEvent = function(e) {
                        if (!tinyMCE.selectedInstance && e.target.editorId)\r
                                tinyMCE.selectedInstance = tinyMCE.instances[e.target.editorId];\r
 \r
-                       // Run image/link fix on Gecko if diffrent document base\r
-                       if (tinyMCE.isGecko && tinyMCE.settings['document_base_url'] != "" + document.location.href)\r
-                               window.setTimeout('tinyMCE.getInstanceById("' + inst.editorId + '").fixBrokenURLs();', 10);\r
-\r
                        return false;\r
                break;\r
     } // end switch\r
@@ -1165,6 +1292,28 @@ TinyMCE.prototype.switchClassSticky = function(element_name, class_name, lock_st
        if (element != null && (lockChanged || !element.classLock)) {\r
                element.className = class_name;\r
                element.oldClassName = class_name;\r
+\r
+               // Fix opacity in Opera\r
+               if (tinyMCE.isOpera) {\r
+                       if (class_name == "mceButtonDisabled") {\r
+                               var suffix = "";\r
+\r
+                               if (!element.mceOldSrc)\r
+                                       element.mceOldSrc = element.src;\r
+\r
+                               if (this.operaOpacityCounter > -1)\r
+                                       suffix = '?rnd=' + this.operaOpacityCounter++;\r
+\r
+                               element.src = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/images/opacity.png" + suffix;\r
+                               element.style.backgroundImage = "url('" + element.mceOldSrc + "')";\r
+                       } else {\r
+                               if (element.mceOldSrc) {\r
+                                       element.src = element.mceOldSrc;\r
+                                       element.parentNode.style.backgroundImage = "";\r
+                                       element.mceOldSrc = null;\r
+                               }\r
+                       }\r
+               }\r
        }\r
 };\r
 \r
@@ -1262,6 +1411,9 @@ TinyMCE.prototype.onLoad = function() {
                                        if (selector != '' && tinyMCE.getAttrib(elm, "class").indexOf(selector) == -1)\r
                                                continue;\r
 \r
+                                       if (selector != '')\r
+                                               trigger = selector != "" ? "true" : "";\r
+\r
                                        if (tinyMCE.getAttrib(elm, "class").indexOf(deselector) != -1)\r
                                                continue;\r
 \r
@@ -1316,7 +1468,7 @@ TinyMCE.prototype.removeMCEControl = function(editor_id) {
                var tmpInstances = new Array();\r
                for (var instanceName in tinyMCE.instances) {\r
                        var instance = tinyMCE.instances[instanceName];\r
-                       if (typeof(instance) == 'function')\r
+                       if (!tinyMCE.isInstance(instance))\r
                                continue;\r
 \r
                        if (instanceName != editor_id)\r
@@ -1432,7 +1584,7 @@ TinyMCE.prototype._moveStyle = function(elm, style, attrib) {
 \r
                        switch (attrib) {\r
                                case "background":\r
-                                       val = "url('" + val + "');";\r
+                                       val = "url('" + val + "')";\r
                                        break;\r
 \r
                                case "bordercolor":\r
@@ -1533,22 +1685,8 @@ TinyMCE.prototype._cleanupAttribute = function(valid_attributes, element_name, a
        if (attribName.indexOf('moz_') != -1)\r
                return null;\r
 \r
-       // Mozilla fix for drag-drop/copy/paste images\r
-       if (!tinyMCE.isMSIE && (attribName == "mce_real_href" || attribName == "mce_real_src")) {\r
-               if (!tinyMCE.cleanup_on_save) {\r
-                       var attrib = new Object();\r
-\r
-                       attrib.name = attribName;\r
-                       attrib.value = attribValue;\r
-\r
-                       return attrib;\r
-               } else\r
-                       return null;\r
-       }\r
-\r
-       // Auto verify \r
-       if (attribName == "mce_onclick")\r
-               verified = true;\r
+       if (!tinyMCE.cleanup_on_save && (attribName == "mce_href" || attribName == "mce_src"))\r
+               return {name : attribName, value : attribValue};\r
 \r
        // Verify attrib\r
        if (tinyMCE.cleanup_verify_html && !verified) {\r
@@ -1596,12 +1734,26 @@ TinyMCE.prototype._cleanupAttribute = function(valid_attributes, element_name, a
                        attribValue = attribValue.toLowerCase();\r
                        break;\r
 \r
+               case "cellspacing":\r
+                       if (tinyMCE.isMSIE5)\r
+                               attribValue = element_node.cellSpacing;\r
+                       break;\r
+\r
+               case "cellpadding":\r
+                       if (tinyMCE.isMSIE5)\r
+                               attribValue = element_node.cellPadding;\r
+                       break;\r
+\r
                case "color":\r
                        if (tinyMCE.isMSIE5 && element_name == "font")\r
                                attribValue = element_node.color;\r
                        break;\r
 \r
                case "class":\r
+                       // Remove mceItem classes from anchors\r
+                       if (tinyMCE.cleanup_on_save && attribValue.indexOf('mceItemAnchor') != -1)\r
+                               attribValue = attribValue.replace(/mceItem[a-z0-9]+/gi, '');\r
+\r
                        if (element_name == "table" || element_name == "td") {\r
                                // Handle visual aid\r
                                if (tinyMCE.cleanup_visual_table_class != "")\r
@@ -1634,25 +1786,31 @@ TinyMCE.prototype._cleanupAttribute = function(valid_attributes, element_name, a
                        break;\r
 \r
                case "style":\r
-                       attribValue = tinyMCE.serializeStyle(tinyMCE.parseStyle(element_node.style.cssText));\r
+                       attribValue = tinyMCE.serializeStyle(tinyMCE.parseStyle(tinyMCE.getAttrib(element_node, "style")));\r
                        break;\r
 \r
                // Convert the URLs of these\r
                case "href":\r
                case "src":\r
-                       // Fix for dragdrop/copy paste Mozilla issue\r
-                       if (!tinyMCE.isMSIE && attribName == "href" && element_node.getAttribute("mce_real_href"))\r
-                               attribValue = element_node.getAttribute("mce_real_href");\r
+               case "longdesc":\r
+                       attribValue = tinyMCE.getAttrib(element_node, attribName);\r
 \r
-                       // Fix for dragdrop/copy paste Mozilla issue\r
-                       if (!tinyMCE.isMSIE && attribName == "src" && element_node.getAttribute("mce_real_src"))\r
-                               attribValue = element_node.getAttribute("mce_real_src");\r
+                       // Use mce_href instead\r
+                       var href = tinyMCE.getAttrib(element_node, "mce_href");\r
+                       if (attribName == "href" && href != "")\r
+                               attribValue = href;\r
 \r
-                       // Force absolute URLs in Firefox\r
-                       if (tinyMCE.isGecko && !tinyMCE.settings['relative_urls'])\r
+                       // Use mce_src instead\r
+                       var src = tinyMCE.getAttrib(element_node, "mce_src");\r
+                       if (attribName == "src" && src != "")\r
+                               attribValue = src;\r
+\r
+                       // Always use absolute URLs within TinyMCE\r
+                       if (!tinyMCE.cleanup_on_save)\r
                                attribValue = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], attribValue);\r
+                       else if (tinyMCE.getParam('convert_urls'))\r
+                               attribValue = eval(tinyMCE.cleanup_urlconverter_callback + "(attribValue, element_node, tinyMCE.cleanup_on_save);");\r
 \r
-                       attribValue = eval(tinyMCE.cleanup_urlconverter_callback + "(attribValue, element_node, tinyMCE.cleanup_on_save);");\r
                        break;\r
 \r
                case "colspan":\r
@@ -1665,8 +1823,8 @@ TinyMCE.prototype._cleanupAttribute = function(valid_attributes, element_name, a
                // Skip these\r
                case "_moz-userdefined":\r
                case "editorid":\r
-               case "mce_real_href":\r
-               case "mce_real_src":\r
+               case "mce_href":\r
+               case "mce_src":\r
                        return null;\r
        }\r
 \r
@@ -1692,10 +1850,28 @@ TinyMCE.prototype._cleanupAttribute = function(valid_attributes, element_name, a
        return attrib;\r
 };\r
 \r
+TinyMCE.prototype.clearArray = function(ar) {\r
+       // Since stupid people tend to extend core objects like\r
+       // Array with their own crap I needed to make functions that clean away\r
+       // this junk so the arrays get clean and nice as they should be\r
+       for (var key in ar)\r
+               ar[key] = null;\r
+};\r
+\r
+TinyMCE.prototype.isInstance = function(inst) {\r
+       return inst != null && typeof(inst) == "object" && inst.isTinyMCEControl;\r
+};\r
+\r
 TinyMCE.prototype.parseStyle = function(str) {\r
        var ar = new Array();\r
+\r
+       if (str == null)\r
+               return ar;\r
+\r
        var st = str.split(';');\r
 \r
+       tinyMCE.clearArray(ar);\r
+\r
        for (var i=0; i<st.length; i++) {\r
                if (st[i] == '')\r
                        continue;\r
@@ -1755,6 +1931,18 @@ TinyMCE.prototype.serializeStyle = function(ar) {
                        // Fix style URL\r
                        val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')");\r
 \r
+                       // Convert URL\r
+                       if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) {\r
+                               var m = new RegExp("url\\('(.*?)'\\)").exec(val);\r
+\r
+                               if (m.length > 1)\r
+                                       val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')";\r
+                       }\r
+\r
+                       // Force HEX colors\r
+                       if (tinyMCE.getParam("force_hex_style_colors"))\r
+                               val = tinyMCE.convertRGBToHex(val, true);\r
+\r
                        if (val != "url('')")\r
                                str += key.toLowerCase() + ": " + val + "; ";\r
                }\r
@@ -1766,6 +1954,38 @@ TinyMCE.prototype.serializeStyle = function(ar) {
        return str;\r
 };\r
 \r
+TinyMCE.prototype.convertRGBToHex = function(s, k) {\r
+       if (s.toLowerCase().indexOf('rgb') != -1) {\r
+               var re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");\r
+               var rgb = s.replace(re, "$1,$2,$3,$4,$5").split(',');\r
+               if (rgb.length == 5) {\r
+                       r = parseInt(rgb[1]).toString(16);\r
+                       g = parseInt(rgb[2]).toString(16);\r
+                       b = parseInt(rgb[3]).toString(16);\r
+\r
+                       r = r.length == 1 ? '0' + r : r;\r
+                       g = g.length == 1 ? '0' + g : g;\r
+                       b = b.length == 1 ? '0' + b : b;\r
+\r
+                       s = "#" + r + g + b;\r
+\r
+                       if (k)\r
+                               s = rgb[0] + s + rgb[4];\r
+               }\r
+       }\r
+\r
+       return s;\r
+};\r
+\r
+TinyMCE.prototype.convertHexToRGB = function(s) {\r
+       if (s.indexOf('#') != -1) {\r
+               s = s.replace(new RegExp('[^0-9A-F]', 'gi'), '');\r
+               return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")";\r
+       }\r
+\r
+       return s;\r
+};\r
+\r
 TinyMCE.prototype._verifyClass = function(node) {\r
        // Sometimes the class gets set to null, weird Gecko bug?\r
        if (tinyMCE.isGecko) {\r
@@ -1859,7 +2079,7 @@ TinyMCE.prototype.cleanupNode = function(node) {
                        if (re.test(node.nodeName)) {\r
                                // Move attrib to style\r
                                if ((node.nodeName != "TABLE" || tinyMCE.cleanup_inline_styles) && (width = tinyMCE.getAttrib(node, "width")) != '') {\r
-                                       node.style.width = width.indexOf('%') == -1 ? width : width + "px";\r
+                                       node.style.width = width.indexOf('%') != -1 ? width : width.replace(/[^0-9]/gi, '') + "px";\r
                                        node.removeAttribute("width");\r
                                }\r
 \r
@@ -1871,7 +2091,8 @@ TinyMCE.prototype.cleanupNode = function(node) {
 \r
                                // Move attrib to style\r
                                if ((height = tinyMCE.getAttrib(node, "height")) != '') {\r
-                                       node.style.height = height.indexOf('%') == -1 ? height : height + "px";\r
+                                       height = "" + height; // Force string\r
+                                       node.style.height = height.indexOf('%') != -1 ? height : height.replace(/[^0-9]/gi, '') + "px";\r
                                        node.removeAttribute("height");\r
                                }\r
                        }\r
@@ -1879,7 +2100,7 @@ TinyMCE.prototype.cleanupNode = function(node) {
                        // Handle inline/outline styles\r
                        if (tinyMCE.cleanup_inline_styles) {\r
                                var re = new RegExp("^(TABLE|TD|TR|IMG|HR)$");\r
-                               if (re.test(node.nodeName)) {\r
+                               if (re.test(node.nodeName) && tinyMCE.getAttrib(node, "class").indexOf('mceItem') == -1) {\r
                                        tinyMCE._moveStyle(node, 'width', 'width');\r
                                        tinyMCE._moveStyle(node, 'height', 'height');\r
                                        tinyMCE._moveStyle(node, 'borderWidth', 'border');\r
@@ -1931,15 +2152,28 @@ TinyMCE.prototype.cleanupNode = function(node) {
                                }\r
                        }\r
 \r
+                       if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && elementName == "style")\r
+                               return "<style>" + node.innerHTML + "</style>";\r
+\r
                        // Remove empty tables\r
                        if (elementName == "table" && !node.hasChildNodes())\r
                                return "";\r
 \r
                        // Handle element attributes\r
                        if (node.attributes.length > 0) {\r
+                               var lastAttrib = "";\r
+\r
                                for (var i=0; i<node.attributes.length; i++) {\r
-                                       if (node.attributes[i].specified || (node.attributes[i].nodeValue != null && node.attributes[i].nodeValue.length > 0)) {\r
-                                               // tinyMCE.debug(node.attributes[i].nodeName + "=" + node.attributes[i].nodeValue);\r
+                                       if (node.attributes[i].specified) {\r
+                                               // Is the attrib already processed (removed duplicate attributes in opera TD[align=left])\r
+                                               if (tinyMCE.isOpera) {\r
+                                                       if (node.attributes[i].nodeName == lastAttrib)\r
+                                                               continue;\r
+\r
+                                                       lastAttrib = node.attributes[i].nodeName;\r
+                                               }\r
+\r
+                                               // tinyMCE.debug(node.nodeName, node.attributes[i].nodeName, node.attributes[i].nodeValue, node.innerHTML);\r
                                                var attrib = tinyMCE._cleanupAttribute(elementValidAttribs, elementName, node.attributes[i], node);\r
                                                if (attrib && attrib.value != "")\r
                                                        elementAttribs += " " + attrib.name + "=" + '"' + this.convertStringToXML("" + attrib.value) + '"';\r
@@ -1954,6 +2188,20 @@ TinyMCE.prototype.cleanupNode = function(node) {
                                        elementAttribs += " summary=" + '"' + this.convertStringToXML(summary) + '"';\r
                        }\r
 \r
+                       // Handle missing attributes in MSIE 5.5\r
+                       if (tinyMCE.isMSIE5 && /^(td|img|a)$/.test(elementName)) {\r
+                               var ma = new Array("scope", "longdesc", "hreflang", "charset", "type");\r
+\r
+                               for (var u=0; u<ma.length; u++) {\r
+                                       if (node.getAttribute(ma[u]) != null) {\r
+                                               var s = tinyMCE.getAttrib(node, ma[u]);\r
+\r
+                                               if (s != '')\r
+                                                       elementAttribs += " " + ma[u] + "=" + '"' + this.convertStringToXML(s) + '"';\r
+                                       }\r
+                               }\r
+                       }\r
+\r
                        // MSIE form element issue\r
                        if (tinyMCE.isMSIE && elementName == "input") {\r
                                if (node.type) {\r
@@ -1977,20 +2225,26 @@ TinyMCE.prototype.cleanupNode = function(node) {
 \r
                        // Clean up children\r
                        if (node.hasChildNodes()) {\r
-                               // Force BR\r
-                               if (elementName == "p" && tinyMCE.cleanup_force_br_newlines)\r
-                                       output += "<div" + elementAttribs + ">";\r
-                               else\r
-                                       output += "<" + elementName + elementAttribs + ">";\r
+                               // If not empty span\r
+                               if (!(elementName == "span" && elementAttribs == "" && tinyMCE.getParam("trim_span_elements"))) {\r
+                                       // Force BR\r
+                                       if (elementName == "p" && tinyMCE.cleanup_force_br_newlines)\r
+                                               output += "<div" + elementAttribs + ">";\r
+                                       else\r
+                                               output += "<" + elementName + elementAttribs + ">";\r
+                               }\r
 \r
                                for (var i=0; i<node.childNodes.length; i++)\r
                                        output += this.cleanupNode(node.childNodes[i]);\r
 \r
-                               // Force BR\r
-                               if (elementName == "p" && tinyMCE.cleanup_force_br_newlines)\r
-                                       output += "</div><br />";\r
-                               else\r
-                                       output += "</" + elementName + ">";\r
+                               // If not empty span\r
+                               if (!(elementName == "span" && elementAttribs == "" && tinyMCE.getParam("trim_span_elements"))) {\r
+                                       // Force BR\r
+                                       if (elementName == "p" && tinyMCE.cleanup_force_br_newlines)\r
+                                               output += "</div><br />";\r
+                                       else\r
+                                               output += "</" + elementName + ">";\r
+                               }\r
                        } else {\r
                                if (!nonEmptyTag) {\r
                                        if (openTag)\r
@@ -2004,7 +2258,7 @@ TinyMCE.prototype.cleanupNode = function(node) {
 \r
                case 3: // Text\r
                        // Do not convert script elements\r
-                       if (node.parentNode.nodeName.toLowerCase() == "script")\r
+                       if (node.parentNode.nodeName == "SCRIPT" || node.parentNode.nodeName == "NOSCRIPT" || node.parentNode.nodeName == "STYLE")\r
                                return node.nodeValue;\r
 \r
                        return this.convertStringToXML(node.nodeValue);\r
@@ -2040,8 +2294,8 @@ TinyMCE.prototype.convertStringToXML = function(html_data) {
                }\r
 \r
                // Named entities\r
-               if (typeof(tinyMCE.cleanup_entities["c" + chr]) != 'undefined' && tinyMCE.cleanup_entities["c" + chr] != '')\r
-                       output += '&' + tinyMCE.cleanup_entities["c" + chr] + ';';\r
+               if (typeof(tinyMCE.settings['cleanup_entities']["c" + chr]) != 'undefined' && tinyMCE.settings['cleanup_entities']["c" + chr] != '')\r
+                       output += '&' + tinyMCE.settings['cleanup_entities']["c" + chr] + ';';\r
                else\r
                        output += '' + String.fromCharCode(chr);\r
     }\r
@@ -2144,24 +2398,39 @@ TinyMCE.prototype._initCleanup = function() {
        // Set these for performance\r
        tinyMCE.settings['cleanup_validElements'] = validElements;\r
        tinyMCE.settings['cleanup_invalidElements'] = invalidElements;\r
-\r
-       // Setup entities\r
-       tinyMCE.settings['cleanup_entities'] = new Array();\r
-       var entities = tinyMCE.getParam('entities', '', true, ',');\r
-       for (var i=0; i<entities.length; i+=2)\r
-               tinyMCE.settings['cleanup_entities']['c' + entities[i]] = entities[i+1];\r
 };\r
 \r
 TinyMCE.prototype._cleanupHTML = function(inst, doc, config, element, visual, on_save) {\r
-       if (!tinyMCE.settings['cleanup'])\r
-               return element.innerHTML;\r
+       if (!tinyMCE.settings['cleanup']) {\r
+               tinyMCE.handleVisualAid(inst.getBody(), true, false, inst);\r
+\r
+               var html = element.innerHTML;\r
+\r
+               // Remove mce_href/mce_src\r
+               html = html.replace(new RegExp('(mce_href|mce_src)=".*?"', 'gi'), '');\r
+               html = html.replace(/\s+>/gi, '>');\r
+\r
+               return html;\r
+       }\r
+\r
+       if (on_save && tinyMCE.getParam("convert_fonts_to_spans"))\r
+               tinyMCE.convertFontsToSpans(doc);\r
 \r
        // Call custom cleanup code\r
        tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body);\r
 \r
+       // Move bgcolor to style\r
+       var n = doc.getElementsByTagName("font");\r
+       for (var i=0; i<n.length; i++) {\r
+               var c = "";\r
+               if ((c = tinyMCE.getAttrib(n[i], "bgcolor")) != "") {\r
+                       n[i].style.backgroundColor = c;\r
+                       tinyMCE.setAttrib(n[i], "bgcolor", "");\r
+               }\r
+       }\r
+\r
        // Set these for performance\r
        tinyMCE.cleanup_validElements = tinyMCE.settings['cleanup_validElements'];\r
-       tinyMCE.cleanup_entities = tinyMCE.settings['cleanup_entities'];\r
        tinyMCE.cleanup_invalidElements = tinyMCE.settings['cleanup_invalidElements'];\r
        tinyMCE.cleanup_verify_html = tinyMCE.settings['verify_html'];\r
        tinyMCE.cleanup_force_br_newlines = tinyMCE.settings['force_br_newlines'];\r
@@ -2186,8 +2455,8 @@ TinyMCE.prototype._cleanupHTML = function(inst, doc, config, element, visual, on
                                nodes[i].removeAttribute("id");\r
                }\r
 \r
-               element.innerHTML = tinyMCE.regexpReplace(element.innerHTML, '<p>[ \n\r]*<hr.*>[ \n\r]*</p>', '<hr />', 'gi');\r
-               element.innerHTML = tinyMCE.regexpReplace(element.innerHTML, '<!([^-(DOCTYPE)]* )|<!/[^-]*>', '', 'gi');\r
+               tinyMCE.setInnerHTML(element, tinyMCE.regexpReplace(element.innerHTML, '<p>[ \n\r]*<hr.*>[ \n\r]*</p>', '<hr />', 'gi'));\r
+               tinyMCE.setInnerHTML(element, tinyMCE.regexpReplace(element.innerHTML, '<!([^-(DOCTYPE)]* )|<!/[^-]*>', '', 'gi'));\r
        }\r
 \r
        var html = this.cleanupNode(element);\r
@@ -2195,22 +2464,26 @@ TinyMCE.prototype._cleanupHTML = function(inst, doc, config, element, visual, on
        if (tinyMCE.settings['debug'])\r
                tinyMCE.debug("Cleanup process executed in: " + (new Date().getTime()-startTime) + " ms.");\r
 \r
-       // Remove pesky HR paragraphs\r
+       // Remove pesky HR paragraphs and other crap\r
        html = tinyMCE.regexpReplace(html, '<p><hr /></p>', '<hr />');\r
        html = tinyMCE.regexpReplace(html, '<p>&nbsp;</p><hr /><p>&nbsp;</p>', '<hr />');\r
        html = tinyMCE.regexpReplace(html, '<td>\\s*<br />\\s*</td>', '<td>&nbsp;</td>');\r
+       html = tinyMCE.regexpReplace(html, '<p>\\s*<br />\\s*</p>', '<p>&nbsp;</p>');\r
+       html = tinyMCE.regexpReplace(html, '<p>\\s*&nbsp;\\s*<br />\\s*&nbsp;\\s*</p>', '<p>&nbsp;</p>');\r
+       html = tinyMCE.regexpReplace(html, '<p>\\s*&nbsp;\\s*<br />\\s*</p>', '<p>&nbsp;</p>');\r
+       html = tinyMCE.regexpReplace(html, '<p>\\s*<br />\\s*&nbsp;\\s*</p>', '<p>&nbsp;</p>');\r
 \r
        // Remove empty anchors\r
        html = html.replace(new RegExp('<a>(.*?)</a>', 'gi'), '$1');\r
 \r
-       // Move contents behind anchors\r
-       html = html.replace(new RegExp('<a(.*?)name="(.*?)"(.*?)>(.*?)</a>', 'gi'), '<a$1name="$2"$3></a>$4');\r
-\r
        // Remove some mozilla crap\r
        if (!tinyMCE.isMSIE)\r
                html = html.replace(new RegExp('<o:p _moz-userdefined="" />', 'g'), "");\r
 \r
-       if (tinyMCE.settings['apply_source_formatting']) {\r
+       if (tinyMCE.settings['remove_linebreaks'])\r
+               html = html.replace(new RegExp('\r|\n', 'g'), ' ');\r
+\r
+       if (tinyMCE.getParam('apply_source_formatting')) {\r
                html = html.replace(new RegExp('<(p|div)([^>]*)>', 'g'), "\n<$1$2>\n");\r
                html = html.replace(new RegExp('<\/(p|div)([^>]*)>', 'g'), "\n</$1$2>\n");\r
                html = html.replace(new RegExp('<br />', 'g'), "<br />\n");\r
@@ -2221,15 +2494,12 @@ TinyMCE.prototype._cleanupHTML = function(inst, doc, config, element, visual, on
                html = html.replace(re, "<br />");\r
        }\r
 \r
-       if (tinyMCE.settings['force_p_newlines']) {\r
+       if (tinyMCE.isGecko && tinyMCE.settings['remove_lt_gt']) {\r
                // Remove weridness!\r
                var re = new RegExp('&lt;&gt;', 'g');\r
                html = html.replace(re, "");\r
        }\r
 \r
-       if (tinyMCE.settings['remove_linebreaks'])\r
-               html = html.replace(new RegExp('\r|\n', 'g'), ' ');\r
-\r
        // Call custom cleanup code\r
        html = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", html);\r
 \r
@@ -2257,8 +2527,12 @@ TinyMCE.prototype.insertLink = function(href, target, title, onclick, style_clas
                        newLink = true;\r
                }\r
 \r
-               href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, linkElement);");\r
-               tinyMCE.setAttrib(linkElement, 'href', href);\r
+               var mhref = href;\r
+               var thref = eval(tinyMCE.settings['urlconverter_callback'] + "(href, linkElement);");\r
+               mhref = tinyMCE.getParam('convert_urls') ? href : mhref;\r
+\r
+               tinyMCE.setAttrib(linkElement, 'href', thref);\r
+               tinyMCE.setAttrib(linkElement, 'mce_href', mhref);\r
                tinyMCE.setAttrib(linkElement, 'target', target);\r
                tinyMCE.setAttrib(linkElement, 'title', title);\r
         tinyMCE.setAttrib(linkElement, 'onclick', onclick);\r
@@ -2274,18 +2548,21 @@ TinyMCE.prototype.insertLink = function(href, target, title, onclick, style_clas
 \r
        if (!this.linkElement && this.selectedInstance) {\r
                if (tinyMCE.isSafari) {\r
-                       tinyMCE.execCommand("mceInsertContent", false, '<a href="#mce_temp_url#">' + this.selectedInstance.getSelectedHTML() + '</a>');\r
+                       tinyMCE.execCommand("mceInsertContent", false, '<a href="' + tinyMCE.uniqueURL + '">' + this.selectedInstance.getSelectedHTML() + '</a>');\r
                } else\r
-                       this.selectedInstance.contentDocument.execCommand("createlink", false, "#mce_temp_url#");\r
+                       this.selectedInstance.contentDocument.execCommand("createlink", false, tinyMCE.uniqueURL);\r
 \r
-               tinyMCE.linkElement = this.getElementByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", "#mce_temp_url#");\r
+               tinyMCE.linkElement = this.getElementByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", tinyMCE.uniqueURL);\r
 \r
-               var elementArray = this.getElementsByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", "#mce_temp_url#");\r
+               var elementArray = this.getElementsByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", tinyMCE.uniqueURL);\r
 \r
                for (var i=0; i<elementArray.length; i++) {\r
-                       href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, elementArray[i]);");\r
-                       tinyMCE.setAttrib(elementArray[i], 'href', href);\r
-                       tinyMCE.setAttrib(elementArray[i], 'mce_real_href', href);\r
+                       var mhref = href;\r
+                       var thref = eval(tinyMCE.settings['urlconverter_callback'] + "(href, elementArray[i]);");\r
+                       mhref = tinyMCE.getParam('convert_urls') ? href : mhref;\r
+\r
+                       tinyMCE.setAttrib(elementArray[i], 'href', thref);\r
+                       tinyMCE.setAttrib(elementArray[i], 'mce_href', mhref);\r
                        tinyMCE.setAttrib(elementArray[i], 'target', target);\r
                        tinyMCE.setAttrib(elementArray[i], 'title', title);\r
             tinyMCE.setAttrib(elementArray[i], 'onclick', onclick);\r
@@ -2296,9 +2573,12 @@ TinyMCE.prototype.insertLink = function(href, target, title, onclick, style_clas
        }\r
 \r
        if (this.linkElement) {\r
+               var mhref = href;\r
                href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, this.linkElement);");\r
+               mhref = tinyMCE.getParam('convert_urls') ? href : mhref;\r
+\r
                tinyMCE.setAttrib(this.linkElement, 'href', href);\r
-               tinyMCE.setAttrib(this.linkElement, 'mce_real_href', href);\r
+               tinyMCE.setAttrib(this.linkElement, 'mce_href', mhref);\r
                tinyMCE.setAttrib(this.linkElement, 'target', target);\r
                tinyMCE.setAttrib(this.linkElement, 'title', title);\r
         tinyMCE.setAttrib(this.linkElement, 'onclick', onclick);\r
@@ -2326,19 +2606,23 @@ TinyMCE.prototype.insertImage = function(src, alt, border, hspace, vspace, width
        } else {\r
                if (!this.imgElement && this.selectedInstance) {\r
                        if (tinyMCE.isSafari)\r
-                               tinyMCE.execCommand("mceInsertContent", false, '<img src="#mce_temp_url#" />');\r
+                               tinyMCE.execCommand("mceInsertContent", false, '<img src="' + tinyMCE.uniqueURL + '" />');\r
                        else\r
-                               this.selectedInstance.contentDocument.execCommand("insertimage", false, "#mce_temp_url#");\r
+                               this.selectedInstance.contentDocument.execCommand("insertimage", false, tinyMCE.uniqueURL);\r
 \r
-                       tinyMCE.imgElement = this.getElementByAttributeValue(this.selectedInstance.contentDocument.body, "img", "src", "#mce_temp_url#");\r
+                       tinyMCE.imgElement = this.getElementByAttributeValue(this.selectedInstance.contentDocument.body, "img", "src", tinyMCE.uniqueURL);\r
                }\r
        }\r
 \r
        if (this.imgElement) {\r
                var needsRepaint = false;\r
+               var msrc = src;\r
 \r
                src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, tinyMCE.imgElement);");\r
 \r
+               if (tinyMCE.getParam('convert_urls'))\r
+                       msrc = src;\r
+\r
                if (onmouseover && onmouseover != "")\r
                        onmouseover = "this.src='" + eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, tinyMCE.imgElement);") + "';";\r
 \r
@@ -2353,7 +2637,7 @@ TinyMCE.prototype.insertImage = function(src, alt, border, hspace, vspace, width
                        needsRepaint = true;\r
 \r
                tinyMCE.setAttrib(this.imgElement, 'src', src);\r
-               tinyMCE.setAttrib(this.imgElement, 'mce_real_src', src);\r
+               tinyMCE.setAttrib(this.imgElement, 'mce_src', msrc);\r
                tinyMCE.setAttrib(this.imgElement, 'alt', alt);\r
                tinyMCE.setAttrib(this.imgElement, 'title', title);\r
                tinyMCE.setAttrib(this.imgElement, 'align', align);\r
@@ -2395,7 +2679,7 @@ TinyMCE.prototype.getElementsByAttributeValue = function(node, element_name, att
                        elements[elements.length] = node;\r
        }\r
 \r
-       if (node.hasChildNodes) {\r
+       if (node && node.hasChildNodes()) {\r
                for (var x=0, n=node.childNodes.length; x<n; x++) {\r
                        var childElements = this.getElementsByAttributeValue(node.childNodes[x], element_name, attrib, value);\r
                        for (var i=0, m=childElements.length; i<m; i++)\r
@@ -2464,7 +2748,7 @@ TinyMCE.prototype.getParentElement = function(node, names, attrib_name, attrib_v
                                }\r
                        }\r
                }\r
-       } while (node = node.parentNode);\r
+       } while ((node = node.parentNode) != null);\r
 \r
        return null;\r
 };\r
@@ -2474,7 +2758,9 @@ TinyMCE.prototype.convertURL = function(url, node, on_save) {
        var host = document.location.hostname;\r
        var port = document.location.port;\r
 \r
-       var fileProto = (prot == "file:");\r
+       // Pass through file protocol\r
+       if (prot == "file:")\r
+               return url;\r
 \r
        // Something is wrong, remove weirdness\r
        url = tinyMCE.regexpReplace(url, '(http|https):///', '/');\r
@@ -2487,41 +2773,35 @@ TinyMCE.prototype.convertURL = function(url, node, on_save) {
        if (!tinyMCE.isMSIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/')\r
                return tinyMCE.settings['base_href'] + url;\r
 \r
-       // Handle absolute url anchors\r
-       if (!tinyMCE.settings['relative_urls']) {\r
-               var urlParts = tinyMCE.parseURL(url);\r
-               var baseUrlParts = tinyMCE.parseURL(tinyMCE.settings['base_href']);\r
+       // Handle relative URLs\r
+       if (on_save && tinyMCE.getParam('relative_urls')) {\r
+               var curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);\r
+               if (curl.charAt(0) == '/')\r
+                       curl = tinyMCE.settings['document_base_prefix'] + curl;\r
 \r
-               // If anchor and path is the same page\r
-               if (urlParts['anchor'] && urlParts['path'] == baseUrlParts['path'])\r
-                       return "#" + urlParts['anchor'];\r
+               var urlParts = tinyMCE.parseURL(curl);\r
+               var tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings['document_base_url']);\r
+\r
+               // Force relative\r
+               if (urlParts['host'] == tmpUrlParts['host'] && (urlParts['port'] == tmpUrlParts['port']))\r
+                       return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'], curl);\r
        }\r
 \r
-       // Convert to relative urls\r
-       if (on_save && tinyMCE.settings['relative_urls']) {\r
+       // Handle absolute URLs\r
+       if (!tinyMCE.getParam('relative_urls')) {\r
                var urlParts = tinyMCE.parseURL(url);\r
+               var baseUrlParts = tinyMCE.parseURL(tinyMCE.settings['base_href']);\r
 \r
-               // If not absolute url, do nothing (Mozilla)\r
-               // WEIRD STUFF?!\r
-/*             if (!urlParts['protocol'] && !tinyMCE.isMSIE) {\r
-                       var urlPrefix = "http://";\r
-                       urlPrefix += host;\r
-                       if (port != "")\r
-                               urlPrefix += ":" + port;\r
-\r
-                       url = urlPrefix + url;\r
-                       urlParts = tinyMCE.parseURL(url);\r
-               }*/\r
-\r
-               var tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings['document_base_url']);\r
+               // Force absolute URLs from relative URLs\r
+               url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);\r
 \r
-               // Link is within this site\r
-               if (urlParts['host'] == tmpUrlParts['host'] && (!urlParts['port'] || urlParts['port'] == tmpUrlParts['port']))\r
-                       return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'], url);\r
+               // If anchor and path is the same page\r
+               if (urlParts['anchor'] && urlParts['path'] == baseUrlParts['path'])\r
+                       return "#" + urlParts['anchor'];\r
        }\r
 \r
        // Remove current domain\r
-       if (!fileProto && tinyMCE.settings['remove_script_host']) {\r
+       if (tinyMCE.getParam('remove_script_host')) {\r
                var start = "", portPart = "";\r
 \r
                if (port != "")\r
@@ -2531,10 +2811,6 @@ TinyMCE.prototype.convertURL = function(url, node, on_save) {
 \r
                if (url.indexOf(start) == 0)\r
                        url = url.substring(start.length-1);\r
-\r
-               // Add first slash if missing on a absolute URL\r
-               if (!tinyMCE.settings['relative_urls'] && url.indexOf('://') == -1 && url.charAt(0) != '/')\r
-                       url = '/' + url;\r
        }\r
 \r
        return url;\r
@@ -2572,6 +2848,7 @@ TinyMCE.prototype.parseURL = function(url_str) {
                urlParts['host'] = url_str.substring(lastPos, pos);\r
 \r
                // Get port\r
+               urlParts['port'] = "";\r
                lastPos = pos;\r
                if (url_str.charAt(pos) == ':') {\r
                        pos = url_str.indexOf('/', lastPos);\r
@@ -2609,19 +2886,51 @@ TinyMCE.prototype.parseURL = function(url_str) {
        return urlParts;\r
 };\r
 \r
+TinyMCE.prototype.serializeURL = function(up) {\r
+       var url = "";\r
+\r
+       if (up['protocol'])\r
+               url += up['protocol'] + "://";\r
+\r
+       if (up['host'])\r
+               url += up['host'];\r
+\r
+       if (up['port'])\r
+               url += ":" + up['port'];\r
+\r
+       if (up['path'])\r
+               url += up['path'];\r
+\r
+       if (up['query'])\r
+               url += "?" + up['query'];\r
+\r
+       if (up['anchor'])\r
+               url += "#" + up['anchor'];\r
+\r
+       return url;\r
+};\r
+\r
 /**\r
  * Converts an absolute path to relative path.\r
  */\r
 TinyMCE.prototype.convertAbsoluteURLToRelativeURL = function(base_url, url_to_relative) {\r
+       var baseURL = this.parseURL(base_url);\r
+       var targetURL = this.parseURL(url_to_relative);\r
        var strTok1;\r
        var strTok2;\r
        var breakPoint = 0;\r
-       var outputString = "";\r
+       var outPath = "";\r
+       var forceSlash = false;\r
+\r
+       if (targetURL.path == "")\r
+               targetURL.path = "/";\r
+       else\r
+               forceSlash = true;\r
 \r
        // Crop away last path part\r
-       base_url = base_url.substring(0, base_url.lastIndexOf('/'));\r
+       base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/'));\r
        strTok1 = base_url.split('/');\r
-       strTok2 = url_to_relative.split('/');\r
+       strTok2 = targetURL.path.split('/');\r
 \r
        if (strTok1.length >= strTok2.length) {\r
                for (var i=0; i<strTok1.length; i++) {\r
@@ -2642,26 +2951,42 @@ TinyMCE.prototype.convertAbsoluteURLToRelativeURL = function(base_url, url_to_re
        }\r
 \r
        if (breakPoint == 1)\r
-               return url_to_relative;\r
+               return targetURL.path;\r
 \r
        for (var i=0; i<(strTok1.length-(breakPoint-1)); i++)\r
-               outputString += "../";\r
+               outPath += "../";\r
 \r
        for (var i=breakPoint-1; i<strTok2.length; i++) {\r
                if (i != (breakPoint-1))\r
-                       outputString += "/" + strTok2[i];\r
+                       outPath += "/" + strTok2[i];\r
                else\r
-                       outputString += strTok2[i];\r
+                       outPath += strTok2[i];\r
        }\r
 \r
-       return outputString;\r
+       targetURL.protocol = null;\r
+       targetURL.host = null;\r
+       targetURL.port = null;\r
+       targetURL.path = outPath == "" && forceSlash ? "/" : outPath;\r
+\r
+       // Remove document prefix from local anchors\r
+       var fileName = baseURL.path;\r
+       var pos;\r
+\r
+       if ((pos = fileName.lastIndexOf('/')) != -1)\r
+               fileName = fileName.substring(pos + 1);\r
+\r
+       // Is local anchor\r
+       if (fileName == targetURL.path && targetURL.anchor != "")\r
+               targetURL.path = "";\r
+\r
+       return this.serializeURL(targetURL);\r
 };\r
 \r
 TinyMCE.prototype.convertRelativeToAbsoluteURL = function(base_url, relative_url) {\r
        var baseURL = TinyMCE.prototype.parseURL(base_url);\r
        var relURL = TinyMCE.prototype.parseURL(relative_url);\r
 \r
-       if (relative_url == "" || relative_url.charAt(0) == '/' || relative_url.indexOf('://') != -1 || relative_url.indexOf('mailto:') != -1 || relative_url.indexOf('javascript:') != -1 || tinyMCE.regexpReplace(relative_url,'[ \t\r\n\+]|%20','').charAt(0) == "#")\r
+       if (relative_url == "" || relative_url.charAt(0) == '/' || relative_url.indexOf('://') != -1 || relative_url.indexOf('mailto:') != -1 || relative_url.indexOf('javascript:') != -1)\r
                return relative_url;\r
 \r
        // Split parts\r
@@ -2705,28 +3030,18 @@ TinyMCE.prototype.convertRelativeToAbsoluteURL = function(base_url, relative_url
        var absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/');\r
        var start = "", end = "";\r
 \r
-       // Build start part\r
-       if (baseURL['protocol'])\r
-               start += baseURL['protocol'] + "://";\r
-\r
-       if (baseURL['host'])\r
-               start += baseURL['host'];\r
-\r
-       if (baseURL['port'])\r
-               start += ":" + baseURL['port'];\r
-\r
-       // Build end part\r
-       if (relURL['query'])\r
-               end += "?" + relURL['query'];\r
-\r
-       if (relURL['anchor'])\r
-               end += "#" + relURL['anchor'];\r
+       // Build output URL\r
+       relURL.protocol = baseURL.protocol;\r
+       relURL.host = baseURL.host;\r
+       relURL.port = baseURL.port;\r
 \r
        // Re-add trailing slash if it's removed\r
-       if (relative_url.charAt(relative_url.length-1) == "/")\r
-               end += "/";\r
+       if (relURL.path.charAt(relURL.path.length-1) == "/")\r
+               absPath += "/";\r
+\r
+       relURL.path = absPath;\r
 \r
-       return start + absPath + end;\r
+       return TinyMCE.prototype.serializeURL(relURL);\r
 };\r
 \r
 TinyMCE.prototype.getParam = function(name, default_value, strip_whitespace, split_chr) {\r
@@ -2757,15 +3072,18 @@ TinyMCE.prototype.getParam = function(name, default_value, strip_whitespace, spl
 TinyMCE.prototype.getLang = function(name, default_value, parse_entities) {\r
        var value = (typeof(tinyMCELang[name]) == "undefined") ? default_value : tinyMCELang[name];\r
 \r
-       if (parse_entities) {\r
-               var el = document.createElement("div");\r
-               el.innerHTML = value;\r
-               value = el.innerHTML;\r
-       }\r
+       if (parse_entities)\r
+               value = tinyMCE.entityDecode(value);\r
 \r
        return value;\r
 };\r
 \r
+TinyMCE.prototype.entityDecode = function(s) {\r
+       var e = document.createElement("div");\r
+       e.innerHTML = s;\r
+       return e.innerHTML;\r
+};\r
+\r
 TinyMCE.prototype.addToLang = function(prefix, ar) {\r
        for (var key in ar) {\r
                if (typeof(ar[key]) == 'function')\r
@@ -2806,6 +3124,8 @@ TinyMCE.prototype.triggerNodeChange = function(focus, setup_content) {
                        var anySelection = false;\r
                        var selectedText = inst.getSelectedText();\r
 \r
+                       inst.switchSettings();\r
+\r
                        if (tinyMCE.settings["auto_resize"]) {\r
                                var doc = inst.getDoc();\r
 \r
@@ -2821,7 +3141,7 @@ TinyMCE.prototype.triggerNodeChange = function(focus, setup_content) {
                                undoLevels = inst.undoLevels.length;\r
                        }\r
 \r
-                       tinyMCE.executeCallback('handleNodeChangeCallback', '_handleNodeChange', 0, editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection);\r
+                       tinyMCE.executeCallback('handleNodeChangeCallback', '_handleNodeChange', 0, editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection, setup_content);\r
                }\r
        }\r
 \r
@@ -2849,8 +3169,12 @@ TinyMCE.prototype.getContent = function(editor_id) {
        if (typeof(editor_id) != "undefined")\r
                tinyMCE.selectedInstance = tinyMCE.getInstanceById(editor_id);\r
 \r
-       if (tinyMCE.selectedInstance)\r
-               return tinyMCE._cleanupHTML(this.selectedInstance, this.selectedInstance.getDoc(), tinyMCE.settings, this.selectedInstance.getBody(), false, true);\r
+       if (tinyMCE.selectedInstance) {\r
+               var old = this.selectedInstance.getBody().innerHTML;\r
+               var html = tinyMCE._cleanupHTML(this.selectedInstance, this.selectedInstance.getDoc(), tinyMCE.settings, this.selectedInstance.getBody(), false, true);\r
+               tinyMCE.setInnerHTML(this.selectedInstance.getBody(), old);\r
+               return html;\r
+       }\r
 \r
        return null;\r
 };\r
@@ -2951,7 +3275,7 @@ TinyMCE.prototype.openWindow = function(template, args) {
                win.resizeTo(width, height);\r
                win.focus();\r
        } else {\r
-               if (tinyMCE.isMSIE && resizable != 'yes' && tinyMCE.settings["dialog_type"] == "modal") {\r
+               if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && resizable != 'yes' && tinyMCE.settings["dialog_type"] == "modal") {\r
             var features = "resizable:" + resizable \r
                 + ";scroll:"\r
                 + scrollbars + ";status:yes;center:yes;help:no;dialogWidth:"\r
@@ -3025,46 +3349,49 @@ TinyMCE.prototype.getVisualAidClass = function(class_name, state) {
        return className;\r
 };\r
 \r
-TinyMCE.prototype.handleVisualAid = function(element, deep, state, inst) {\r
-       if (!element)\r
+TinyMCE.prototype.handleVisualAid = function(el, deep, state, inst) {\r
+       if (!el)\r
                return;\r
 \r
        var tableElement = null;\r
 \r
-       switch (element.nodeName) {\r
+       switch (el.nodeName) {\r
                case "TABLE":\r
-                       var oldW = element.style.width;\r
-                       var oldH = element.style.height;\r
+                       var oldW = el.style.width;\r
+                       var oldH = el.style.height;\r
+                       var bo = tinyMCE.getAttrib(el, "border");\r
+\r
+                       bo = bo == "" || bo == "0" ? true : false;\r
 \r
-                       element.className = tinyMCE.getVisualAidClass(element.className, state && element.getAttribute("border") == 0);\r
+                       tinyMCE.setAttrib(el, "class", tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el, "class"), state && bo));\r
 \r
-                       element.style.width = oldW;\r
-                       element.style.height = oldH;\r
+                       el.style.width = oldW;\r
+                       el.style.height = oldH;\r
 \r
-                       for (var y=0; y<element.rows.length; y++) {\r
-                               for (var x=0; x<element.rows[y].cells.length; x++) {\r
-                                       var className = tinyMCE.getVisualAidClass(element.rows[y].cells[x].className, state && element.getAttribute("border") == 0);\r
-                                       element.rows[y].cells[x].className = className;\r
+                       for (var y=0; y<el.rows.length; y++) {\r
+                               for (var x=0; x<el.rows[y].cells.length; x++) {\r
+                                       var cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo);\r
+                                       tinyMCE.setAttrib(el.rows[y].cells[x], "class", cn);\r
                                }\r
                        }\r
 \r
                        break;\r
 \r
                case "A":\r
-                       var anchorName = tinyMCE.getAttrib(element, "name");\r
+                       var anchorName = tinyMCE.getAttrib(el, "name");\r
 \r
                        if (anchorName != '' && state) {\r
-                               element.title = anchorName;\r
-                               element.className = 'mceItemAnchor';\r
+                               el.title = anchorName;\r
+                               el.className = 'mceItemAnchor';\r
                        } else if (anchorName != '' && !state)\r
-                               element.className = '';\r
+                               el.className = '';\r
 \r
                        break;\r
        }\r
 \r
-       if (deep && element.hasChildNodes()) {\r
-               for (var i=0; i<element.childNodes.length; i++)\r
-                       tinyMCE.handleVisualAid(element.childNodes[i], deep, state, inst);\r
+       if (deep && el.hasChildNodes()) {\r
+               for (var i=0; i<el.childNodes.length; i++)\r
+                       tinyMCE.handleVisualAid(el.childNodes[i], deep, state, inst);\r
        }\r
 };\r
 \r
@@ -3082,7 +3409,15 @@ TinyMCE.prototype.getAttrib = function(elm, name, default_value) {
        if (name == "class" && !v)\r
                v = elm.className;\r
 \r
-       if (name == "style")\r
+       // Workaround for a issue with Firefox 1.5rc2+\r
+       if (tinyMCE.isGecko && name == "src" && elm.src != null && elm.src != "")\r
+               v = elm.src;\r
+\r
+       // Workaround for a issue with Firefox 1.5rc2+\r
+       if (tinyMCE.isGecko && name == "href" && elm.href != null && elm.href != "")\r
+               v = elm.href;\r
+\r
+       if (name == "style" && !tinyMCE.isOpera)\r
                v = elm.style.cssText;\r
 \r
        return (v && v != "") ? v : default_value;\r
@@ -3112,20 +3447,254 @@ TinyMCE.prototype.setAttrib = function(element, name, value, fix_value) {
                element.removeAttribute(name);\r
 };\r
 \r
-TinyMCE.prototype._setHTML = function(doc, html_content) {\r
-       // Force closed anchors open\r
-       html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');\r
-       html_content = html_content.replace(new RegExp('<a(.*?)name="(.*?)"(.*?)>(.*?)</a>', 'gi'), '<a$1name="$2"$3></a>$4');\r
+TinyMCE.prototype.setStyleAttrib = function(elm, name, value) {\r
+       eval('elm.style.' + name + '=value;');\r
 \r
-       // Weird MSIE bug, <p><hr /></p> breaks runtime?\r
+       // Style attrib deleted\r
+       if (tinyMCE.isMSIE && value == null || value == '') {\r
+               var str = tinyMCE.serializeStyle(tinyMCE.parseStyle(elm.style.cssText));\r
+               elm.style.cssText = str;\r
+               elm.setAttribute("style", str);\r
+       }\r
+};\r
+\r
+TinyMCE.prototype.convertSpansToFonts = function(doc) {\r
+       var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');\r
+\r
+       var h = doc.body.innerHTML;\r
+       h = h.replace(/<span/gi, '<font');\r
+       h = h.replace(/<\/span/gi, '</font');\r
+       doc.body.innerHTML = h;\r
+\r
+       var s = doc.getElementsByTagName("font");\r
+       for (var i=0; i<s.length; i++) {\r
+               var size = tinyMCE.trim(s[i].style.fontSize).toLowerCase();\r
+               var fSize = 0;\r
+\r
+               for (var x=0; x<sizes.length; x++) {\r
+                       if (sizes[x] == size) {\r
+                               fSize = x + 1;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (fSize > 0) {\r
+                       tinyMCE.setAttrib(s[i], 'size', fSize);\r
+                       s[i].style.fontSize = '';\r
+               }\r
+\r
+               var fFace = s[i].style.fontFamily;\r
+               if (fFace != null && fFace != "") {\r
+                       tinyMCE.setAttrib(s[i], 'face', fFace);\r
+                       s[i].style.fontFamily = '';\r
+               }\r
+\r
+               var fColor = s[i].style.color;\r
+               if (fColor != null && fColor != "") {\r
+                       tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor));\r
+                       s[i].style.color = '';\r
+               }\r
+       }\r
+};\r
+\r
+TinyMCE.prototype.convertFontsToSpans = function(doc) {\r
+       var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');\r
+\r
+       var h = doc.body.innerHTML;\r
+       h = h.replace(/<font/gi, '<span');\r
+       h = h.replace(/<\/font/gi, '</span');\r
+       doc.body.innerHTML = h;\r
+\r
+       var fsClasses = tinyMCE.getParam('font_size_classes');\r
+       if (fsClasses != '')\r
+               fsClasses = fsClasses.replace(/\s+/, '').split(',');\r
+       else\r
+               fsClasses = null;\r
+\r
+       var s = doc.getElementsByTagName("span");\r
+       for (var i=0; i<s.length; i++) {\r
+               var fSize, fFace, fColor;\r
+\r
+               fSize = tinyMCE.getAttrib(s[i], 'size');\r
+               fFace = tinyMCE.getAttrib(s[i], 'face');\r
+               fColor = tinyMCE.getAttrib(s[i], 'color');\r
+\r
+               if (fSize != "") {\r
+                       fSize = parseInt(fSize);\r
+\r
+                       if (fSize > 0 && fSize < 8) {\r
+                               if (fsClasses != null)\r
+                                       tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]);\r
+                               else\r
+                                       s[i].style.fontSize = sizes[fSize-1];\r
+                       }\r
+\r
+                       s[i].removeAttribute('size');\r
+               }\r
+\r
+               if (fFace != "") {\r
+                       s[i].style.fontFamily = fFace;\r
+                       s[i].removeAttribute('face');\r
+               }\r
+\r
+               if (fColor != "") {\r
+                       s[i].style.color = fColor;\r
+                       s[i].removeAttribute('color');\r
+               }\r
+       }\r
+};\r
+\r
+/*\r
+TinyMCE.prototype.applyClassesToFonts = function(doc, size) {\r
+       var f = doc.getElementsByTagName("font");\r
+       for (var i=0; i<f.length; i++) {\r
+               var s = tinyMCE.getAttrib(f[i], "size");\r
+\r
+               if (s != "")\r
+                       tinyMCE.setAttrib(f[i], 'class', "mceItemFont" + s);\r
+       }\r
+\r
+       if (typeof(size) != "undefined") {\r
+               var css = "";\r
+\r
+               for (var x=0; x<doc.styleSheets.length; x++) {\r
+                       for (var i=0; i<doc.styleSheets[x].rules.length; i++) {\r
+                               if (doc.styleSheets[x].rules[i].selectorText == '#mceSpanFonts .mceItemFont' + size) {\r
+                                       css = doc.styleSheets[x].rules[i].style.cssText;\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (css != "")\r
+                               break;\r
+               }\r
+\r
+               if (doc.styleSheets[0].rules[0].selectorText == "FONT")\r
+                       doc.styleSheets[0].removeRule(0);\r
+\r
+               doc.styleSheets[0].addRule("FONT", css, 0);\r
+       }\r
+};\r
+*/\r
+\r
+TinyMCE.prototype.setInnerHTML = function(e, h) {\r
+       if (tinyMCE.isMSIE && !tinyMCE.isOpera) {\r
+               e.innerHTML = tinyMCE.uniqueTag + h;\r
+               e.firstChild.removeNode(true);\r
+       } else {\r
+               h = this.fixGeckoBaseHREFBug(1, e, h);\r
+               e.innerHTML = h;\r
+               this.fixGeckoBaseHREFBug(2, e, h);\r
+       }\r
+};\r
+\r
+TinyMCE.prototype.fixGeckoBaseHREFBug = function(m, e, h) {\r
+       if (tinyMCE.isGecko) {\r
+               if (m == 1) {\r
+                       h = h.replace(/\ssrc=/gi, " xsrc=");\r
+                       h = h.replace(/\shref=/gi, " xhref=");\r
+\r
+                       return h;\r
+               } else {\r
+                       if (h.indexOf(' xsrc') != -1) {\r
+                               var n = e.getElementsByTagName("img");\r
+                               for (var i=0; i<n.length; i++) {\r
+                                       var xsrc = tinyMCE.getAttrib(n[i], "xsrc");\r
+\r
+                                       if (xsrc != "") {\r
+                                               n[i].src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xsrc);\r
+                                               n[i].removeAttribute("xsrc");\r
+                                       }\r
+                               }\r
+\r
+                               // Select image form fields\r
+                               var n = e.getElementsByTagName("select");\r
+                               for (var i=0; i<n.length; i++) {\r
+                                       var xsrc = tinyMCE.getAttrib(n[i], "xsrc");\r
+\r
+                                       if (xsrc != "") {\r
+                                               n[i].src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xsrc);\r
+                                               n[i].removeAttribute("xsrc");\r
+                                       }\r
+                               }\r
+\r
+                               // iframes\r
+                               var n = e.getElementsByTagName("iframe");\r
+                               for (var i=0; i<n.length; i++) {\r
+                                       var xsrc = tinyMCE.getAttrib(n[i], "xsrc");\r
+\r
+                                       if (xsrc != "") {\r
+                                               n[i].src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xsrc);\r
+                                               n[i].removeAttribute("xsrc");\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       if (h.indexOf(' xhref') != -1) {\r
+                               var n = e.getElementsByTagName("a");\r
+                               for (var i=0; i<n.length; i++) {\r
+                                       var xhref = tinyMCE.getAttrib(n[i], "xhref");\r
+\r
+                                       if (xhref != "") {\r
+                                               n[i].href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xhref);\r
+                                               n[i].removeAttribute("xhref");\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       return h;\r
+};\r
+\r
+TinyMCE.prototype.getOuterHTML = function(e) {\r
+       if (tinyMCE.isMSIE)\r
+               return e.outerHTML;\r
+\r
+       var d = e.ownerDocument.createElement("body");\r
+       d.appendChild(e);\r
+       return d.innerHTML;\r
+};\r
+\r
+TinyMCE.prototype.setOuterHTML = function(doc, e, h) {\r
        if (tinyMCE.isMSIE) {\r
-               var re = new RegExp('<p><hr /></p>', 'g');\r
-               html_content = html_content.replace(re, "<hr>");\r
+               e.outerHTML = h;\r
+               return;\r
+       }\r
+\r
+       var d = e.ownerDocument.createElement("body");\r
+       d.innerHTML = h;\r
+       e.parentNode.replaceChild(d.firstChild, e);\r
+};\r
+\r
+TinyMCE.prototype.insertAfter = function(nc, rc){\r
+       if (rc.nextSibling)\r
+               rc.parentNode.insertBefore(nc, rc.nextSibling);\r
+       else\r
+               rc.parentNode.appendChild(nc);\r
+};\r
+\r
+TinyMCE.prototype.cleanupAnchors = function(doc) {\r
+       var an = doc.getElementsByTagName("a");\r
+\r
+       for (var i=0; i<an.length; i++) {\r
+               if (tinyMCE.getAttrib(an[i], "name") != "") {\r
+                       var cn = an[i].childNodes;\r
+                       for (var x=cn.length-1; x>=0; x--)\r
+                               tinyMCE.insertAfter(cn[x], an[i]);\r
+               }\r
        }\r
+};\r
+\r
+TinyMCE.prototype._setHTML = function(doc, html_content) {\r
+       // Force closed anchors open\r
+       //html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');\r
+\r
+       html_content = tinyMCE.cleanupHTMLCode(html_content);\r
 \r
        // Try innerHTML if it fails use pasteHTML in MSIE\r
        try {\r
-               doc.body.innerHTML = html_content;\r
+               tinyMCE.setInnerHTML(doc.body, html_content);\r
        } catch (e) {\r
                if (this.isMSIE)\r
                        doc.body.createTextRange().pasteHTML(html_content);\r
@@ -3138,7 +3707,7 @@ TinyMCE.prototype._setHTML = function(doc, html_content) {
                for (var i=0; i<paras.length; i++) {\r
                        var node = paras[i];\r
                        while ((node = node.parentNode) != null) {\r
-                               if (node.nodeName.toLowerCase() == "p")\r
+                               if (node.nodeName == "P")\r
                                        node.outerHTML = node.innerHTML;\r
                        }\r
                }\r
@@ -3165,8 +3734,13 @@ TinyMCE.prototype._setHTML = function(doc, html_content) {
                }\r
 \r
                // Always set the htmlText output\r
-               doc.body.innerHTML = html;\r
+               tinyMCE.setInnerHTML(doc.body, html);\r
        }\r
+\r
+       tinyMCE.cleanupAnchors(doc);\r
+\r
+       if (tinyMCE.getParam("convert_fonts_to_spans"))\r
+               tinyMCE.convertSpansToFonts(doc);\r
 };\r
 \r
 TinyMCE.prototype.getImageSrc = function(str) {\r
@@ -3216,7 +3790,7 @@ TinyMCE.prototype.getInstanceById = function(editor_id) {
        if (!inst) {\r
                for (var n in tinyMCE.instances) {\r
                        var instance = tinyMCE.instances[n];\r
-                       if (typeof(instance) == 'function')\r
+                       if (!tinyMCE.isInstance(instance))\r
                                continue;\r
 \r
                        if (instance.formTargetElementId == editor_id) {\r
@@ -3265,7 +3839,7 @@ TinyMCE.prototype.getCSSClasses = function(editor_id, doc) {
 \r
                for (var instanceName in tinyMCE.instances) {\r
                        instance = tinyMCE.instances[instanceName];\r
-                       if (typeof(instance) == 'function')\r
+                       if (!tinyMCE.isInstance(instance))\r
                                continue;\r
 \r
                        break;\r
@@ -3325,6 +3899,9 @@ TinyMCE.prototype.getCSSClasses = function(editor_id, doc) {
 };\r
 \r
 TinyMCE.prototype.regexpReplace = function(in_str, reg_exp, replace_str, opts) {\r
+       if (in_str == null)\r
+               return in_str;\r
+\r
        if (typeof(opts) == "undefined")\r
                opts = 'g';\r
 \r
@@ -3340,7 +3917,7 @@ TinyMCE.prototype.cleanupEventStr = function(str) {
        str = "" + str;\r
        str = str.replace('function anonymous()\n{\n', '');\r
        str = str.replace('\n}', '');\r
-       str = str.replace(/^return true;/gi, '');\r
+       str = str.replace(/^return true;/gi, ''); // Remove event blocker\r
 \r
        return str;\r
 };\r
@@ -3513,7 +4090,7 @@ TinyMCE.prototype.debug = function() {
                debugDiv.className = "debugger";\r
                debugDiv.innerHTML = '\\r
                        Debug output:\\r
-                       <textarea id="tinymce_debug" style="width: 100%; height: 300px"></textarea>';\r
+                       <textarea id="tinymce_debug" style="width: 100%; height: 300px" wrap="nowrap"></textarea>';\r
 \r
                document.body.appendChild(debugDiv);\r
                elm = document.getElementById("tinymce_debug");\r
@@ -3536,6 +4113,7 @@ function TinyMCEControl(settings) {
        this.undoIndex = 0;\r
        this.typingUndoIndex = -1;\r
        this.undoRedo = true;\r
+       this.isTinyMCEControl = true;\r
 \r
        // Default settings\r
        this.settings = settings;\r
@@ -3545,11 +4123,18 @@ function TinyMCEControl(settings) {
 };\r
 \r
 TinyMCEControl.prototype.repaint = function() {\r
-       if (tinyMCE.isMSIE)\r
+       if (tinyMCE.isMSIE && !tinyMCE.isOpera)\r
                return;\r
 \r
-       this.getBody().style.display = 'none';\r
-       this.getBody().style.display = 'block';\r
+       // Ugly mozilla hack to remove ghost resize handles\r
+       try {\r
+               this.getBody().style.display = 'none';\r
+               this.getDoc().execCommand('selectall', false, null);\r
+               this.getSel().collapseToStart();\r
+               this.getBody().style.display = 'block';\r
+       } catch (ex) {\r
+               // Could I care less!!\r
+       }\r
 };\r
 \r
 TinyMCEControl.prototype.switchSettings = function() {\r
@@ -3559,46 +4144,36 @@ TinyMCEControl.prototype.switchSettings = function() {
        }\r
 };\r
 \r
-TinyMCEControl.prototype.fixBrokenURLs = function() {\r
-       var body = this.getBody();\r
-\r
-       var elms = body.getElementsByTagName("img");\r
-       for (var i=0; i<elms.length; i++) {\r
-               var src = elms[i].getAttribute('mce_real_src');\r
-               if (src && src != "")\r
-                       elms[i].setAttribute("src", src);\r
-       }\r
-\r
-       var elms = body.getElementsByTagName("a");\r
-       for (var i=0; i<elms.length; i++) {\r
-               var href = elms[i].getAttribute('mce_real_href');\r
-               if (href && href != "")\r
-                       elms[i].setAttribute("href", href);\r
-       }\r
-};\r
-\r
 TinyMCEControl.prototype.convertAllRelativeURLs = function() {\r
        var body = this.getBody();\r
 \r
        // Convert all image URL:s to absolute URL\r
        var elms = body.getElementsByTagName("img");\r
        for (var i=0; i<elms.length; i++) {\r
-               var src = elms[i].getAttribute('src');\r
-               if (src && src != "") {\r
+               var src = tinyMCE.getAttrib(elms[i], 'src');\r
+\r
+               var msrc = tinyMCE.getAttrib(elms[i], 'mce_src');\r
+               if (msrc != "")\r
+                       src = msrc;\r
+\r
+               if (src != "") {\r
                        src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src);\r
                        elms[i].setAttribute("src", src);\r
-                       elms[i].setAttribute("mce_real_src", src);\r
                }\r
        }\r
 \r
        // Convert all link URL:s to absolute URL\r
        var elms = body.getElementsByTagName("a");\r
        for (var i=0; i<elms.length; i++) {\r
-               var href = elms[i].getAttribute('href');\r
+               var href = tinyMCE.getAttrib(elms[i], 'href');\r
+\r
+               var mhref = tinyMCE.getAttrib(elms[i], 'mce_href');\r
+               if (mhref != "")\r
+                       href = mhref;\r
+\r
                if (href && href != "") {\r
                        href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], href);\r
                        elms[i].setAttribute("href", href);\r
-                       elms[i].setAttribute("mce_real_href", href);\r
                }\r
        }\r
 };\r
@@ -3773,8 +4348,8 @@ TinyMCEControl.prototype.scrollToNode = function(node) {
        var height = tinyMCE.isMSIE ? document.getElementById(this.editorId).style.pixelHeight : this.targetElement.clientHeight;\r
 \r
        // Only scroll if out of visible area\r
-       if (!tinyMCE.settings['auto_resize'] && !(node.absTop > scrollY && node.absTop < (scrollY - 25 + height)))\r
-               this.contentWindow.scrollTo(pos.absLeft, pos.absTop - height + 25);\r
+       if (!tinyMCE.settings['auto_resize'] && !(pos.absTop > scrollY && pos.absTop < (scrollY - 25 + height)))\r
+               this.contentWindow.scrollTo(pos.absLeft, pos.absTop - height + 25); \r
 };\r
 \r
 TinyMCEControl.prototype.getBody = function() {\r
@@ -3790,7 +4365,7 @@ TinyMCEControl.prototype.getWin = function() {
 };\r
 \r
 TinyMCEControl.prototype.getSel = function() {\r
-       if (tinyMCE.isMSIE)\r
+       if (tinyMCE.isMSIE && !tinyMCE.isOpera)\r
                return this.getDoc().selection;\r
 \r
        var sel = this.contentWindow.getSelection();\r
@@ -3849,7 +4424,7 @@ TinyMCEControl.prototype.getRng = function() {
        if (sel == null)\r
                return null;\r
 \r
-       if (tinyMCE.isMSIE)\r
+       if (tinyMCE.isMSIE && !tinyMCE.isOpera)\r
                return sel.createRange();\r
 \r
        if (tinyMCE.isSafari) {\r
@@ -3942,8 +4517,8 @@ TinyMCEControl.prototype._insertPara = function(e) {
                        blockName = "P";\r
        }\r
 \r
-       // Within a list item (use normal behavior)\r
-       if ((startBlock != null && startBlock.nodeName == "LI") || (endBlock != null && endBlock.nodeName == "LI"))\r
+       // Within a list use normal behaviour\r
+       if (tinyMCE.getParentElement(startBlock, "OL,UL") != null)\r
                return false;\r
 \r
        // Within a table create new paragraphs\r
@@ -3951,8 +4526,12 @@ TinyMCEControl.prototype._insertPara = function(e) {
                startBlock = endBlock = null;\r
 \r
        // Setup new paragraphs\r
-       var paraBefore = (startBlock != null && startBlock.nodeName.toUpperCase() == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName);\r
-       var paraAfter = (endBlock != null && endBlock.nodeName.toUpperCase() == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName);\r
+       var paraBefore = (startBlock != null && startBlock.nodeName == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName);\r
+       var paraAfter = (endBlock != null && endBlock.nodeName == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName);\r
+\r
+       // Is header, then force paragraph under\r
+       if (/^(H[1-6])$/.test(blockName))\r
+               paraAfter = doc.createElement("p");\r
 \r
        // Setup chop nodes\r
        var startChop = startNode;\r
@@ -4004,18 +4583,17 @@ TinyMCEControl.prototype._insertPara = function(e) {
                        if (endChop.parentNode.nodeName == blockName)\r
                                endChop = endChop.parentNode;\r
 \r
-                       rng.setEndAfter(endChop);\r
+                       // If not after image\r
+                       //if (rng.startContainer.nodeName != "BODY" && rng.endContainer.nodeName != "BODY")\r
+                               rng.setEndAfter(endChop);\r
+\r
                        if (endChop.nodeName != "#text" && endChop.nodeName != "BODY")\r
                                rngBefore.setEndAfter(endChop);\r
 \r
                        var contents = rng.cloneContents();\r
-                       if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName == "BODY")) {\r
-                               var nodes = contents.firstChild.childNodes;\r
-                               for (var i=0; i<nodes.length; i++) {\r
-                                       if (nodes[i].nodeName != "BODY")\r
-                                               paraAfter.appendChild(nodes[i]);\r
-                               }\r
-                       } else\r
+                       if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName == "BODY"))\r
+                               paraAfter.innerHTML = contents.firstChild.innerHTML;\r
+                       else\r
                                paraAfter.appendChild(contents);\r
 \r
                        // Check if it's a empty paragraph\r
@@ -4037,7 +4615,7 @@ TinyMCEControl.prototype._insertPara = function(e) {
                        paraBefore.normalize();\r
                        rngBefore.insertNode(paraBefore);\r
 \r
-//                     tinyMCE.debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML);\r
+                       // tinyMCE.debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML);\r
                } else {\r
                        body.innerHTML = "<" + blockName + ">&nbsp;</" + blockName + "><" + blockName + ">&nbsp;</" + blockName + ">";\r
                        paraAfter = body.childNodes[1];\r
@@ -4053,6 +4631,7 @@ TinyMCEControl.prototype._insertPara = function(e) {
                rngBefore.setStart(startChop, 0);\r
        else\r
                rngBefore.setStartBefore(startChop);\r
+\r
        rngBefore.setEnd(startNode, startOffset);\r
        paraBefore.appendChild(rngBefore.cloneContents());\r
 \r
@@ -4060,12 +4639,16 @@ TinyMCEControl.prototype._insertPara = function(e) {
        rngAfter.setEndAfter(endChop);\r
        rngAfter.setStart(endNode, endOffset);\r
        var contents = rngAfter.cloneContents();\r
+\r
        if (contents.firstChild && contents.firstChild.nodeName == blockName) {\r
-               var nodes = contents.firstChild.childNodes;\r
+/*             var nodes = contents.firstChild.childNodes;\r
                for (var i=0; i<nodes.length; i++) {\r
-                       if (nodes[i].nodeName.toLowerCase() != "body")\r
+                       //tinyMCE.debug(nodes[i].nodeName);\r
+                       if (nodes[i].nodeName != "BODY")\r
                                paraAfter.appendChild(nodes[i]);\r
                }\r
+*/\r
+               paraAfter.innerHTML = contents.firstChild.innerHTML;\r
        } else\r
                paraAfter.appendChild(contents);\r
 \r
@@ -4098,7 +4681,7 @@ TinyMCEControl.prototype._insertPara = function(e) {
        rng.deleteContents();\r
        rng.insertNode(paraAfter);\r
        rng.insertNode(paraBefore);\r
-       // debug("2", paraBefore.innerHTML, paraAfter.innerHTML);\r
+       //tinyMCE.debug("2", paraBefore.innerHTML, paraAfter.innerHTML);\r
 \r
        // Normalize\r
        paraAfter.normalize();\r
@@ -4192,13 +4775,18 @@ TinyMCEControl.prototype._insertSpace = function() {
 \r
 TinyMCEControl.prototype.autoResetDesignMode = function() {\r
        // Add fix for tab/style.display none/block problems in Gecko\r
-       if (!tinyMCE.isMSIE && tinyMCE.settings['auto_reset_designmode']) {\r
-               var sel = this.getSel();\r
+       if (!tinyMCE.isMSIE && tinyMCE.settings['auto_reset_designmode'] && this.isHidden())\r
+               eval('try { this.getDoc().designMode = "On"; } catch(e) {}');\r
+};\r
 \r
-               // Weird, wheres that cursor selection?\r
-               if (!sel || !sel.rangeCount || sel.rangeCount == 0)\r
-                       eval('try { this.getDoc().designMode = "On"; } catch(e) {}');\r
-       }\r
+TinyMCEControl.prototype.isHidden = function() {\r
+       if (tinyMCE.isMSIE)\r
+               return false;\r
+\r
+       var sel = this.getSel();\r
+\r
+       // Weird, wheres that cursor selection?\r
+       return (!sel || !sel.rangeCount || sel.rangeCount == 0);\r
 };\r
 \r
 TinyMCEControl.prototype.isDirty = function() {\r
@@ -4245,6 +4833,18 @@ TinyMCEControl.prototype._mergeElements = function(scmd, pa, ch, override) {
        ch.removeAttribute("style");\r
 };\r
 \r
+TinyMCEControl.prototype.setUseCSS = function(b) {\r
+       var doc = this.getDoc();\r
+       try {doc.execCommand("useCSS", false, !b);} catch (ex) {}\r
+       try {doc.execCommand("styleWithCSS", false, b);} catch (ex) {}\r
+\r
+       if (!tinyMCE.getParam("table_inline_editing"))\r
+               try {doc.execCommand('enableInlineTableEditing', false, "false");} catch (ex) {}\r
+\r
+       if (!tinyMCE.getParam("object_resizing"))\r
+               try {doc.execCommand('enableObjectResizing', false, "false");} catch (ex) {}\r
+};\r
+\r
 TinyMCEControl.prototype.execCommand = function(command, user_interface, value) {\r
        var doc = this.getDoc();\r
        var win = this.getWin();\r
@@ -4257,8 +4857,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
 \r
        // Mozilla issue\r
        if (!tinyMCE.isMSIE && !this.useCSS) {\r
-               try {doc.execCommand("styleWithCSS", false, false);} catch (ex) {}\r
-               try {doc.execCommand("useCSS", false, true);} catch (ex) {}\r
+               this.setUseCSS(false);\r
                this.useCSS = true;\r
        }\r
 \r
@@ -4467,10 +5066,12 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                        var sel = this.getSel();\r
                        var scmd = value['command'];\r
                        var sname = value['name'];\r
-                       var svalue = value['value'];\r
+                       var svalue = value['value'] == null ? '' : value['value'];\r
+                       //var svalue = value['value'] == null ? '' : value['value'];\r
                        var wrapper = value['wrapper'] ? value['wrapper'] : "span";\r
                        var parentElm = null;\r
                        var invalidRe = new RegExp("^BODY|HTML$", "g");\r
+                       var invalidParentsRe = tinyMCE.settings['merge_styles_invalid_parents'] != '' ? new RegExp(tinyMCE.settings['merge_styles_invalid_parents'], "gi") : null;\r
 \r
                        // Whole element selected check\r
                        if (tinyMCE.isMSIE) {\r
@@ -4482,8 +5083,10 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                        var prng = doc.selection.createRange();\r
                                        prng.moveToElementText(pelm);\r
 \r
-                                       if (rng.htmlText == prng.htmlText || rng.boundingWidth == 0)\r
-                                               parentElm = pelm;\r
+                                       if (rng.htmlText == prng.htmlText || rng.boundingWidth == 0) {\r
+                                               if (invalidParentsRe == null || !invalidParentsRe.test(pelm.nodeName))\r
+                                                       parentElm = pelm;\r
+                                       }\r
                                }\r
                        } else {\r
                                var felm = this.getFocusElement();\r
@@ -4494,7 +5097,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                        // Whole element selected\r
                        if (parentElm && !invalidRe.test(parentElm.nodeName)) {\r
                                if (scmd == "setstyle")\r
-                                       eval("parentElm.style." + sname + " = svalue;");\r
+                                       tinyMCE.setStyleAttrib(parentElm, sname, svalue);\r
 \r
                                if (scmd == "setattrib")\r
                                        tinyMCE.setAttrib(parentElm, sname, svalue);\r
@@ -4511,7 +5114,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                                continue;\r
 \r
                                        if (scmd == "setstyle")\r
-                                               eval("ch[z].style." + sname + " = '';");\r
+                                               tinyMCE.setStyleAttrib(ch[z], sname, '');\r
 \r
                                        if (scmd == "setattrib")\r
                                                tinyMCE.setAttrib(ch[z], sname, '');\r
@@ -4532,7 +5135,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                                var spanElm = doc.createElement(wrapper);\r
 \r
                                                if (scmd == "setstyle")\r
-                                                       eval("spanElm.style." + sname + " = svalue;");\r
+                                                       tinyMCE.setStyleAttrib(spanElm, sname, svalue);\r
 \r
                                                if (scmd == "setattrib")\r
                                                        tinyMCE.setAttrib(spanElm, sname, svalue);\r
@@ -4557,7 +5160,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                                                continue;\r
 \r
                                                        if (scmd == "setstyle")\r
-                                                               eval("ch[z].style." + sname + " = '';");\r
+                                                               tinyMCE.setStyleAttrib(ch[z], sname, '');\r
 \r
                                                        if (scmd == "setattrib")\r
                                                                tinyMCE.setAttrib(ch[z], sname, '');\r
@@ -4589,7 +5192,8 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                // Is I the only child\r
                                if (elm.parentNode.childNodes.length == 1 && !invalidRe.test(elm.nodeName) && !invalidRe.test(elm.parentNode.nodeName)) {\r
                                        //tinyMCE.debug("merge2" + isNew + "," + elm.nodeName + "," + elm.parentNode.nodeName);\r
-                                       this._mergeElements(scmd, elm.parentNode, elm, false);\r
+                                       if (invalidParentsRe == null || !invalidParentsRe.test(elm.parentNode.nodeName))\r
+                                               this._mergeElements(scmd, elm.parentNode, elm, false);\r
                                }\r
                        }\r
 \r
@@ -4604,7 +5208,8 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                tmp.appendChild(elm.cloneNode(false));\r
 \r
                                // Is empty span, remove it\r
-                               tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style|class=""', 'gi'), '');\r
+                               tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style=""|class=""', 'gi'), '');\r
+                               //tinyMCE.debug(tmp.innerHTML);\r
                                if (new RegExp('<span>', 'gi').test(tmp.innerHTML)) {\r
                                        for (var x=0; x<elm.childNodes.length; x++) {\r
                                                if (elm.parentNode != null)\r
@@ -4624,48 +5229,54 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                        break;\r
 \r
                case "FontName":\r
-                       if (tinyMCE.getParam("convert_fonts_to_styles"))\r
-                               this.execCommand("SetStyleInfo", false, {command : "setstyle", name : "fontFamily", value : value});\r
-                       else\r
+                       if (value == null) {\r
+                               var s = this.getSel();\r
+\r
+                               // Find font and select it\r
+                               if (tinyMCE.isGecko && s.isCollapsed) {\r
+                                       var f = tinyMCE.getParentElement(this.getFocusElement(), "font");\r
+\r
+                                       if (f != null)\r
+                                               this.selectNode(f, false);\r
+                               }\r
+\r
+                               // Remove format\r
+                               this.getDoc().execCommand("RemoveFormat", false, null);\r
+\r
+                               // Collapse range if font was found\r
+                               if (f != null && tinyMCE.isGecko) {\r
+                                       var r = this.getRng().cloneRange();\r
+                                       r.collapse(true);\r
+                                       s.removeAllRanges();\r
+                                       s.addRange(r);\r
+                               }\r
+                       } else\r
                                this.getDoc().execCommand('FontName', false, value);\r
-                       break;\r
+\r
+                       if (tinyMCE.isGecko)\r
+                               window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
+\r
+                       return;\r
 \r
                case "FontSize":\r
-                       if (tinyMCE.getParam("convert_fonts_to_styles")) {\r
-                               var sizes = new Array('', 8, 10, 12, 14, 18, 24, 36);\r
-                               var size = sizes[value] == '' ? '' : sizes[value] + 'px';\r
+                       this.getDoc().execCommand('FontSize', false, value);\r
 \r
-                               this.execCommand("SetStyleInfo", false, {command : "setstyle", name : "fontSize", value : size});\r
-                       } else\r
-                               this.getDoc().execCommand('FontSize', false, value);\r
+                       if (tinyMCE.isGecko)\r
+                               window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
 \r
-                       break;\r
+                       return;\r
 \r
                case "forecolor":\r
-                       if (tinyMCE.getParam("convert_fonts_to_styles"))\r
-                               this.execCommand("SetStyleInfo", false, {command : "setstyle", name : "color", value : value});\r
-                       else {\r
-                               if (tinyMCE.isGecko) {\r
-                                       this.getDoc().execCommand("useCSS", false, true);\r
-                                       this.getDoc().execCommand('forecolor', false, value);\r
-                                       this.getDoc().execCommand("useCSS", false, true);\r
-                               } else\r
-                                       this.getDoc().execCommand('forecolor', false, value);\r
-                       }\r
+                       this.getDoc().execCommand('forecolor', false, value);\r
                        break;\r
 \r
                case "HiliteColor":\r
-                       if (tinyMCE.getParam("convert_fonts_to_styles"))\r
-                               this.execCommand("SetStyleInfo", false, {command : "setstyle", name : "backgroundColor", value : value});\r
-                       else {\r
-                               if (tinyMCE.isGecko) {\r
-                                       this.getDoc().execCommand("useCSS", false, false);\r
-                                       this.getDoc().execCommand('hilitecolor', false, value);\r
-                                       this.getDoc().execCommand("useCSS", false, true);\r
-                               } else\r
-                                       this.getDoc().execCommand('BackColor', false, value);\r
-                       }\r
-\r
+                       if (tinyMCE.isGecko) {\r
+                               this.setUseCSS(true);\r
+                               this.getDoc().execCommand('hilitecolor', false, value);\r
+                               this.setUseCSS(false);\r
+                       } else\r
+                               this.getDoc().execCommand('BackColor', false, value);\r
                        break;\r
 \r
                case "Cut":\r
@@ -4676,6 +5287,9 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                        // Try executing command\r
                        eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}');\r
 \r
+                       if (tinyMCE.isOpera && cmdFailed)\r
+                               alert('Currently not supported by your browser, use keyboard shortcuts instead.');\r
+\r
                        // Alert error in gecko if command failed\r
                        if (tinyMCE.isGecko && cmdFailed) {\r
                                // Confirm more info\r
@@ -4692,11 +5306,13 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                value = "";\r
 \r
                        // Call custom cleanup code\r
+                       value = tinyMCE.storeAwayURLs(value);\r
                        value = tinyMCE._customCleanup(this, "insert_to_editor", value);\r
                        tinyMCE._setHTML(doc, value);\r
-                       doc.body.innerHTML = tinyMCE._cleanupHTML(this, doc, tinyMCE.settings, doc.body);\r
+                       tinyMCE.setInnerHTML(doc.body, tinyMCE._cleanupHTML(this, doc, tinyMCE.settings, doc.body));\r
+                       this.convertAllRelativeURLs();\r
                        tinyMCE.handleVisualAid(doc.body, true, this.visualAid, this);\r
-                       tinyMCE._setEventsEnabled(doc.body, true);\r
+                       tinyMCE._setEventsEnabled(doc.body, false);\r
                        return true;\r
 \r
                case "mceLink":\r
@@ -4735,12 +5351,17 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
 \r
                                onclick = tinyMCE.cleanupEventStr(onclick);\r
 \r
-                               // Fix for drag-drop/copy paste bug in Mozilla\r
-                               mceRealHref = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_real_href');\r
-                               if (mceRealHref != "")\r
+                               href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);");\r
+\r
+                               // Use mce_href if defined\r
+                               mceRealHref = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_href');\r
+                               if (mceRealHref != "") {\r
                                        href = mceRealHref;\r
 \r
-                               href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);");\r
+                                       if (tinyMCE.getParam('convert_urls'))\r
+                                               href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);");\r
+                               }\r
+\r
                                action = "update";\r
                        }\r
 \r
@@ -4749,7 +5370,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                if (returnVal && returnVal['href'])\r
                                        tinyMCE.insertLink(returnVal['href'], returnVal['target'], returnVal['title'], returnVal['onclick'], returnVal['style_class']);\r
                        } else {\r
-                               tinyMCE.openWindow(this.insertLinkTemplate, {href : href, target : target, title : title, onclick : onclick, action : action, className : style_class});\r
+                               tinyMCE.openWindow(this.insertLinkTemplate, {href : href, target : target, title : title, onclick : onclick, action : action, className : style_class, inline : "yes"});\r
                        }\r
                break;\r
 \r
@@ -4805,12 +5426,16 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                onmouseover = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseover));\r
                                onmouseout = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseout));\r
 \r
-                               // Fix for drag-drop/copy paste bug in Mozilla\r
-                               mceRealSrc = tinyMCE.getAttrib(img, 'mce_real_src');\r
-                               if (mceRealSrc != "")\r
+                               src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");\r
+\r
+                               // Use mce_src if defined\r
+                               mceRealSrc = tinyMCE.getAttrib(img, 'mce_src');\r
+                               if (mceRealSrc != "") {\r
                                        src = mceRealSrc;\r
 \r
-                               src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");\r
+                                       if (tinyMCE.getParam('convert_urls'))\r
+                                               src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");\r
+                               }\r
 \r
                                if (onmouseover != "")\r
                                        onmouseover = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, img, true);");\r
@@ -4826,19 +5451,22 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                if (returnVal && returnVal['src'])\r
                                        tinyMCE.insertImage(returnVal['src'], returnVal['alt'], returnVal['border'], returnVal['hspace'], returnVal['vspace'], returnVal['width'], returnVal['height'], returnVal['align'], returnVal['title'], returnVal['onmouseover'], returnVal['onmouseout']);\r
                        } else\r
-                               tinyMCE.openWindow(this.insertImageTemplate, {src : src, alt : alt, border : border, hspace : hspace, vspace : vspace, width : width, height : height, align : align, title : title, onmouseover : onmouseover, onmouseout : onmouseout, action : action});\r
+                               tinyMCE.openWindow(this.insertImageTemplate, {src : src, alt : alt, border : border, hspace : hspace, vspace : vspace, width : width, height : height, align : align, title : title, onmouseover : onmouseover, onmouseout : onmouseout, action : action, inline : "yes"});\r
                break;\r
 \r
                case "mceCleanup":\r
                        tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML);\r
-                       this.getBody().innerHTML = tinyMCE._cleanupHTML(this, this.contentDocument, this.settings, this.getBody(), this.visualAid);\r
+                       tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, this.contentDocument, this.settings, this.getBody(), this.visualAid));\r
+                       this.convertAllRelativeURLs();\r
                        tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);\r
-                       tinyMCE._setEventsEnabled(this.getBody(), true);\r
+                       tinyMCE._setEventsEnabled(this.getBody(), false);\r
                        this.repaint();\r
                        tinyMCE.triggerNodeChange();\r
                break;\r
 \r
                case "mceReplaceContent":\r
+                       this.getWin().focus();\r
+\r
                        var selectedText = "";\r
 \r
                        if (tinyMCE.isMSIE) {\r
@@ -4886,7 +5514,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                        // Find marker and replace with RAW HTML\r
                        var html = this.getBody().innerHTML;\r
                        if ((pos = html.indexOf(key)) != -1)\r
-                               this.getBody().innerHTML = html.substring(0, pos) + value + html.substring(pos + key.length);\r
+                               tinyMCE.setInnerHTML(this.getBody(), html.substring(0, pos) + value + html.substring(pos + key.length));\r
 \r
                        // Restore scoll pos\r
                        this.contentWindow.scrollTo(scrollX, scrollY);\r
@@ -4896,10 +5524,55 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                        break;\r
 \r
                case "mceInsertContent":\r
+                       var insertHTMLFailed = false;\r
+                       this.getWin().focus();\r
+\r
+                       if (tinyMCE.isGecko || tinyMCE.isOpera) {\r
+                               try {\r
+                                       // Is plain text or HTML\r
+                                       if (value.indexOf('<') == -1) {\r
+                                               var r = this.getRng();\r
+                                               var n = this.getDoc().createTextNode(tinyMCE.entityDecode(value));\r
+                                               var s = this.getSel();\r
+                                               var r2 = r.cloneRange();\r
+\r
+                                               // Insert text at cursor position\r
+                                               s.removeAllRanges();\r
+                                               r.deleteContents();\r
+                                               r.insertNode(n);\r
+\r
+                                               // Move the cursor to the end of text\r
+                                               r2.selectNode(n);\r
+                                               r2.collapse(false);\r
+                                               s.removeAllRanges();\r
+                                               s.addRange(r2);\r
+                                       } else {\r
+                                               value = tinyMCE.fixGeckoBaseHREFBug(1, this.getDoc(), value);\r
+                                               this.getDoc().execCommand('inserthtml', false, value);\r
+                                               tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);\r
+                                       }\r
+                               } catch (ex) {\r
+                                       insertHTMLFailed = true;\r
+                               }\r
+\r
+                               if (!insertHTMLFailed) {\r
+                                       tinyMCE.triggerNodeChange();\r
+                                       return;\r
+                               }\r
+                       }\r
+\r
+                       // Ugly hack in Opera due to non working "inserthtml"\r
+                       if (tinyMCE.isOpera && insertHTMLFailed) {\r
+                               this.getDoc().execCommand("insertimage", false, tinyMCE.uniqueURL);\r
+                               var ar = tinyMCE.getElementsByAttributeValue(this.getBody(), "img", "src", tinyMCE.uniqueURL);\r
+                               ar[0].outerHTML = value;\r
+                               return;\r
+                       }\r
+\r
                        if (!tinyMCE.isMSIE) {\r
+                               var isHTML = value.indexOf('<') != -1;\r
                                var sel = this.getSel();\r
                                var rng = this.getRng();\r
-                               var isHTML = value.indexOf('<') != -1;\r
 \r
                                if (isHTML) {\r
                                        if (tinyMCE.isSafari) {\r
@@ -4956,11 +5629,22 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                        rng.collapse(false);\r
                        } else {\r
                                var rng = doc.selection.createRange();\r
+                               var c = value.indexOf('<!--') != -1;\r
+\r
+                               // Fix comment bug, add tag before comments\r
+                               if (c)\r
+                                       value = tinyMCE.uniqueTag + value;\r
 \r
                                if (rng.item)\r
                                        rng.item(0).outerHTML = value;\r
                                else\r
                                        rng.pasteHTML(value);\r
+\r
+                               // Remove unique tag\r
+                               if (c) {\r
+                                       var e = this.getDoc().getElementById('mceTMPElement');\r
+                                       e.parentNode.removeChild(e);\r
+                               }\r
                        }\r
 \r
                        tinyMCE.triggerNodeChange();\r
@@ -5002,8 +5686,6 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
 \r
                                var newHTML = tinyMCE.trim(this.getBody().innerHTML);\r
                                if (newHTML != this.undoLevels[this.undoIndex]) {\r
-                                       // tinyMCE.debug("[" + newHTML + "," + this.undoLevels[this.undoIndex] + "]");\r
-\r
                                        tinyMCE.executeCallback('onchange_callback', '_onchange', 0, this);\r
 \r
                                        // Time to compress\r
@@ -5037,7 +5719,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                // Do undo\r
                                if (this.undoIndex > 0) {\r
                                        this.undoIndex--;\r
-                                       this.getBody().innerHTML = this.undoLevels[this.undoIndex];\r
+                                       tinyMCE.setInnerHTML(this.getBody(), this.undoLevels[this.undoIndex]);\r
                                        this.repaint();\r
                                }\r
 \r
@@ -5053,7 +5735,7 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
 \r
                                if (this.undoIndex < (this.undoLevels.length-1)) {\r
                                        this.undoIndex++;\r
-                                       this.getBody().innerHTML = this.undoLevels[this.undoIndex];\r
+                                       tinyMCE.setInnerHTML(this.getBody(), this.undoLevels[this.undoIndex]);\r
                                        this.repaint();\r
                                        // tinyMCE.debug("Redo - undo levels:" + this.undoLevels.length + ", undo index: " + this.undoIndex);\r
                                }\r
@@ -5079,13 +5761,18 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
                                                n.removeAttribute("dir");\r
                                                n.removeAttribute("style");\r
                                        }\r
-                               } while (n = n.parentNode);\r
+                               } while (n != null && (n = n.parentNode) != null);\r
                        }\r
                        break;\r
 \r
                case "removeformat":\r
                        var text = this.getSelectedText();\r
 \r
+                       if (tinyMCE.isOpera) {\r
+                               this.getDoc().execCommand("RemoveFormat", false, null);\r
+                               return;\r
+                       }\r
+\r
                        if (tinyMCE.isMSIE) {\r
                                try {\r
                                        var rng = doc.selection.createRange();\r
@@ -5110,7 +5797,11 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
 \r
                default:\r
                        this.getDoc().execCommand(command, user_interface, value);\r
-                       tinyMCE.triggerNodeChange();\r
+\r
+                       if (tinyMCE.isGecko)\r
+                               window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
+                       else\r
+                               tinyMCE.triggerNodeChange();\r
        }\r
 \r
        // Add undo level after modification\r
@@ -5119,7 +5810,11 @@ TinyMCEControl.prototype.execCommand = function(command, user_interface, value)
 };\r
 \r
 TinyMCEControl.prototype.queryCommandValue = function(command) {\r
-       return this.getDoc().queryCommandValue(command);\r
+       try {\r
+               return this.getDoc().queryCommandValue(command);\r
+       } catch (ex) {\r
+               return null;\r
+       }\r
 };\r
 \r
 TinyMCEControl.prototype.queryCommandState = function(command) {\r
@@ -5263,7 +5958,11 @@ TinyMCEControl.prototype.onAdd = function(replace_element, form_element_name, ta
                        rng.setStartBefore(replace_element);\r
 \r
                        var fragment = rng.createContextualFragment(html);\r
-                       replace_element.parentNode.insertBefore(fragment, replace_element);\r
+\r
+                       if (tinyMCE.isGecko)\r
+                               tinyMCE.insertAfter(fragment, replace_element);\r
+                       else\r
+                               replace_element.parentNode.insertBefore(fragment, replace_element);\r
                } else\r
                        replace_element.insertAdjacentHTML("beforeBegin", html);\r
        }\r
@@ -5292,18 +5991,28 @@ TinyMCEControl.prototype.onAdd = function(replace_element, form_element_name, ta
 \r
                this.targetElement = tElm;\r
                this.iframeElement = targetDoc.getElementById(this.editorId);\r
-               this.contentDocument = tElm.window.document;\r
-               this.contentWindow = tElm.window;\r
+\r
+               if (tinyMCE.isOpera) {\r
+                       this.contentDocument = this.iframeElement.contentDocument;\r
+                       this.contentWindow = this.iframeElement.contentWindow;\r
+                       dynamicIFrame = true;\r
+               } else {\r
+                       this.contentDocument = tElm.window.document;\r
+                       this.contentWindow = tElm.window;\r
+               }\r
+\r
                this.getDoc().designMode = "on";\r
        }\r
 \r
        // Setup base HTML\r
        var doc = this.contentDocument;\r
        if (dynamicIFrame) {\r
-        var html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><base href="' + tinyMCE.settings['base_href'] + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>';\r
+               var html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings['base_href'] + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>';\r
 \r
                try {\r
-                       this.getDoc().designMode = "on";\r
+                       if (!this.isHidden())\r
+                               this.getDoc().designMode = "on";\r
+\r
                        doc.open();\r
                        doc.write(html);\r
                        doc.close();\r
@@ -5324,17 +6033,21 @@ TinyMCEControl.prototype.onAdd = function(replace_element, form_element_name, ta
 };\r
 \r
 TinyMCEControl.prototype.getFocusElement = function() {\r
-       if (tinyMCE.isMSIE) {\r
+       if (tinyMCE.isMSIE && !tinyMCE.isOpera) {\r
                var doc = this.getDoc();\r
                var rng = doc.selection.createRange();\r
 \r
-               if (rng.collapse)\r
-                       rng.collapse(true);\r
+//             if (rng.collapse)\r
+//                     rng.collapse(true);\r
 \r
                var elm = rng.item ? rng.item(0) : rng.parentElement();\r
        } else {\r
+               if (this.isHidden())\r
+                       return this.getBody();\r
+\r
                var sel = this.getSel();\r
                var rng = this.getRng();\r
+\r
                var elm = rng.commonAncestorContainer;\r
                //var elm = (sel && sel.anchorNode) ? sel.anchorNode : null;\r
 \r