merge fx-team to mozilla-central
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 21 Nov 2013 14:32:10 +0100
changeset 156765 dbe66b706ba8dd446f8a1a056f410a4e39035b92
parent 156733 7427eede548f20038fe0ebd63dfc52b94c9f9d35 (current diff)
parent 156764 f37f1fcd9823da5f8fdac0494ae9d5642739fc90 (diff)
child 156774 09e33431c54327b00f8309145fdaf3658ae23b92
push id25685
push usercbook@mozilla.com
push dateThu, 21 Nov 2013 13:32:48 +0000
treeherdermozilla-central@dbe66b706ba8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge fx-team to mozilla-central
browser/devtools/sourceeditor/orion/LICENSE
browser/devtools/sourceeditor/orion/Makefile.dryice.js
browser/devtools/sourceeditor/orion/README
browser/devtools/sourceeditor/orion/UPGRADE
browser/devtools/sourceeditor/orion/orion.css
browser/devtools/sourceeditor/orion/orion.js
browser/devtools/sourceeditor/source-editor-orion.jsm
browser/devtools/sourceeditor/source-editor-overlay.xul
browser/devtools/sourceeditor/source-editor-ui.jsm
browser/devtools/sourceeditor/source-editor.jsm
browser/devtools/sourceeditor/test/browser_bug650345_find.js
browser/devtools/sourceeditor/test/browser_bug684546_reset_undo.js
browser/devtools/sourceeditor/test/browser_bug684862_paste_html.js
browser/devtools/sourceeditor/test/browser_bug687160_line_api.js
browser/devtools/sourceeditor/test/browser_bug687568_pagescroll.js
browser/devtools/sourceeditor/test/browser_bug687573_vscroll.js
browser/devtools/sourceeditor/test/browser_bug687580_drag_and_drop.js
browser/devtools/sourceeditor/test/browser_bug695035_middle_click_paste.js
browser/devtools/sourceeditor/test/browser_bug700893_dirty_state.js
browser/devtools/sourceeditor/test/browser_bug703692_focus_blur.js
browser/devtools/sourceeditor/test/browser_bug707987_debugger_breakpoints.js
browser/devtools/sourceeditor/test/browser_bug712982_line_ruler_click.js
browser/devtools/sourceeditor/test/browser_bug725388_mouse_events.js
browser/devtools/sourceeditor/test/browser_bug725392_mouse_coords_char_offset.js
browser/devtools/sourceeditor/test/browser_bug725430_comment_uncomment.js
browser/devtools/sourceeditor/test/browser_bug725618_moveLines_shortcut.js
browser/devtools/sourceeditor/test/browser_bug729480_line_vertical_align.js
browser/devtools/sourceeditor/test/browser_bug729960_block_bracket_jump.js
browser/devtools/sourceeditor/test/browser_bug731721_debugger_stepping.js
browser/devtools/sourceeditor/test/browser_bug744021_next_prev_bracket_jump.js
browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js
browser/metro/base/content/AnimatedZoom.js
browser/themes/linux/devtools/orion-breakpoint.png
browser/themes/linux/devtools/orion-container.css
browser/themes/linux/devtools/orion-debug-location.png
browser/themes/linux/devtools/orion-error.png
browser/themes/linux/devtools/orion-task.png
browser/themes/linux/devtools/orion.css
browser/themes/osx/devtools/orion-breakpoint.png
browser/themes/osx/devtools/orion-container.css
browser/themes/osx/devtools/orion-debug-location.png
browser/themes/osx/devtools/orion-error.png
browser/themes/osx/devtools/orion-task.png
browser/themes/osx/devtools/orion.css
browser/themes/windows/devtools/orion-breakpoint.png
browser/themes/windows/devtools/orion-container.css
browser/themes/windows/devtools/orion-debug-location.png
browser/themes/windows/devtools/orion-error.png
browser/themes/windows/devtools/orion-task.png
browser/themes/windows/devtools/orion.css
build/automationutils.py
content/base/src/nsDocument.cpp
mobile/android/base/gfx/LayerView.java
testing/mochitest/browser-test.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -654,19 +654,28 @@ pref("pfs.datasource.url", "https://pfs.
 pref("plugins.hide_infobar_for_blocked_plugin", false);
 pref("plugins.hide_infobar_for_outdated_plugin", false);
 
 pref("plugins.update.url", "https://www.mozilla.org/%LOCALE%/plugincheck/");
 pref("plugins.update.notifyUser", false);
 
 pref("plugins.click_to_play", true);
 
-// let all plugins except Flash default to click-to-play
+#ifdef RELEASE_BUILD
+// For now, plugins other than Java and Flash are enabled in beta/release
+// and click-to-activate in earlier channels.
+pref("plugin.default.state", 2);
+#else
 pref("plugin.default.state", 1);
+#endif
+
+// Flash is enabled by default, and Java is click-to-activate by default on
+// all channels.
 pref("plugin.state.flash", 2);
+pref("plugin.state.java", 1);
 
 // display door hanger if flash not installed
 pref("plugins.notifyMissingFlash", true);
 
 #ifdef XP_WIN
 pref("browser.preferences.instantApply", false);
 #else
 pref("browser.preferences.instantApply", true);
@@ -1222,24 +1231,16 @@ pref("devtools.hud.loglimit.exception", 
 pref("devtools.hud.loglimit.console", 200);
 
 // The developer tools editor configuration:
 // - tabsize: how many spaces to use when a Tab character is displayed.
 // - expandtab: expand Tab characters to spaces.
 pref("devtools.editor.tabsize", 4);
 pref("devtools.editor.expandtab", true);
 
-// Tells which component you want to use for source editing in developer tools.
-//
-// Available components:
-//   "orion" - this is the Orion source code editor from the Eclipse project. It
-//   provides programmer-specific editor features such as syntax highlighting,
-//   indenting and bracket recognition.
-pref("devtools.editor.component", "orion");
-
 // Enable the Font Inspector
 pref("devtools.fontinspector.enabled", true);
 
 // Pref to store the browser version at the time of a telemetry ping for an
 // opened developer tool. This allows us to ping telemetry just once per browser
 // version for each user.
 pref("devtools.telemetry.tools.opened.version", "{}");
 
--- a/browser/base/content/aboutDialog.js
+++ b/browser/base/content/aboutDialog.js
@@ -16,27 +16,32 @@ function init(aEvent)
     var distroId = Services.prefs.getCharPref("distribution.id");
     if (distroId) {
       var distroVersion = Services.prefs.getCharPref("distribution.version");
 
       var distroIdField = document.getElementById("distributionId");
       distroIdField.value = distroId + " - " + distroVersion;
       distroIdField.style.display = "block";
 
-      // This must be set last because it might not exist due to bug 895473.
-      var distroAbout = Services.prefs.getComplexValue("distribution.about",
-        Components.interfaces.nsISupportsString);
-      var distroField = document.getElementById("distribution");
-      distroField.value = distroAbout;
-      distroField.style.display = "block";
+      try {
+        // This is in its own try catch due to bug 895473 and bug 900925.
+        var distroAbout = Services.prefs.getComplexValue("distribution.about",
+          Components.interfaces.nsISupportsString);
+        var distroField = document.getElementById("distribution");
+        distroField.value = distroAbout;
+        distroField.style.display = "block";
+      }
+      catch (ex) {
+        // Pref is unset
+        Components.utils.reportError(ex);
+      }
     }
   }
   catch (e) {
     // Pref is unset
-    Components.utils.reportError(e);
   }
 
   // Include the build ID and display warning if this is an "a#" (nightly or aurora) build
   let version = Services.appinfo.version;
   if (/a\d+$/.test(version)) {
     let buildID = Services.appinfo.appBuildID;
     let buildDate = buildID.slice(0,4) + "-" + buildID.slice(4,6) + "-" + buildID.slice(6,8);
     document.getElementById("version").textContent += " (" + buildDate + ")";
--- a/browser/components/customizableui/src/CustomizableUI.jsm
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -1501,16 +1501,26 @@ let CustomizableUIInternal = {
   createWidget: function(aProperties) {
     let widget = this.normalizeWidget(aProperties, CustomizableUI.SOURCE_EXTERNAL);
     //XXXunf This should probably throw.
     if (!widget) {
       return;
     }
 
     gPalette.set(widget.id, widget);
+
+    // Clear our caches:
+    gGroupWrapperCache.delete(widget.id);
+    for (let [win, ] of gBuildWindows) {
+      let cache = gSingleWrapperCache.get(win);
+      if (cache) {
+        cache.delete(widget.id);
+      }
+    }
+
     this.notifyListeners("onWidgetCreated", widget.id);
 
     if (widget.defaultArea) {
       let area = gAreas.get(widget.defaultArea);
       //XXXgijs this won't have any effect for legacy items. Sort of OK because
       // consumers can modify currentset? Maybe?
       if (area.has("defaultPlacements")) {
         area.get("defaultPlacements").push(widget.id);
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -31,9 +31,10 @@ skip-if = true
 [browser_923857_customize_mode_event_wrapping_during_reset.js]
 [browser_927717_customize_drag_empty_toolbar.js]
 
 [browser_934113_menubar_removable.js]
 # Because this test is about the menubar, it can't be run on mac
 skip-if = os == "mac"
 
 [browser_938980_navbar_collapsed.js]
+[browser_941083_invalidate_wrapper_cache_createWidget.js]
 [browser_panel_toggle.js]
--- a/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
+++ b/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
@@ -109,24 +109,17 @@ function checkPalette(id, method) {
 
 let otherWin;
 let gTests = [
   {
     desc: "Moving widgets in two windows, one with customize mode and one without, should work",
     setup: startCustomizing,
     run: function() {
       otherWin = yield openAndLoadWindow(null, true);
-      // Open and close the panel to force its construction:
-      let shownPromise = promisePanelShown(otherWin);
-      otherWin.PanelUI.toggle({type: "command"});
-      yield shownPromise;
-      let hiddenPromise = promisePanelHidden(otherWin);
-      otherWin.PanelUI.toggle({type: "command"});
-      yield hiddenPromise;
-
+      yield otherWin.PanelUI.ensureReady();
       ok(CustomizableUI.inDefaultState, "Should start in default state");
 
       for (let widgetId of [kXULWidgetId, kAPIWidgetId]) {
         for (let method of ["API", "drag", "dragToItem"]) {
           info("Moving widget " + widgetId + " using " + method);
           checkToolbar(widgetId, method);
           checkPanel(widgetId, method);
           checkPalette(widgetId, method);
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/test/browser_941083_invalidate_wrapper_cache_createWidget.js
@@ -0,0 +1,38 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=941083
+
+const kWidgetId = "test-invalidate-wrapper-cache";
+
+let gTests = [
+  {
+    desc: "Check createWidget invalidates the widget cache",
+    run: function() {
+      let groupWrapper = CustomizableUI.getWidget(kWidgetId);
+      ok(groupWrapper, "Should get group wrapper.");
+      let singleWrapper = groupWrapper.forWindow(window);
+      ok(singleWrapper, "Should get single wrapper.");
+
+      CustomizableUI.createWidget({id: kWidgetId, label: "Test invalidating widgets caching"});
+
+      let newGroupWrapper = CustomizableUI.getWidget(kWidgetId);
+      ok(newGroupWrapper, "Should get a group wrapper again.");
+      isnot(newGroupWrapper, groupWrapper, "Wrappers shouldn't be the same.");
+      isnot(newGroupWrapper.provider, groupWrapper.provider, "Wrapper providers shouldn't be the same.");
+
+      let newSingleWrapper = newGroupWrapper.forWindow(window);
+      isnot(newSingleWrapper, singleWrapper, "Single wrappers shouldn't be the same.");
+      isnot(newSingleWrapper.provider, singleWrapper.provider, "Single wrapper providers shouldn't be the same.");
+
+      CustomizableUI.destroyWidget(kWidgetId);
+      ok(!CustomizableUI.getWidget(kWidgetId), "Shouldn't get a wrapper after destroying the widget.");
+    },
+  },
+];
+
+function test() {
+  waitForExplicitFinish();
+  runTests(gTests);
+}
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -1393,48 +1393,65 @@ EventListeners.prototype = {
     });
   },
 
   /**
    * Fetches the currently attached event listeners from the debugee.
    */
   scheduleEventListenersFetch: function() {
     let getListeners = aCallback => gThreadClient.eventListeners(aResponse => {
-      this._onEventListeners(aResponse);
+      if (aResponse.error) {
+        let msg = "Error getting event listeners: " + aResponse.message;
+        DevToolsUtils.reportException("scheduleEventListenersFetch", msg);
+        return;
+      }
+
+      promise.all(aResponse.listeners.map(listener => {
+        const deferred = promise.defer();
 
-      // Notify that event listeners were fetched and shown in the view,
-      // and callback to resume the active thread if necessary.
-      window.emit(EVENTS.EVENT_LISTENERS_FETCHED);
-      aCallback && aCallback();
+        gThreadClient.pauseGrip(listener.function).getDefinitionSite(aResponse => {
+          if (aResponse.error) {
+            const msg = "Error getting function definition site: " + aResponse.message;
+            DevToolsUtils.reportException("scheduleEventListenersFetch", msg);
+            deferred.reject(msg);
+            return;
+          }
+
+          listener.function.url = aResponse.url;
+          deferred.resolve(listener);
+        });
+
+        return deferred.promise;
+      })).then(listeners => {
+        this._onEventListeners(listeners);
+
+        // Notify that event listeners were fetched and shown in the view,
+        // and callback to resume the active thread if necessary.
+        window.emit(EVENTS.EVENT_LISTENERS_FETCHED);
+        aCallback && aCallback();
+      });
     });
 
     // Make sure we're not sending a batch of closely repeated requests.
     // This can easily happen whenever new sources are fetched.
     setNamedTimeout("event-listeners-fetch", FETCH_EVENT_LISTENERS_DELAY, () => {
       if (gThreadClient.state != "paused") {
         gThreadClient.interrupt(() => getListeners(() => gThreadClient.resume()));
       } else {
         getListeners();
       }
     });
   },
 
   /**
-   * Callback for the debugger's active thread eventListeners() method.
+   * Callback for a debugger's successful active thread eventListeners() call.
    */
-  _onEventListeners: function(aResponse) {
-    if (aResponse.error) {
-      let msg = "Error getting event listeners: " + aResponse.message;
-      Cu.reportError(msg);
-      dumpn(msg);
-      return;
-    }
-
+  _onEventListeners: function(aListeners) {
     // Add all the listeners in the debugger view event linsteners container.
-    for (let listener of aResponse.listeners) {
+    for (let listener of aListeners) {
       DebuggerView.EventListeners.addListener(listener, { staged: true });
     }
 
     // Flushes all the prepared events into the event listeners container.
     DebuggerView.EventListeners.commit();
   }
 };
 
--- a/browser/devtools/debugger/test/browser_dbg_event-listeners.js
+++ b/browser/devtools/debugger/test/browser_dbg_event-listeners.js
@@ -55,65 +55,87 @@ function pauseDebuggee(aThreadClient) {
 
   return deferred.promise;
 }
 
 function testEventListeners(aThreadClient) {
   let deferred = promise.defer();
 
   aThreadClient.eventListeners(aPacket => {
+    if (aPacket.error) {
+      let msg = "Error getting event listeners: " + aPacket.message;
+      ok(false, msg);
+      deferred.reject(msg);
+      return;
+    }
+
     is(aPacket.listeners.length, 3,
       "Found all event listeners.");
 
-    let types = [];
-
-    for (let l of aPacket.listeners) {
-      let node = l.node;
-      ok(node, "There is a node property.");
-      ok(node.object, "There is a node object property.");
-      ok(node.selector == "window" ||
-        content.document.querySelectorAll(node.selector).length == 1,
-        "The node property is a unique CSS selector.");
+    promise.all(aPacket.listeners.map(listener => {
+      const lDeferred = promise.defer();
+      aThreadClient.pauseGrip(listener.function).getDefinitionSite(aResponse => {
+        if (aResponse.error) {
+          const msg = "Error getting function definition site: " + aResponse.message;
+          ok(false, msg);
+          lDeferred.reject(msg);
+          return;
+        }
+        listener.function.url = aResponse.url;
+        lDeferred.resolve(listener);
+      });
+      return lDeferred.promise;
+    })).then(listeners => {
+      let types = [];
 
-      let func = l.function;
-      ok(func, "There is a function property.");
-      is(func.type, "object", "The function form is of type 'object'.");
-      is(func.class, "Function", "The function form is of class 'Function'.");
-      is(func.url, TAB_URL, "The function url is correct.");
+      for (let l of listeners) {
+        let node = l.node;
+        ok(node, "There is a node property.");
+        ok(node.object, "There is a node object property.");
+        ok(node.selector == "window" ||
+          content.document.querySelectorAll(node.selector).length == 1,
+          "The node property is a unique CSS selector.");
 
-      is(l.allowsUntrusted, true,
-        "'allowsUntrusted' property has the right value.");
-      is(l.inSystemEventGroup, false,
-        "'inSystemEventGroup' property has the right value.");
-
-      types.push(l.type);
+        let func = l.function;
+        ok(func, "There is a function property.");
+        is(func.type, "object", "The function form is of type 'object'.");
+        is(func.class, "Function", "The function form is of class 'Function'.");
+        is(func.url, TAB_URL, "The function url is correct.");
 
-      if (l.type == "keyup") {
-        is(l.capturing, true,
-          "Capturing property has the right value.");
-        is(l.isEventHandler, false,
-          "'isEventHandler' property has the right value.");
-      } else if (l.type == "load") {
-        is(l.capturing, false,
-          "Capturing property has the right value.");
-        is(l.isEventHandler, false,
-          "'isEventHandler' property has the right value.");
-      } else {
-        is(l.capturing, false,
-          "Capturing property has the right value.");
-        is(l.isEventHandler, true,
-          "'isEventHandler' property has the right value.");
+        is(l.allowsUntrusted, true,
+          "'allowsUntrusted' property has the right value.");
+        is(l.inSystemEventGroup, false,
+          "'inSystemEventGroup' property has the right value.");
+
+        types.push(l.type);
+
+        if (l.type == "keyup") {
+          is(l.capturing, true,
+            "Capturing property has the right value.");
+          is(l.isEventHandler, false,
+            "'isEventHandler' property has the right value.");
+        } else if (l.type == "load") {
+          is(l.capturing, false,
+            "Capturing property has the right value.");
+          is(l.isEventHandler, false,
+            "'isEventHandler' property has the right value.");
+        } else {
+          is(l.capturing, false,
+            "Capturing property has the right value.");
+          is(l.isEventHandler, true,
+            "'isEventHandler' property has the right value.");
+        }
       }
-    }
 
-    ok(types.indexOf("click") != -1, "Found the click handler.");
-    ok(types.indexOf("change") != -1, "Found the change handler.");
-    ok(types.indexOf("keyup") != -1, "Found the keyup handler.");
+      ok(types.indexOf("click") != -1, "Found the click handler.");
+      ok(types.indexOf("change") != -1, "Found the change handler.");
+      ok(types.indexOf("keyup") != -1, "Found the keyup handler.");
 
-    aThreadClient.resume(deferred.resolve);
+      aThreadClient.resume(deferred.resolve);
+    });
   });
 
   return deferred.promise;
 }
 
 function closeConnection() {
   let deferred = promise.defer();
   gClient.close(deferred.resolve);
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -23,34 +23,32 @@ browser.jar:
     content/browser/devtools/cssruleview.xhtml                         (styleinspector/cssruleview.xhtml)
     content/browser/devtools/ruleview.css                              (styleinspector/ruleview.css)
     content/browser/devtools/layoutview/view.js                        (layoutview/view.js)
     content/browser/devtools/layoutview/view.xhtml                     (layoutview/view.xhtml)
     content/browser/devtools/layoutview/view.css                       (layoutview/view.css)
     content/browser/devtools/fontinspector/font-inspector.js           (fontinspector/font-inspector.js)
     content/browser/devtools/fontinspector/font-inspector.xhtml        (fontinspector/font-inspector.xhtml)
     content/browser/devtools/fontinspector/font-inspector.css          (fontinspector/font-inspector.css)
-    content/browser/devtools/orion.js                                  (sourceeditor/orion/orion.js)
     content/browser/devtools/codemirror/codemirror.js                  (sourceeditor/codemirror/codemirror.js)
     content/browser/devtools/codemirror/codemirror.css                 (sourceeditor/codemirror/codemirror.css)
     content/browser/devtools/codemirror/javascript.js                  (sourceeditor/codemirror/javascript.js)
     content/browser/devtools/codemirror/xml.js                         (sourceeditor/codemirror/xml.js)
     content/browser/devtools/codemirror/css.js                         (sourceeditor/codemirror/css.js)
     content/browser/devtools/codemirror/htmlmixed.js                   (sourceeditor/codemirror/htmlmixed.js)
     content/browser/devtools/codemirror/clike.js                       (sourceeditor/codemirror/clike.js)
     content/browser/devtools/codemirror/activeline.js                  (sourceeditor/codemirror/activeline.js)
     content/browser/devtools/codemirror/matchbrackets.js               (sourceeditor/codemirror/matchbrackets.js)
     content/browser/devtools/codemirror/closebrackets.js               (sourceeditor/codemirror/closebrackets.js)
     content/browser/devtools/codemirror/comment.js                     (sourceeditor/codemirror/comment.js)
     content/browser/devtools/codemirror/searchcursor.js                (sourceeditor/codemirror/search/searchcursor.js)
     content/browser/devtools/codemirror/search.js                      (sourceeditor/codemirror/search/search.js)
     content/browser/devtools/codemirror/dialog.js                      (sourceeditor/codemirror/dialog/dialog.js)
     content/browser/devtools/codemirror/dialog.css                     (sourceeditor/codemirror/dialog/dialog.css)
     content/browser/devtools/codemirror/mozilla.css                    (sourceeditor/codemirror/mozilla.css)
-*   content/browser/devtools/source-editor-overlay.xul                 (sourceeditor/source-editor-overlay.xul)
     content/browser/devtools/debugger.xul                              (debugger/debugger.xul)
     content/browser/devtools/debugger.css                              (debugger/debugger.css)
     content/browser/devtools/debugger-controller.js                    (debugger/debugger-controller.js)
     content/browser/devtools/debugger-view.js                          (debugger/debugger-view.js)
     content/browser/devtools/debugger-toolbar.js                       (debugger/debugger-toolbar.js)
     content/browser/devtools/debugger-panes.js                         (debugger/debugger-panes.js)
     content/browser/devtools/shadereditor.xul                          (shadereditor/shadereditor.xul)
     content/browser/devtools/shadereditor.js                           (shadereditor/shadereditor.js)
--- a/browser/devtools/markupview/html-editor.js
+++ b/browser/devtools/markupview/html-editor.js
@@ -62,17 +62,18 @@ function HTMLEditor(htmlDocument)
   config.extraKeys[ctrl("Enter")] = this.hide;
   config.extraKeys["F2"] = this.hide;
   config.extraKeys["Esc"] = this.hide.bind(this, false);
 
   this.container.addEventListener("click", this.hide, false);
   this.editorInner.addEventListener("click", stopPropagation, false);
   this.editor = new Editor(config);
 
-  this.editor.appendTo(this.editorInner).then(() => {
+  let iframe = this.editorInner.ownerDocument.createElement("iframe");
+  this.editor.appendTo(this.editorInner, iframe).then(() => {
     this.hide(false);
   }).then(null, (err) => console.log(err.message));
 }
 
 HTMLEditor.prototype = {
 
   /**
    * Need to refresh position by manually setting CSS values, so this will
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -19,16 +19,17 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 const SCRATCHPAD_CONTEXT_CONTENT = 1;
 const SCRATCHPAD_CONTEXT_BROWSER = 2;
 const BUTTON_POSITION_SAVE       = 0;
 const BUTTON_POSITION_CANCEL     = 1;
 const BUTTON_POSITION_DONT_SAVE  = 2;
 const BUTTON_POSITION_REVERT     = 0;
+const EVAL_FUNCTION_TIMEOUT      = 1000; // milliseconds
 
 const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties";
 const DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
 const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
 
 const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul";
 
 const require   = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
@@ -70,16 +71,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   "resource://gre/modules/devtools/dbg-client.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "REMOTE_TIMEOUT", () =>
   Services.prefs.getIntPref("devtools.debugger.remote-timeout"));
 
 XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
   "resource://gre/modules/ShortcutUtils.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "Reflect",
+  "resource://gre/modules/reflect.jsm");
+
 // Because we have no constructor / destructor where we can log metrics we need
 // to do so here.
 let telemetry = new Telemetry();
 telemetry.toolOpened("scratchpad");
 
 /**
  * The scratchpad object handles the Scratchpad window functionality.
  */
@@ -563,16 +567,178 @@ var Scratchpad = {
       indent: tabsize,
       source: uglyText
     });
 
     return deferred.promise;
   },
 
   /**
+   * Parse the text and return an AST. If we can't parse it, write an error
+   * comment and return false.
+   */
+  _parseText: function SP__parseText(aText) {
+    try {
+      return Reflect.parse(aText);
+    } catch (e) {
+      this.writeAsErrorComment(DevToolsUtils.safeErrorString(e));
+      return false;
+    }
+  },
+
+  /**
+   * Determine if the given AST node location contains the given cursor
+   * position.
+   *
+   * @returns Boolean
+   */
+  _containsCursor: function (aLoc, aCursorPos) {
+    // Our line numbers are 1-based, while CodeMirror's are 0-based.
+    const lineNumber = aCursorPos.line + 1;
+    const columnNumber = aCursorPos.ch;
+
+    if (aLoc.start.line <= lineNumber && aLoc.end.line >= lineNumber) {
+      if (aLoc.start.line === aLoc.end.line) {
+        return aLoc.start.column <= columnNumber
+          && aLoc.end.column >= columnNumber;
+      }
+
+      if (aLoc.start.line == lineNumber) {
+        return columnNumber >= aLoc.start.column;
+      }
+
+      if (aLoc.end.line == lineNumber) {
+        return columnNumber <= aLoc.end.column;
+      }
+
+      return true;
+    }
+
+    return false;
+  },
+
+  /**
+   * Find the top level function AST node that the cursor is within.
+   *
+   * @returns Object|null
+   */
+  _findTopLevelFunction: function SP__findTopLevelFunction(aAst, aCursorPos) {
+    for (let statement of aAst.body) {
+      switch (statement.type) {
+      case "FunctionDeclaration":
+        if (this._containsCursor(statement.loc, aCursorPos)) {
+          return statement;
+        }
+        break;
+
+      case "VariableDeclaration":
+        for (let decl of statement.declarations) {
+          if (!decl.init) {
+            continue;
+          }
+          if ((decl.init.type == "FunctionExpression"
+               || decl.init.type == "ArrowExpression")
+              && this._containsCursor(decl.loc, aCursorPos)) {
+            return decl;
+          }
+        }
+        break;
+      }
+    }
+
+    return null;
+  },
+
+  /**
+   * Get the source text associated with the given function statement.
+   *
+   * @param Object aFunction
+   * @param String aFullText
+   * @returns String
+   */
+  _getFunctionText: function SP__getFunctionText(aFunction, aFullText) {
+    let functionText = "";
+    // Initially set to 0, but incremented first thing in the loop below because
+    // line numbers are 1 based, not 0 based.
+    let lineNumber = 0;
+    const { start, end } = aFunction.loc;
+    const singleLine = start.line === end.line;
+
+    for (let line of aFullText.split(/\n/g)) {
+      lineNumber++;
+
+      if (singleLine && start.line === lineNumber) {
+        functionText = line.slice(start.column, end.column);
+        break;
+      }
+
+      if (start.line === lineNumber) {
+        functionText += line.slice(start.column) + "\n";
+        continue;
+      }
+
+      if (end.line === lineNumber) {
+        functionText += line.slice(0, end.column);
+        break;
+      }
+
+      if (start.line < lineNumber && end.line > lineNumber) {
+        functionText += line + "\n";
+      }
+    }
+
+    return functionText;
+  },
+
+  /**
+   * Evaluate the top level function that the cursor is resting in.
+   *
+   * @returns Promise [text, error, result]
+   */
+  evalTopLevelFunction: function SP_evalTopLevelFunction() {
+    const text = this.getText();
+    const ast = this._parseText(text);
+    if (!ast) {
+      return promise.resolve([text, undefined, undefined]);
+    }
+
+    const cursorPos = this.editor.getCursor();
+    const funcStatement = this._findTopLevelFunction(ast, cursorPos);
+    if (!funcStatement) {
+      return promise.resolve([text, undefined, undefined]);
+    }
+
+    let functionText = this._getFunctionText(funcStatement, text);
+
+    // TODO: This is a work around for bug 940086. It should be removed when
+    // that is fixed.
+    if (funcStatement.type == "FunctionDeclaration"
+        && !functionText.startsWith("function ")) {
+      functionText = "function " + functionText;
+      funcStatement.loc.start.column -= 9;
+    }
+
+    // The decrement by one is because our line numbers are 1-based, while
+    // CodeMirror's are 0-based.
+    const from = {
+      line: funcStatement.loc.start.line - 1,
+      ch: funcStatement.loc.start.column
+    };
+    const to = {
+      line: funcStatement.loc.end.line - 1,
+      ch: funcStatement.loc.end.column
+    };
+
+    const marker = this.editor.markText(from, to, { className: "eval-text" });
+    setTimeout(() => marker.clear(), EVAL_FUNCTION_TIMEOUT);
+
+    return this.evaluate(functionText);
+  },
+
+  /**
    * Writes out a primitive value as a comment. This handles values which are
    * to be printed directly (number, string) as well as grips to values
    * (null, undefined, longString).
    *
    * @param any aValue
    *        The value to print.
    * @return Promise
    *         The promise that resolves after the value has been printed.
@@ -1511,17 +1677,17 @@ var Scratchpad = {
   },
 
   _observers: [],
 
   /**
    * Add an observer for Scratchpad events.
    *
    * The observer implements IScratchpadObserver := {
-   *   onReady:      Called when the Scratchpad and its SourceEditor are ready.
+   *   onReady:      Called when the Scratchpad and its Editor are ready.
    *                 Arguments: (Scratchpad aScratchpad)
    * }
    *
    * All observer handlers are optional.
    *
    * @param IScratchpadObserver aObserver
    * @see removeObserver
    */
--- a/browser/devtools/scratchpad/scratchpad.xul
+++ b/browser/devtools/scratchpad/scratchpad.xul
@@ -58,16 +58,17 @@
   <command id="sp-cmd-close" oncommand="Scratchpad.close();"/>
   <command id="sp-cmd-run" oncommand="Scratchpad.run();"/>
   <command id="sp-cmd-inspect" oncommand="Scratchpad.inspect();"/>
   <command id="sp-cmd-display" oncommand="Scratchpad.display();"/>
   <command id="sp-cmd-pprint" oncommand="Scratchpad.prettyPrint();"/>
   <command id="sp-cmd-contentContext" oncommand="Scratchpad.setContentContext();"/>
   <command id="sp-cmd-browserContext" oncommand="Scratchpad.setBrowserContext();" disabled="true"/>
   <command id="sp-cmd-reloadAndRun" oncommand="Scratchpad.reloadAndRun();"/>
+  <command id="sp-cmd-evalFunction" oncommand="Scratchpad.evalTopLevelFunction();"/>
   <command id="sp-cmd-errorConsole" oncommand="Scratchpad.openErrorConsole();" disabled="true"/>
   <command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/>
   <command id="sp-cmd-documentationLink" oncommand="Scratchpad.openDocumentationPage();"/>
   <command id="sp-cmd-hideSidebar" oncommand="Scratchpad.sidebar.hide();"/>
 </commandset>
 
 <keyset id="editMenuKeys"/>
 
@@ -103,16 +104,20 @@
   <key id="sp-key-pprint"
        key="&pprint.key;"
        command="sp-cmd-pprint"
        modifiers="accel"/>
   <key id="sp-key-reloadAndRun"
        key="&reloadAndRun.key;"
        command="sp-cmd-reloadAndRun"
        modifiers="accel,shift"/>
+  <key id="sp-key-evalFunction"
+       key="&evalFunction.key;"
+       command="sp-cmd-evalFunction"
+       modifiers="accel"/>
   <key id="sp-key-errorConsole"
        key="&errorConsoleCmd.commandkey;"
        command="sp-cmd-errorConsole"
        modifiers="accel,shift"/>
   <key id="sp-key-hideSidebar"
        keycode="VK_ESCAPE"
        command="sp-cmd-hideSidebar"/>
   <key id="key_openHelp"
@@ -208,16 +213,21 @@
                 key="sp-key-display"
                 command="sp-cmd-display"/>
       <menuseparator/>
       <menuitem id="sp-text-reloadAndRun"
                 label="&reloadAndRun.label;"
                 key="sp-key-reloadAndRun"
                 accesskey="&reloadAndRun.accesskey;"
                 command="sp-cmd-reloadAndRun"/>
+      <menuitem id="sp-text-evalFunction"
+                label="&evalFunction.label;"
+                key="sp-key-evalFunction"
+                accesskey="&evalFunction.accesskey;"
+                command="sp-cmd-evalFunction"/>
     </menupopup>
   </menu>
 
   <menu id="sp-environment-menu"
         label="&environmentMenu.label;"
         accesskey="&environmentMenu.accesskey;"
         hidden="true">
     <menupopup id="sp-menu-environment">
@@ -309,16 +319,21 @@
               accesskey="&inspect.accesskey;"
               key="sp-key-inspect"
               command="sp-cmd-inspect"/>
     <menuitem id="sp-text-display"
               label="&display.label;"
               accesskey="&display.accesskey;"
               key="sp-key-display"
               command="sp-cmd-display"/>
+    <menuitem id="sp-text-evalFunction"
+              label="&evalFunction.label;"
+              key="sp-key-evalFunction"
+              accesskey="&evalFunction.accesskey;"
+              command="sp-cmd-evalFunction"/>
   </menupopup>
 </popupset>
 
 <notificationbox id="scratchpad-notificationbox" flex="1">
   <hbox flex="1">
     <vbox id="scratchpad-editor" flex="1"/>
     <splitter class="devtools-side-splitter"/>
     <tabbox id="scratchpad-sidebar" class="devtools-sidebar-tabs"
--- a/browser/devtools/scratchpad/test/browser.ini
+++ b/browser/devtools/scratchpad/test/browser.ini
@@ -1,14 +1,15 @@
 [DEFAULT]
 support-files = head.js
 
 [browser_scratchpad_browser_last_window_closing.js]
 [browser_scratchpad_reset_undo.js]
 [browser_scratchpad_display_outputs_errors.js]
+[browser_scratchpad_eval_func.js]
 [browser_scratchpad_goto_line_ui.js]
 [browser_scratchpad_reload_and_run.js]
 [browser_scratchpad_display_non_error_exceptions.js]
 [browser_scratchpad_modeline.js]
 [browser_scratchpad_chrome_context_pref.js]
 [browser_scratchpad_help_key.js]
 [browser_scratchpad_recent_files.js]
 # [browser_scratchpad_confirm_close.js]
--- a/browser/devtools/scratchpad/test/browser_scratchpad_edit_ui_updates.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_edit_ui_updates.js
@@ -1,19 +1,15 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 /* Bug 699130 */
 
 "use strict";
 
-let tempScope = {};
-Cu.import("resource:///modules/devtools/sourceeditor/source-editor.jsm", tempScope);
-let SourceEditor = tempScope.SourceEditor;
-
 function test()
 {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
     gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
     openScratchpad(runTests);
new file mode 100644
--- /dev/null
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_eval_func.js
@@ -0,0 +1,86 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+    gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+    openScratchpad(runTests);
+  }, true);
+
+  content.location = "data:text/html;charset=utf8,test Scratchpad eval function.";
+}
+
+function reportErrorAndQuit(error) {
+  DevToolsUtils.reportException("browser_scratchpad_eval_func.js", error);
+  ok(false);
+  finish();
+}
+
+function runTests(sw)
+{
+  const sp = sw.Scratchpad;
+
+  let foo = "" + function main() { console.log(1); };
+  let bar = "var bar = " + (() => { console.log(2); });
+
+  const fullText =
+    foo + "\n" +
+    "\n" +
+    bar + "\n"
+
+  sp.setText(fullText);
+
+  // On the function declaration.
+  sp.editor.setCursor({ line: 0, ch: 18 });
+  sp.evalTopLevelFunction()
+    .then(([text, error, result]) => {
+      is(text, foo, "Should re-eval foo.");
+      ok(!error, "Should not have got an error.");
+      ok(result, "Should have got a result.");
+    })
+
+    // On the arrow function.
+    .then(() => {
+      sp.editor.setCursor({ line: 2, ch: 18 });
+      return sp.evalTopLevelFunction();
+    })
+    .then(([text, error, result]) => {
+      is(text, bar.replace("var ", ""), "Should re-eval bar.");
+      ok(!error, "Should not have got an error.");
+      ok(result, "Should have got a result.");
+    })
+
+    // On the empty line.
+    .then(() => {
+      sp.editor.setCursor({ line: 1, ch: 0 });
+      return sp.evalTopLevelFunction();
+    })
+    .then(([text, error, result]) => {
+      is(text, fullText,
+         "Should get full text back since we didn't find a specific function.");
+      ok(!error, "Should not have got an error.");
+      ok(!result, "Should not have got a result.");
+    })
+
+    // Syntax error.
+    .then(() => {
+      sp.setText("function {}");
+      sp.editor.setCursor({ line: 0, ch: 9 });
+      return sp.evalTopLevelFunction();
+    })
+    .then(([text, error, result]) => {
+      is(text, "function {}",
+         "Should get the full text back since there was a parse error.");
+      ok(!error, "Should not have got an error");
+      ok(!result, "Should not have got a result");
+      ok(sp.getText().contains("SyntaxError"),
+         "We should have written the syntax error to the scratchpad.");
+    })
+
+    .then(finish, reportErrorAndQuit);
+}
--- a/browser/devtools/sourceeditor/codemirror/dialog/dialog.js
+++ b/browser/devtools/sourceeditor/codemirror/dialog/dialog.js
@@ -5,17 +5,21 @@
     var wrap = cm.getWrapperElement();
     var dialog;
     dialog = wrap.appendChild(document.createElement("div"));
     if (bottom) {
       dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
     } else {
       dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
     }
-    dialog.innerHTML = template;
+    if (typeof template == "string") {
+      dialog.innerHTML = template;
+    } else {
+      dialog.appendChild(template);
+    }
     return dialog;
   }
 
   CodeMirror.defineExtension("openDialog", function(template, callback, options) {
     var dialog = dialogDiv(this, template, options && options.bottom);
     var closed = false, me = this;
     function close() {
       if (closed) return;
--- a/browser/devtools/sourceeditor/codemirror/mozilla.css
+++ b/browser/devtools/sourceeditor/codemirror/mozilla.css
@@ -13,31 +13,31 @@
   width: 12px;
   height: 12px;
   background-repeat: no-repeat;
   background-position: center;
   background-size: contain;
 }
 
 .error {
-  background-image: url("chrome://browser/skin/devtools/orion-error.png");
+  background-image: url("chrome://browser/skin/devtools/editor-error.png");
   opacity: 0.75;
 }
 
 .breakpoint {
-  background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
+  background-image: url("chrome://browser/skin/devtools/editor-breakpoint.png");
 }
 
 .debugLocation {
-  background-image: url("chrome://browser/skin/devtools/orion-debug-location.png");
+  background-image: url("chrome://browser/skin/devtools/editor-debug-location.png");
 }
 
 .breakpoint.debugLocation {
-  background-image: url("chrome://browser/skin/devtools/orion-debug-location.png"),
-    url("chrome://browser/skin/devtools/orion-breakpoint.png");
+  background-image: url("chrome://browser/skin/devtools/editor-debug-location.png"),
+    url("chrome://browser/skin/devtools/editor-breakpoint.png");
 }
 
 .error-line {
   background: rgba(255,0,0,0.2);
 }
 
 /* This is to avoid the fake horizontal scrollbar div of codemirror to go 0
 height when floating scrollbars are active. Make sure that this value is equal
@@ -49,8 +49,22 @@ selector in floating-scrollbar-light.css
 
 /* This is to avoid the fake vertical scrollbar div of codemirror to go 0
 width when floating scrollbars are active. Make sure that this value is equal
 to the maximum of `min-width` specific to the `scrollbar[orient="vertical"]`
 selector in floating-scrollbar-light.css across all platforms. */
 .CodeMirror-vscrollbar {
   min-width: 10px;
 }
+
+/* This is to make CodeMirror's dialogs more DevTool-ey. */
+
+.CodeMirror-dialog {
+  font: message-box;
+  padding: 5px 4px;
+  color: hsl(210,30%,85%);
+  background-image: url("chrome://browser/skin/devtools/background-noise-toolbar.png"),
+    linear-gradient(#3e4750, #3e4750);
+}
+
+.CodeMirror-dialog input {
+  font: message-box;
+}
\ No newline at end of file
--- a/browser/devtools/sourceeditor/codemirror/search/search.js
+++ b/browser/devtools/sourceeditor/codemirror/search/search.js
@@ -43,18 +43,27 @@
   }
   function parseQuery(query) {
     var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
     return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
   }
   var queryDialog;
   function doSearch(cm, rev) {
     if (!queryDialog) {
-      queryDialog = cm.l10n('findCmd.promptMessage') +
-        ' <input type="text" style="width: 10em"/>';
+      let doc = cm.getWrapperElement().ownerDocument;
+      let inp = doc.createElement("input");
+      let txt = doc.createTextNode(cm.l10n("findCmd.promptMessage"));
+
+      inp.type = "text";
+      inp.style.width = "10em";
+      inp.style.MozMarginStart = "1em";
+
+      queryDialog = doc.createElement("div");
+      queryDialog.appendChild(txt);
+      queryDialog.appendChild(inp);
     }
 
     var state = getSearchState(cm);
     if (state.query) return findNext(cm, rev);
     dialog(cm, queryDialog, cm.l10n('findCmd.promptMessage'), function(query) {
       cm.operation(function() {
         if (!query || state.query) return;
         state.query = parseQuery(query);
--- a/browser/devtools/sourceeditor/editor.js
+++ b/browser/devtools/sourceeditor/editor.js
@@ -73,24 +73,20 @@ const CM_MAPPING = [
   "setSelection",
   "getSelection",
   "replaceSelection",
   "undo",
   "redo",
   "clearHistory",
   "openDialog",
   "cursorCoords",
+  "markText",
   "refresh"
 ];
 
-const CM_JUMP_DIALOG = [
-  L10N.GetStringFromName("gotoLineCmd.promptTitle")
-    + " <input type=text style='width: 10em'/>"
-];
-
 const { cssProperties, cssValues, cssColors } = getCSSKeywords();
 
 const editors = new WeakMap();
 
 Editor.modes = {
   text: { name: "text" },
   html: { name: "htmlmixed" },
   css:  { name: "css" },
@@ -134,17 +130,17 @@ function Editor(config) {
     matchBrackets:   true,
     extraKeys:       {},
     indentWithTabs:  useTabs,
     styleActiveLine: true,
     theme: "mozilla"
   };
 
   // Additional shortcuts.
-  this.config.extraKeys[Editor.keyFor("jumpToLine")] = (cm) => this.jumpToLine();
+  this.config.extraKeys[Editor.keyFor("jumpToLine")] = (cm) => this.jumpToLine(cm);
   this.config.extraKeys[Editor.keyFor("toggleComment")] = "toggleComment";
 
   // Disable ctrl-[ and ctrl-] because toolbox uses those shortcuts.
   this.config.extraKeys[Editor.keyFor("indentLess")] = false;
   this.config.extraKeys[Editor.keyFor("indentMore")] = false;
 
   // Overwrite default config with user-provided, if needed.
   Object.keys(config).forEach((k) => {
@@ -180,25 +176,29 @@ function Editor(config) {
 
 Editor.prototype = {
   container: null,
   version: null,
   config: null,
 
   /**
    * Appends the current Editor instance to the element specified by
-   * the only argument 'el'. This method actually creates and loads
-   * CodeMirror and all its dependencies.
+   * 'el'. You can also provide your won iframe to host the editor as
+   * an optional second parameter. This method actually creates and
+   * loads CodeMirror and all its dependencies.
    *
    * This method is asynchronous and returns a promise.
    */
-  appendTo: function (el) {
+  appendTo: function (el, env) {
     let def = promise.defer();
     let cm  = editors.get(this);
-    let env = el.ownerDocument.createElement("iframe");
+
+    if (!env)
+      env = el.ownerDocument.createElementNS(XUL_NS, "iframe");
+
     env.flex = 1;
 
     if (cm)
       throw new Error("You can append an editor only once.");
 
     let onLoad = () => {
       // Once the iframe is loaded, we can inject CodeMirror
       // and its dependencies into its DOM.
@@ -497,20 +497,21 @@ Editor.prototype = {
   },
 
   /**
    * Returns whether a line is decorated using the specified class name.
    */
   hasLineClass: function (line, className) {
     let cm = editors.get(this);
     let info = cm.lineInfo(line);
-    if (!info)
+
+    if (!info || !info.wrapClass)
       return false;
 
-    return info.wrapClass == className;
+    return info.wrapClass.split(" ").indexOf(className) != -1;
   },
 
   /**
    * Set a CSS class name for the given line, including the text and gutter.
    */
   addLineClass: function (line, className) {
     let cm = editors.get(this);
     cm.addLineClass(line, "wrap", className);
@@ -614,19 +615,30 @@ Editor.prototype = {
     let popup = container.getElementById(this.config.contextMenu);
     popup.openPopupAtScreen(x, y, true);
   },
 
   /**
    * This method opens an in-editor dialog asking for a line to
    * jump to. Once given, it changes cursor to that line.
    */
-  jumpToLine: function () {
-    this.openDialog(CM_JUMP_DIALOG, (line) =>
-      this.setCursor({ line: line - 1, ch: 0 }));
+  jumpToLine: function (cm) {
+    let doc = cm.getWrapperElement().ownerDocument;
+    let div = doc.createElement("div");
+    let inp = doc.createElement("input");
+    let txt = doc.createTextNode(L10N.GetStringFromName("gotoLineCmd.promptTitle"));
+
+    inp.type = "text";
+    inp.style.width = "10em";
+    inp.style.MozMarginStart = "1em";
+
+    div.appendChild(txt);
+    div.appendChild(inp);
+
+    this.openDialog(div, (line) => this.setCursor({ line: line - 1, ch: 0 }));
   },
 
   /**
    * Extends an instance of the Editor object with additional
    * functions. Each function will be called with context as
    * the first argument. Context is a {ed, cm} object where
    * 'ed' is an instance of the Editor object and 'cm' is an
    * instance of the CodeMirror object. Example:
--- a/browser/devtools/sourceeditor/moz.build
+++ b/browser/devtools/sourceeditor/moz.build
@@ -5,14 +5,11 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['test']
 
 JS_MODULES_PATH = 'modules/devtools/sourceeditor'
 
 EXTRA_JS_MODULES += [
     'debugger.js',
-    'editor.js',
-    'source-editor-orion.jsm',
-    'source-editor-ui.jsm',
-    'source-editor.jsm',
+    'editor.js'
 ]
 
deleted file mode 100644
--- a/browser/devtools/sourceeditor/orion/LICENSE
+++ /dev/null
@@ -1,29 +0,0 @@
-Eclipse Distribution License - v 1.0
-
-Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright notice, this
-  list of conditions and the following disclaimer in the documentation and/or
-  other materials provided with the distribution.
-* Neither the name of the Eclipse Foundation, Inc. nor the names of its
-  contributors may be used to endorse or promote products derived from this
-  software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
deleted file mode 100644
--- a/browser/devtools/sourceeditor/orion/Makefile.dryice.js
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env node
-/* vim:set ts=2 sw=2 sts=2 et tw=80:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var copy = require('dryice').copy;
-
-const ORION_EDITOR = "org.eclipse.orion.client.editor/web";
-
-var js_src = copy.createDataObject();
-
-copy({
-  source: [
-    ORION_EDITOR + "/orion/textview/global.js",
-    ORION_EDITOR + "/orion/textview/eventTarget.js",
-    ORION_EDITOR + "/orion/editor/regex.js",
-    ORION_EDITOR + "/orion/textview/keyBinding.js",
-    ORION_EDITOR + "/orion/textview/annotations.js",
-    ORION_EDITOR + "/orion/textview/rulers.js",
-    ORION_EDITOR + "/orion/textview/undoStack.js",
-    ORION_EDITOR + "/orion/textview/textModel.js",
-    ORION_EDITOR + "/orion/textview/projectionTextModel.js",
-    ORION_EDITOR + "/orion/textview/tooltip.js",
-    ORION_EDITOR + "/orion/textview/textView.js",
-    ORION_EDITOR + "/orion/textview/textDND.js",
-    ORION_EDITOR + "/orion/editor/htmlGrammar.js",
-    ORION_EDITOR + "/orion/editor/textMateStyler.js",
-    ORION_EDITOR + "/examples/textview/textStyler.js",
-  ],
-  dest: js_src,
-});
-
-copy({
-    source: js_src,
-    dest: "orion.js",
-});
-
-var css_src = copy.createDataObject();
-
-copy({
-  source: [
-    ORION_EDITOR + "/orion/textview/textview.css",
-    ORION_EDITOR + "/orion/textview/rulers.css",
-    ORION_EDITOR + "/orion/textview/annotations.css",
-    ORION_EDITOR + "/examples/textview/textstyler.css",
-    ORION_EDITOR + "/examples/editor/htmlStyles.css",
-  ],
-  dest: css_src,
-});
-
-copy({
-    source: css_src,
-    dest: "orion.css",
-});
-
deleted file mode 100644
--- a/browser/devtools/sourceeditor/orion/README
+++ /dev/null
@@ -1,43 +0,0 @@
-# Introduction
-
-This is the Orion editor packaged for Mozilla.
-
-The Orion editor web site: http://www.eclipse.org/orion
-
-# Upgrade
-
-To upgrade Orion to a newer version see the UPGRADE file.
-
-Orion version: git clone from 2012-01-26
-               commit hash 1d1150131dacecc9f4d9eb3cdda9103ea1819045
-
-  + patch for Eclipse Bug 370584 - [Firefox] Edit menu items in context menus
-    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=137d5a8e9bbc0fa204caae74ebd25a7d9d4729bd
-    see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370584
-
-  + patches for Eclipse Bug 370606 - Problems with UndoStack and deletions at
-                                     the beginning of the document
-    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=cec71bddaf32251c34d3728df5da13c130d14f33
-    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=3ce24b94f1d8103b16b9cf16f2f50a6302d43b18
-    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=27177e9a3dc70c20b4877e3eab3adfff1d56e342
-    see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370606
-
-  + patch for Mozilla Bug 730532 - remove CSS2Properties aliases for MozOpacity
-                                   and MozOutline*
-    see https://bugzilla.mozilla.org/show_bug.cgi?id=730532#c3
-
-# License
-
-The following files are licensed according to the contents in the LICENSE
-file:
-  orion.js
-  orion.css
-
-# Theming
-
-The syntax highlighting and the editor UI are themed using a style sheet. The
-default theme file is browser/themes/*/devtools/orion.css - this is based on the
-orion.css found in this folder.
-
-Please note that the orion.css file from this folder is not used. It is kept
-here only as reference.
deleted file mode 100644
--- a/browser/devtools/sourceeditor/orion/UPGRADE
+++ /dev/null
@@ -1,20 +0,0 @@
-Upgrade notes:
-
-1. Get the Orion client source code from:
-http://www.eclipse.org/orion
-
-2. Install Dryice from:
-https://github.com/mozilla/dryice
-
-You also need nodejs for Dryice to run:
-http://nodejs.org
-
-3. Copy Makefile.dryice.js to:
-org.eclipse.orion.client/bundles/
-
-4. Execute Makefile.dryice.js. You should get orion.js and orion.css.
-
-5. Copy the two files back here.
-
-6. Make a new build of Firefox.
-
deleted file mode 100644
--- a/browser/devtools/sourceeditor/orion/orion.css
+++ /dev/null
@@ -1,277 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-.view {
-	background-color: white;
-}
-
-.viewContainer {
-	background-color: #eeeeee;
-	font-family: monospace;
-	font-size: 10pt;
-}
-::-webkit-scrollbar-corner {
-	background-color: #eeeeee;
-}
-
-.viewContent {
-}/* Styles for rulers */
-.ruler {
-	background-color: white;
-}
-.ruler.annotations {
-	border-right: 1px solid lightgray;
-	width: 16px;
-}
-.ruler.folding {
-	border-right: 1px solid lightgray;
-	width: 14px;
-}
-.ruler.lines {
-	border-right: 1px solid lightgray;
-	text-align: right;
-}
-.ruler.overview {
-	border-left: 1px solid lightgray;
-	width: 14px;
-}
-
-/* Styles for the line number ruler */
-.rulerLines {
-}
-.rulerLines.even
-.rulerLines.odd {
-}/* Styles for the annotation ruler (all lines) */
-.annotation {
-}
-.annotation.error,
-.annotation.warning
-.annotation.task,
-.annotation.bookmark,
-.annotation.breakpoint,
-.annotation.collapsed
-.annotation.expanded {
-}
-
-/* Styles for the annotation ruler (first line) */
-.annotationHTML {
-	cursor: pointer;
-	width: 16px;
-	height: 16px;
-	display: inline-block;
-	vertical-align: middle;
-	background-position: center;
-	background-repeat: no-repeat;
-}
-.annotationHTML.error {
-	/* images/error.gif */
-	background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAPVvcvWHiPVucvRuc+ttcfV6f91KVN5LU99PV/FZY/JhaM4oN84pONE4Rd1ATfJLWutVYPRgbdxpcsgWKMgZKs4lNfE/UvE/U+artcpdSc5uXveimslHPuBhW/eJhfV5efaCgO2CgP+/v+PExP///////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACUALAAAAAAQABAAAAZ+wJJwSCwaScgkySgkjTQZTkYzWhadnE5oE+pwqkSshwQqkzxfa4kkQXxEpA9J9EFI1KQGQQBAigYCBA14ExEWF0gXihETeA0QD3AkD5QQg0NsDnAJmwkOd5gYFSQKpXAFDBhqaxgLBwQBBAapq00YEg0UDRKqTGtKSL7Cw8JBADs=");
-}
-.annotationHTML.warning {
-	/* images/warning.gif */
-	background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAP7bc//egf/ij/7ijv/jl/7kl//mnv7lnv/uwf7CTP7DTf7DT/7IW//Na/7Na//NbP7QdP/dmbltAIJNAF03AMSAJMSCLKqASa2DS6uBSquCSrGHTq6ETbCHT7WKUrKIUcCVXL+UXMOYX8GWXsSZYMiib6+ETbOIUcOXX86uhd3Muf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACsALAAAAAAQABAAAAZowJVwSCwaj0ihikRSJYcoBEL0XKlGkcjImQQhJBREKFnyICoThKeE/AAW6AXgdPyUAgrLJBEo0YsbAQyDhAEdRRwDDw8OaA4NDQImRBgFEJdglxAEGEQZKQcHBqOkKRpFF6mqq1WtrUEAOw==");
-}
-.annotationHTML.task {
-	/* images/task.gif */
-	background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQAAN7s4uTy6ICvY423c2WdP2ugR3mqWYeza2ejOl6VNVqPM1aJMURsJ2GaOnKlT8PbsbPDqGmmO1OCLk98LEhxKGWfOWKaN0t2KkJoJf///////wAAAAAAAAAAAAAAAAAAACH5BAEAABoALAAAAAAQABAAAAVmoCaOZDk+UaquDxkNcCxHJHLceI6QleD/vkCmQrIYjkiDMGAhJRzQ6NKRICkKgYJ2qVWQFktCmEBYkCSNZSbQaDckpAl5TCZMSBdtAaDXX0gUUYJRFCQMSYgGDCQQGI6PkBAmkyUhADs=");
-}
-.annotationHTML.bookmark {
-	/* images/bookmark.gif */
-	background-image: url("data:image/gif;base64,R0lGODlhEAAQALMAAP7//+/VNPzZS/vifeumAPrBOOSlHOSuRP///wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAAQABAAAARLEMlJq5Xn3EvIrkenfRIhCB5pmKhRdbAJAGhssuc8n6eJoAKdkOaTAIdEQeWoA1oGsiZhYAnIcqiApVPjElyUbkFSgCkn5XElLYkAADs=");
-}
-.annotationHTML.breakpoint {
-	/* images/breakpoint.gif */
-	background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAFheoFxkoFxnpmt0pmZxpnF7rYyWwmJwpnaFs3aDrWt8rXGBrYycwmZ3mXuNs42cu77F03GIs3aJrYGVu2J5oKCuxeDj6LK/03GLrYieu3aIoIygu6m4zcLN3MTM1m6Rs2aLriRgkSZilXGXtoGcs7LD0QBLhSZikihol3ScubrO2Yaqu5q4xpO0wpm7yabF0ZO9yaXI0r3X3tHj6P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADQALAAAAAAQABAAAAafQJpwSCwWLYZBIDAwWIw0A+FFpW6aRUPCxe1yE4ahhdCCxWSzmSwGgxGeUceKpUqhUCkVa7UK0wgkJCUjJoUmIyWBBEIEGhoeJ4YmJx6OAUIADQ0QIZIhEJoAQgEUFBUgkiAVpZdRCxIPFx8iIh8XDw4FfhYHDhgZHB0dHBkYEwdwUQoTEc3OEwp+QwYHCBMMDBMIB9JESAJLAk5Q5EVBADs=");
-}
-.annotationHTML.collapsed {
-	/* images/collapsed.png */
-	width: 14px;
-	height: 14px;
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWBJREFUeNpi/P//PwMlgImBQkCxASzoAp++fo+6de+Z+fXbD/Jev/nAICoiwKCpqrBBTUlqNR835zJ09YzIYfDxy7eo/cevLmXlYGNQUJAEahZieP3mHcODB08Zfv/4w+BoqR3Nz8O1DKcXzt94HPqXmZlBU1+LgZNfkMHazIOBA0hr6uswgMTP33gYijcMLlx/EMAnLs7w7sc/hg9AG0HgPZB+B8S84hJA+UcBeMPg+at3DJIMnAxZzt5wsUhnXzDdsmIVWB6vAcLCfAys3z4wzN64huEfkJ/uH8IwexOQDQymD2/fgeXxekFLRWHD51evGDhZGRi4WSFSnCwgNjB2Xr1m0AbK4zXAQkdhNdPf3wx3r91g+PruLcOqnasYvn54x3Dv2k0G5r+/GMyB8nijEQTefvoadeH6w9Cbtx8GvH//kUFQkJ9BQ1V+g76m/GphPu5lBA0YenmBYgMAAgwA34GIKjmLxOUAAAAASUVORK5CYII=");
-}
-.annotationHTML.expanded {
-	/* images/expanded.png */
-	width: 14px;
-	height: 14px;	
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT5JREFUeNrUksFKw0AURW+mTWw67SSEiG209U90r4jddFO34l+5U0HdZCHiFwiCOz9AlMSmGEpMOqk1TWJSFGyFbATR2dyZd+Dw3mOENE3xkyP8PYHrBT3OX7uW43ZefA6FUaw1dJPSyrmu1k8KBYOh37Od4XFZLEPXFdRrFMGIw3U9TKMYqw1tb0VjcxLy9eEF425CCIxWE5JcxSQGxCyNloG87gXhwWIHc4J767lTZQw8ShFGSZbxRyaQmZJxd3NRUJ6ffwQNEi6PzG/L2tjdmvFCgcKqKL2F2Olu43MzggDka+IjPuOFI7Sbujn2fUglYKkkzFIi+R0I/QDrGS8UqDX5QkhiOHYfE84hkhSTkGNgOyDJFCzjhYLTq+vDtrG8r1LZtB6fcHtzB+uhD5VWzLx+lvF/8JV/XfAuwADsrJbMGG4l4AAAAABJRU5ErkJggg==");
-}
-.annotationHTML.multiple {
-	/* images/multiple.gif */
-	background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAOdpa+yJiuFYXOFYXeBYXONwded8f+NwdmhwkHB4iPr7/ezx+fP2+2h4kOzy+Wh4iPr8/gCBwTaczjaXyjaYyjaXyTaYyfr8/QCMzQCMzACHxzao2jal2Dak1zag03iAgI/Ckn64fZrHmX+4fZLCianPopPCiarOoqbLlafLlbnXq7nWq6fLlMTcsoCIeJCQcIiIeKCYaJiQcO16ee16evGVlfGWlfahn/ahoPWhn/WhoPe1tP///////wAAAAAAACH5BAEAAD0ALAAAAAAQABAAAAaRwJ5wSCwaj8WYcslcDmObaDTGq1Zjzw4mk+FQIRcFTzaUeTRoj4zHaI+HL0lkLnnxFgsH7zWEWSoTFBMwVlUwQy6JMDCJjYwuQx8tk5MfOzk4OjcfkSssKCkqHzY0MzQ1nEIJJSYkJCcJAQCzAQlDDyIjISMiCQYEAgMGD0MNIMfHDQUHBc3EQgjR0tPSSNY9QQA7");
-}
-.annotationHTML.overlay {
-	/* images/plus.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJEAQvB2JVdrAAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAD1JREFUCNdtjkESADAEAzemf69f66HMqGlOIhYiFRFRtSQBWAY7mzx+EDTL6sSgb1jTk7Q87rxyqe37fXsAa78gLyZnRgEAAAAASUVORK5CYII=");
-	background-position: right bottom;
-	position: relative;
-	top: -16px;
-}
-.annotationHTML.currentBracket {
-	/* images/currentBracket.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLEBULCGQmEKAAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAnklEQVQ4y7VTsRHDIBATJg1HCUzAHEzFBExAzwZsRMkE9gifKhc72ODYibr/+xcnoQdugq0LAujEwmbn0UxQh4OxpjX1XgshwFqLnPM5PQTQGlprWpbl3RhJ/CSQUm7qPYLp7i8cEpRSoJT6ju0lIaVEQgiKMQ4lHHpQayVjzHWCn5jIOcc8z9dMBADvPZxz3SC1tzCI8vgWdvL+VzwB8JSj2GFTyxIAAAAASUVORK5CYII=");
-}
-.annotationHTML.matchingBracket {
-	/* images/matchingBracket.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLEBUMAsuyb3kAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAoklEQVQ4y61TsQ3EIAw80DcI0USKGIApWIsB2IGGKbJPugxBR3VfvfRRCOSTvw7LPuPzGXgI8f0gwAsFu5rXIYMdDiEOIdnKW5YFzjnEGH+bhwA/KKVwmibu0BhRnpEZY1BrHTaVT7fQJZjnGeu63tOAJFNKVEox53yqQZfAWstt27oidgm01ve3UEqBaBjnspG89wgh3LiFgZXHt3Dh23/FGxKViehm0X85AAAAAElFTkSuQmCC");
-}
-.annotationHTML.currentLine {
-	/* images/currentLine.gif */
-	background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQAALxe0bNWzbdZzrlb0KpPx61RybBTy6VLxadNxZGctIeUroyYsG92hHyMqIKRq2l9nmyAoHGDonaIpStXj6q80k1aXf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABYALAAAAAAQABAAAAVCoCWOZGmeKDql5ppOMGXBk/zOoltSNO6XrlXwxIPNYiMGq8SoLC2MaNPygEQkDYdikUg6LQcEoWAICAaA5HPNLoUAADs=");
-}
-
-/* Styles for the overview ruler  */
-.annotationOverview {
-	cursor: pointer;
-	border-radius: 2px;
-	left: 2px;
-	width: 8px;
-}
-.annotationOverview.task {
-	background-color: lightgreen;
-	border: 1px solid green;
-}
-.annotationOverview.breakpoint {
-	background-color: lightblue;
-	border: 1px solid blue;
-}
-.annotationOverview.bookmark {
-	background-color: yellow;
-	border: 1px solid orange;
-}
-.annotationOverview.error {
-	background-color: lightcoral;
-	border: 1px solid darkred;
-}
-.annotationOverview.warning {
-	background-color: Gold;
-	border: 1px solid black;
-}
-.annotationOverview.currentBracket {
-	background-color: lightgray;
-	border: 1px solid red;
-}
-.annotationOverview.matchingBracket {
-	background-color: lightgray;
-	border: 1px solid red;
-}
-.annotationOverview.currentLine {
-	background-color: #EAF2FE;
-	border: 1px solid black;
-}
-
-/* Styles for text range */
-.annotationRange {
-	background-repeat: repeat-x;
- 	background-position: left bottom;
-}
-.annotationRange.task {
-	/* images/squiggly_task.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLDhEoIrb7JmcAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAGUlEQVQI12NggIH/DGdhDCM45z/DfyiBAADgdQjGhI/4DAAAAABJRU5ErkJggg==");
-}
-.annotationRange.breakpoint {
-	/* images/squiggly_breakpoint.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLDhEqHTKradgAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAIklEQVQI11XJMQ0AMAzAMGMafwrFlD19+sUKIJTFo9k+B/kQ+Qr2bIVKOgAAAABJRU5ErkJggg==");
-}
-.annotationRange.bookmark {
-	/* images/squiggly_bookmark.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
-}
-.annotationRange.error {
-	/* images/squiggly_error.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==");
-}
-.annotationRange.warning {
-	/* images/squiggly_warning.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
-}
-.annotationRange.currentBracket {
-}
-.annotationRange.matchingBracket {
-	outline: 1px solid red;
-}
-
-/* Styles for lines of text */
-.annotationLine {
-}
-.annotationLine.currentLine {
-	background-color: #EAF2FE;
-}
-
-.token_singleline_comment {
-	color: green;
-}
-
-.token_multiline_comment {
-	color: green;
-}
-
-.token_doc_comment {
-	color: #00008F;
-}
-
-.token_doc_html_markup {
-	color: #7F7F9F;
-}
-
-.token_doc_tag {
-	color: #7F9FBF;
-}
-
-.token_task_tag {
-	color: #7F9FBF;
-}
-
-.token_string {
-	color: blue;
-}
-
-.token_keyword {
-	color: darkred;
-	font-weight: bold;
-}
-
-.token_space {
-	/* images/white_space.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAABnRSTlMA/wAAAACkwsAdAAAAIUlEQVR4nGP4z8CAC+GUIEXuABhgkTuABEiRw2cmae4EAH05X7xDolNRAAAAAElFTkSuQmCC");
-	background-repeat: no-repeat;
- 	background-position: center center;
-}
-
-.token_tab {
-	/* images/white_tab.png */
-	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAJCAIAAACJ2loDAAAABnRSTlMA/wD/AP83WBt9AAAAMklEQVR4nGP4TwRgoK6i52c3bz5w6zMSA6tJn28d2Lx589nnCAYu63AaSLxJRLoJPwAAeNk0aG4opfMAAAAASUVORK5CYII=");
-	background-repeat: no-repeat;
- 	background-position: left center;
-}
-
-.line_caret {
-	background-color: #EAF2FE;
-}
-
-/* Styling for html syntax highlighting */
-.entity-name-tag {
-	color: #3f7f7f;
-}
-
-.entity-other-attribute-name {
-	color: #7f007f;
-}
-
-.punctuation-definition-comment {
-	color: #3f5fbf;
-}
-
-.comment {
-	color: #3f5fbf
-}
-
-.string-quoted {
-	color: #2a00ff;
-	font-style: italic;
-}
-
-.invalid {
-	color: red;
-	font-weight: bold;
-}
\ No newline at end of file
deleted file mode 100644
--- a/browser/devtools/sourceeditor/orion/orion.js
+++ /dev/null
@@ -1,12303 +0,0 @@
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- *		Mihai Sucan (Mozilla Foundation) - fix for Bug#364214
- */
-
-/*global window */
-
-/**
- * Evaluates the definition function and mixes in the returned module with
- * the module specified by <code>moduleName</code>.
- * <p>
- * This function is intented to by used when RequireJS is not available.
- * </p>
- *
- * @param {String} name The mixin module name.
- * @param {String[]} deps The array of dependency names.
- * @param {Function} callback The definition function.
- */
-if (!window.define) {
-	window.define = function(name, deps, callback) {
-		var module = this;
-		var split = (name || "").split("/"), i, j;
-		for (i = 0; i < split.length - 1; i++) {
-			module = module[split[i]] = (module[split[i]] || {});
-		}
-		var depModules = [], depModule;
-		for (j = 0; j < deps.length; j++) {
-			depModule = this;
-			split = deps[j].split("/");
-			for (i = 0; i < split.length - 1; i++) {
-				depModule = depModule[split[i]] = (depModule[split[i]] || {});
-			}
-			depModules.push(depModule);
-		}
-		var newModule = callback.apply(this, depModules);
-		for (var p in newModule) {
-			if (newModule.hasOwnProperty(p)) {
-				module[p] = newModule[p];
-			}
-		}
-	};
-}
-
-/**
- * Require/get the defined modules.
- * <p>
- * This function is intented to by used when RequireJS is not available.
- * </p>
- *
- * @param {String[]|String} deps The array of dependency names. This can also be
- * a string, a single dependency name.
- * @param {Function} [callback] Optional, the callback function to execute when
- * multiple dependencies are required. The callback arguments will have
- * references to each module in the same order as the deps array.
- * @returns {Object|undefined} If the deps parameter is a string, then this
- * function returns the required module definition, otherwise undefined is
- * returned.
- */
-if (!window.require) {
-	window.require = function(deps, callback) {
-		var depsArr = typeof deps === "string" ? [deps] : deps;
-		var depModules = [], depModule, split, i, j;
-		for (j = 0; j < depsArr.length; j++) {
-			depModule = this;
-			split = depsArr[j].split("/");
-			for (i = 0; i < split.length - 1; i++) {
-				depModule = depModule[split[i]] = (depModule[split[i]] || {});
-			}
-			depModules.push(depModule);
-		}
-		if (callback) {
-			callback.apply(this, depModules);
-		}
-		return typeof deps === "string" ? depModules[0] : undefined;
-	};
-}/*******************************************************************************
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- ******************************************************************************/
- 
-/*global define */
-define("orion/textview/eventTarget", [], function() {
-	/** 
-	 * Constructs a new EventTarget object.
-	 * 
-	 * @class 
-	 * @name orion.textview.EventTarget
-	 */
-	function EventTarget() {
-	}
-	/**
-	 * Adds in the event target interface into the specified object.
-	 *
-	 * @param {Object} object The object to add in the event target interface.
-	 */
-	EventTarget.addMixin = function(object) {
-		var proto = EventTarget.prototype;
-		for (var p in proto) {
-			if (proto.hasOwnProperty(p)) {
-				object[p] = proto[p];
-			}
-		}
-	};
-	EventTarget.prototype = /** @lends orion.textview.EventTarget.prototype */ {
-		/**
-		 * Adds an event listener to this event target.
-		 * 
-		 * @param {String} type The event type.
-		 * @param {Function|EventListener} listener The function or the EventListener that will be executed when the event happens. 
-		 * @param {Boolean} [useCapture=false] <code>true</code> if the listener should be trigged in the capture phase.
-		 * 
-		 * @see #removeEventListener
-		 */
-		addEventListener: function(type, listener, useCapture) {
-			if (!this._eventTypes) { this._eventTypes = {}; }
-			var state = this._eventTypes[type];
-			if (!state) {
-				state = this._eventTypes[type] = {level: 0, listeners: []};
-			}
-			var listeners = state.listeners;
-			listeners.push({listener: listener, useCapture: useCapture});
-		},
-		/**
-		 * Dispatches the given event to the listeners added to this event target.
-		 * @param {Event} evt The event to dispatch.
-		 */
-		dispatchEvent: function(evt) {
-			if (!this._eventTypes) { return; }
-			var type = evt.type;
-			var state = this._eventTypes[type];
-			if (state) {
-				var listeners = state.listeners;
-				try {
-					state.level++;
-					if (listeners) {
-						for (var i=0, len=listeners.length; i < len; i++) {
-							if (listeners[i]) {
-								var l = listeners[i].listener;
-								if (typeof l === "function") {
-									l.call(this, evt);
-								} else if (l.handleEvent && typeof l.handleEvent === "function") {
-									l.handleEvent(evt);
-								}
-							}
-						}
-					}
-				} finally {
-					state.level--;
-					if (state.compact && state.level === 0) {
-						for (var j=listeners.length - 1; j >= 0; j--) {
-							if (!listeners[j]) {
-								listeners.splice(j, 1);
-							}
-						}
-						if (listeners.length === 0) {
-							delete this._eventTypes[type];
-						}
-						state.compact = false;
-					}
-				}
-			}
-		},
-		/**
-		 * Returns whether there is a listener for the specified event type.
-		 * 
-		 * @param {String} type The event type
-		 * 
-		 * @see #addEventListener
-		 * @see #removeEventListener
-		 */
-		isListening: function(type) {
-			if (!this._eventTypes) { return false; }
-			return this._eventTypes[type] !== undefined;
-		},		
-		/**
-		 * Removes an event listener from the event target.
-		 * <p>
-		 * All the parameters must be the same ones used to add the listener.
-		 * </p>
-		 * 
-		 * @param {String} type The event type
-		 * @param {Function|EventListener} listener The function or the EventListener that will be executed when the event happens. 
-		 * @param {Boolean} [useCapture=false] <code>true</code> if the listener should be trigged in the capture phase.
-		 * 
-		 * @see #addEventListener
-		 */
-		removeEventListener: function(type, listener, useCapture){
-			if (!this._eventTypes) { return; }
-			var state = this._eventTypes[type];
-			if (state) {
-				var listeners = state.listeners;
-				for (var i=0, len=listeners.length; i < len; i++) {
-					var l = listeners[i];
-					if (l && l.listener === listener && l.useCapture === useCapture) {
-						if (state.level !== 0) {
-							listeners[i] = null;
-							state.compact = true;
-						} else {
-							listeners.splice(i, 1);
-						}
-						break;
-					}
-				}
-				if (listeners.length === 0) {
-					delete this._eventTypes[type];
-				}
-			}
-		}
-	};
-	return {EventTarget: EventTarget};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-/*global define */
-/*jslint browser:true regexp:false*/
-/**
- * @name orion.editor.regex
- * @class Utilities for dealing with regular expressions.
- * @description Utilities for dealing with regular expressions.
- */
-define("orion/editor/regex", [], function() {
-	/**
-	 * @methodOf orion.editor.regex
-	 * @static
-	 * @description Escapes regex special characters in the input string.
-	 * @param {String} str The string to escape.
-	 * @returns {String} A copy of <code>str</code> with regex special characters escaped.
-	 */
-	function escape(str) {
-		return str.replace(/([\\$\^*\/+?\.\(\)|{}\[\]])/g, "\\$&");
-	}
-
-	/**
-	 * @methodOf orion.editor.regex
-	 * @static
-	 * @description Parses a pattern and flags out of a regex literal string.
-	 * @param {String} str The string to parse. Should look something like <code>"/ab+c/"</code> or <code>"/ab+c/i"</code>.
-	 * @returns {Object} If <code>str</code> looks like a regex literal, returns an object with properties
-	 * <code><dl>
-	 * <dt>pattern</dt><dd>{String}</dd>
-	 * <dt>flags</dt><dd>{String}</dd>
-	 * </dl></code> otherwise returns <code>null</code>.
-	 */
-	function parse(str) {
-		var regexp = /^\s*\/(.+)\/([gim]{0,3})\s*$/.exec(str);
-		if (regexp) {
-			return {
-				pattern : regexp[1],
-				flags : regexp[2]
-			};
-		}
-		return null;
-	}
-
-	return {
-		escape: escape,
-		parse: parse
-	};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- ******************************************************************************/
-
-/*global window define */
-
-define("orion/textview/keyBinding", [], function() {
-	var isMac = window.navigator.platform.indexOf("Mac") !== -1;
-
-	/**
-	 * Constructs a new key binding with the given key code and modifiers.
-	 * 
-	 * @param {String|Number} keyCode the key code.
-	 * @param {Boolean} mod1 the primary modifier (usually Command on Mac and Control on other platforms).
-	 * @param {Boolean} mod2 the secondary modifier (usually Shift).
-	 * @param {Boolean} mod3 the third modifier (usually Alt).
-	 * @param {Boolean} mod4 the fourth modifier (usually Control on the Mac).
-	 * 
-	 * @class A KeyBinding represents of a key code and a modifier state that can be triggered by the user using the keyboard.
-	 * @name orion.textview.KeyBinding
-	 * 
-	 * @property {String|Number} keyCode The key code.
-	 * @property {Boolean} mod1 The primary modifier (usually Command on Mac and Control on other platforms).
-	 * @property {Boolean} mod2 The secondary modifier (usually Shift).
-	 * @property {Boolean} mod3 The third modifier (usually Alt).
-	 * @property {Boolean} mod4 The fourth modifier (usually Control on the Mac).
-	 *
-	 * @see orion.textview.TextView#setKeyBinding
-	 */
-	function KeyBinding (keyCode, mod1, mod2, mod3, mod4) {
-		if (typeof(keyCode) === "string") {
-			this.keyCode = keyCode.toUpperCase().charCodeAt(0);
-		} else {
-			this.keyCode = keyCode;
-		}
-		this.mod1 = mod1 !== undefined && mod1 !== null ? mod1 : false;
-		this.mod2 = mod2 !== undefined && mod2 !== null ? mod2 : false;
-		this.mod3 = mod3 !== undefined && mod3 !== null ? mod3 : false;
-		this.mod4 = mod4 !== undefined && mod4 !== null ? mod4 : false;
-	}
-	KeyBinding.prototype = /** @lends orion.textview.KeyBinding.prototype */ {
-		/**
-		 * Returns whether this key binding matches the given key event.
-		 * 
-		 * @param e the key event.
-		 * @returns {Boolean} <code>true</code> whether the key binding matches the key event.
-		 */
-		match: function (e) {
-			if (this.keyCode === e.keyCode) {
-				var mod1 = isMac ? e.metaKey : e.ctrlKey;
-				if (this.mod1 !== mod1) { return false; }
-				if (this.mod2 !== e.shiftKey) { return false; }
-				if (this.mod3 !== e.altKey) { return false; }
-				if (isMac && this.mod4 !== e.ctrlKey) { return false; }
-				return true;
-			}
-			return false;
-		},
-		/**
-		 * Returns whether this key binding is the same as the given parameter.
-		 * 
-		 * @param {orion.textview.KeyBinding} kb the key binding to compare with.
-		 * @returns {Boolean} whether or not the parameter and the receiver describe the same key binding.
-		 */
-		equals: function(kb) {
-			if (!kb) { return false; }
-			if (this.keyCode !== kb.keyCode) { return false; }
-			if (this.mod1 !== kb.mod1) { return false; }
-			if (this.mod2 !== kb.mod2) { return false; }
-			if (this.mod3 !== kb.mod3) { return false; }
-			if (this.mod4 !== kb.mod4) { return false; }
-			return true;
-		} 
-	};
-	return {KeyBinding: KeyBinding};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- ******************************************************************************/
-
-/*global define */
-
-define("orion/textview/annotations", ['orion/textview/eventTarget'], function(mEventTarget) {
-	/**
-	 * @class This object represents a decoration attached to a range of text. Annotations are added to a
-	 * <code>AnnotationModel</code> which is attached to a <code>TextModel</code>.
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.AnnotationModel}<br/>
-	 * {@link orion.textview.Ruler}<br/>
-	 * </p>		 
-	 * @name orion.textview.Annotation
-	 * 
-	 * @property {String} type The annotation type (for example, orion.annotation.error).
-	 * @property {Number} start The start offset of the annotation in the text model.
-	 * @property {Number} end The end offset of the annotation in the text model.
-	 * @property {String} html The HTML displayed for the annotation.
-	 * @property {String} title The text description for the annotation.
-	 * @property {orion.textview.Style} style The style information for the annotation used in the annotations ruler and tooltips.
-	 * @property {orion.textview.Style} overviewStyle The style information for the annotation used in the overview ruler.
-	 * @property {orion.textview.Style} rangeStyle The style information for the annotation used in the text view to decorate a range of text.
-	 * @property {orion.textview.Style} lineStyle The style information for the annotation used in the text view to decorate a line of text.
-	 */
-	/**
-	 * Constructs a new folding annotation.
-	 * 
-	 * @param {orion.textview.ProjectionTextModel} projectionModel The projection text model.
-	 * @param {String} type The annotation type.
-	 * @param {Number} start The start offset of the annotation in the text model.
-	 * @param {Number} end The end offset of the annotation in the text model.
-	 * @param {String} expandedHTML The HTML displayed for this annotation when it is expanded.
-	 * @param {orion.textview.Style} expandedStyle The style information for the annotation when it is expanded.
-	 * @param {String} collapsedHTML The HTML displayed for this annotation when it is collapsed.
-	 * @param {orion.textview.Style} collapsedStyle The style information for the annotation when it is collapsed.
-	 * 
-	 * @class This object represents a folding annotation.
-	 * @name orion.textview.FoldingAnnotation
-	 */
-	function FoldingAnnotation (projectionModel, type, start, end, expandedHTML, expandedStyle, collapsedHTML, collapsedStyle) {
-		this.type = type;
-		this.start = start;
-		this.end = end;
-		this._projectionModel = projectionModel;
-		this._expandedHTML = this.html = expandedHTML;
-		this._expandedStyle = this.style = expandedStyle;
-		this._collapsedHTML = collapsedHTML;
-		this._collapsedStyle = collapsedStyle;
-		this.expanded = true;
-	}
-	
-	FoldingAnnotation.prototype = /** @lends orion.textview.FoldingAnnotation.prototype */ {
-		/**
-		 * Collapses the annotation.
-		 */
-		collapse: function () {
-			if (!this.expanded) { return; }
-			this.expanded = false;
-			this.html = this._collapsedHTML;
-			this.style = this._collapsedStyle;
-			var projectionModel = this._projectionModel;
-			var baseModel = projectionModel.getBaseModel();
-			this._projection = {
-				start: baseModel.getLineStart(baseModel.getLineAtOffset(this.start) + 1),
-				end: baseModel.getLineEnd(baseModel.getLineAtOffset(this.end), true)
-			};
-			projectionModel.addProjection(this._projection);
-		},
-		/**
-		 * Expands the annotation.
-		 */
-		expand: function () {
-			if (this.expanded) { return; }
-			this.expanded = true;
-			this.html = this._expandedHTML;
-			this.style = this._expandedStyle;
-			this._projectionModel.removeProjection(this._projection);
-		}
-	};
-	
-	/** 
-	 * Constructs a new AnnotationTypeList object.
-	 * 
-	 * @class 
-	 * @name orion.textview.AnnotationTypeList
-	 */
-	function AnnotationTypeList () {
-	}
-	/**
-	 * Adds in the annotation type interface into the specified object.
-	 *
-	 * @param {Object} object The object to add in the annotation type interface.
-	 */
-	AnnotationTypeList.addMixin = function(object) {
-		var proto = AnnotationTypeList.prototype;
-		for (var p in proto) {
-			if (proto.hasOwnProperty(p)) {
-				object[p] = proto[p];
-			}
-		}
-	};	
-	AnnotationTypeList.prototype = /** @lends orion.textview.AnnotationTypeList.prototype */ {
-		/**
-		 * Adds an annotation type to the receiver.
-		 * <p>
-		 * Only annotations of the specified types will be shown by
-		 * the receiver.
-		 * </p>
-		 *
-		 * @param {Object} type the annotation type to be shown
-		 * 
-		 * @see #removeAnnotationType
-		 * @see #isAnnotationTypeVisible
-		 */
-		addAnnotationType: function(type) {
-			if (!this._annotationTypes) { this._annotationTypes = []; }
-			this._annotationTypes.push(type);
-		},
-		/**
-		 * Gets the annotation type priority.  The priority is determined by the
-		 * order the annotation type is added to the receiver.  Annotation types
-		 * added first have higher priority.
-		 * <p>
-		 * Returns <code>0</code> if the annotation type is not added.
-		 * </p>
-		 *
-		 * @param {Object} type the annotation type
-		 * 
-		 * @see #addAnnotationType
-		 * @see #removeAnnotationType
-		 * @see #isAnnotationTypeVisible
-		 */
-		getAnnotationTypePriority: function(type) {
-			if (this._annotationTypes) { 
-				for (var i = 0; i < this._annotationTypes.length; i++) {
-					if (this._annotationTypes[i] === type) {
-						return i + 1;
-					}
-				}
-			}
-			return 0;
-		},
-		/**
-		 * Returns an array of annotations in the specified annotation model for the given range of text sorted by type.
-		 *
-		 * @param {orion.textview.AnnotationModel} annotationModel the annotation model.
-		 * @param {Number} start the start offset of the range.
-		 * @param {Number} end the end offset of the range.
-		 * @return {orion.textview.Annotation[]} an annotation array.
-		 */
-		getAnnotationsByType: function(annotationModel, start, end) {
-			var iter = annotationModel.getAnnotations(start, end);
-			var annotation, annotations = [];
-			while (iter.hasNext()) {
-				annotation = iter.next();
-				var priority = this.getAnnotationTypePriority(annotation.type);
-				if (priority === 0) { continue; }
-				annotations.push(annotation);
-			}
-			var self = this;
-			annotations.sort(function(a, b) {
-				return self.getAnnotationTypePriority(a.type) - self.getAnnotationTypePriority(b.type);
-			});
-			return annotations;
-		},
-		/**
-		 * Returns whether the receiver shows annotations of the specified type.
-		 *
-		 * @param {Object} type the annotation type 
-		 * @returns {Boolean} whether the specified annotation type is shown
-		 * 
-		 * @see #addAnnotationType
-		 * @see #removeAnnotationType
-		 */
-		isAnnotationTypeVisible: function(type) {
-			return this.getAnnotationTypePriority(type) !== 0;
-		},
-		/**
-		 * Removes an annotation type from the receiver.
-		 *
-		 * @param {Object} type the annotation type to be removed
-		 * 
-		 * @see #addAnnotationType
-		 * @see #isAnnotationTypeVisible
-		 */
-		removeAnnotationType: function(type) {
-			if (!this._annotationTypes) { return; }
-			for (var i = 0; i < this._annotationTypes.length; i++) {
-				if (this._annotationTypes[i] === type) {
-					this._annotationTypes.splice(i, 1);
-					break;
-				}
-			}
-		}
-	};
-	
-	/**
-	 * Constructs an annotation model.
-	 * 
-	 * @param {textModel} textModel The text model.
-	 * 
-	 * @class This object manages annotations for a <code>TextModel</code>.
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.Annotation}<br/>
-	 * {@link orion.textview.TextModel}<br/> 
-	 * </p>	
-	 * @name orion.textview.AnnotationModel
-	 * @borrows orion.textview.EventTarget#addEventListener as #addEventListener
-	 * @borrows orion.textview.EventTarget#removeEventListener as #removeEventListener
-	 * @borrows orion.textview.EventTarget#dispatchEvent as #dispatchEvent
-	 */
-	function AnnotationModel(textModel) {
-		this._annotations = [];
-		var self = this;
-		this._listener = {
-			onChanged: function(modelChangedEvent) {
-				self._onChanged(modelChangedEvent);
-			}
-		};
-		this.setTextModel(textModel);
-	}
-
-	AnnotationModel.prototype = /** @lends orion.textview.AnnotationModel.prototype */ {
-		/**
-		 * Adds an annotation to the annotation model. 
-		 * <p>The annotation model listeners are notified of this change.</p>
-		 * 
-		 * @param {orion.textview.Annotation} annotation the annotation to be added.
-		 * 
-		 * @see #removeAnnotation
-		 */
-		addAnnotation: function(annotation) {
-			if (!annotation) { return; }
-			var annotations = this._annotations;
-			var index = this._binarySearch(annotations, annotation.start);
-			annotations.splice(index, 0, annotation);
-			var e = {
-				type: "Changed",
-				added: [annotation],
-				removed: [],
-				changed: []
-			};
-			this.onChanged(e);
-		},
-		/**
-		 * Returns the text model. 
-		 * 
-		 * @return {orion.textview.TextModel} The text model.
-		 * 
-		 * @see #setTextModel
-		 */
-		getTextModel: function() {
-			return this._model;
-		},
-		/**
-		 * @class This object represents an annotation iterator.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.AnnotationModel#getAnnotations}<br/>
-		 * </p>		 
-		 * @name orion.textview.AnnotationIterator
-		 * 
-		 * @property {Function} hasNext Determines whether there are more annotations in the iterator.
-		 * @property {Function} next Returns the next annotation in the iterator.
-		 */		
-		/**
-		 * Returns an iterator of annotations for the given range of text.
-		 *
-		 * @param {Number} start the start offset of the range.
-		 * @param {Number} end the end offset of the range.
-		 * @return {orion.textview.AnnotationIterator} an annotation iterartor.
-		 */
-		getAnnotations: function(start, end) {
-			var annotations = this._annotations, current;
-			//TODO binary search does not work for range intersection when there are overlaping ranges, need interval search tree for this
-			var i = 0;
-			var skip = function() {
-				while (i < annotations.length) {
-					var a =  annotations[i++];
-					if ((start === a.start) || (start > a.start ? start < a.end : a.start < end)) {
-						return a;
-					}
-					if (a.start >= end) {
-						break;
-					}
-				}
-				return null;
-			};
-			current = skip();
-			return {
-				next: function() {
-					var result = current;
-					if (result) { current = skip(); }
-					return result;					
-				},
-				hasNext: function() {
-					return current !== null;
-				}
-			};
-		},
-		/**
-		 * Notifies the annotation model that the given annotation has been modified.
-		 * <p>The annotation model listeners are notified of this change.</p>
-		 * 
-		 * @param {orion.textview.Annotation} annotation the modified annotation.
-		 * 
-		 * @see #addAnnotation
-		 */
-		modifyAnnotation: function(annotation) {
-			if (!annotation) { return; }
-			var index = this._getAnnotationIndex(annotation);
-			if (index < 0) { return; }
-			var e = {
-				type: "Changed",
-				added: [],
-				removed: [],
-				changed: [annotation]
-			};
-			this.onChanged(e);
-		},
-		/**
-		 * Notifies all listeners that the annotation model has changed.
-		 *
-		 * @param {orion.textview.Annotation[]} added The list of annotation being added to the model.
-		 * @param {orion.textview.Annotation[]} changed The list of annotation modified in the model.
-		 * @param {orion.textview.Annotation[]} removed The list of annotation being removed from the model.
-		 * @param {ModelChangedEvent} textModelChangedEvent the text model changed event that trigger this change, can be null if the change was trigger by a method call (for example, {@link #addAnnotation}).
-		 */
-		onChanged: function(e) {
-			return this.dispatchEvent(e);
-		},
-		/**
-		 * Removes all annotations of the given <code>type</code>. All annotations
-		 * are removed if the type is not specified. 
-		 * <p>The annotation model listeners are notified of this change.  Only one changed event is generated.</p>
-		 * 
-		 * @param {Object} type the type of annotations to be removed.
-		 * 
-		 * @see #removeAnnotation
-		 */
-		removeAnnotations: function(type) {
-			var annotations = this._annotations;
-			var removed, i; 
-			if (type) {
-				removed = [];
-				for (i = annotations.length - 1; i >= 0; i--) {
-					var annotation = annotations[i];
-					if (annotation.type === type) {
-						annotations.splice(i, 1);
-					}
-					removed.splice(0, 0, annotation);
-				}
-			} else {
-				removed = annotations;
-				annotations = [];
-			}
-			var e = {
-				type: "Changed",
-				removed: removed,
-				added: [],
-				changed: []
-			};
-			this.onChanged(e);
-		},
-		/**
-		 * Removes an annotation from the annotation model. 
-		 * <p>The annotation model listeners are notified of this change.</p>
-		 * 
-		 * @param {orion.textview.Annotation} annotation the annotation to be removed.
-		 * 
-		 * @see #addAnnotation
-		 */
-		removeAnnotation: function(annotation) {
-			if (!annotation) { return; }
-			var index = this._getAnnotationIndex(annotation);
-			if (index < 0) { return; }
-			var e = {
-				type: "Changed",
-				removed: this._annotations.splice(index, 1),
-				added: [],
-				changed: []
-			};
-			this.onChanged(e);
-		},
-		/**
-		 * Removes and adds the specifed annotations to the annotation model. 
-		 * <p>The annotation model listeners are notified of this change.  Only one changed event is generated.</p>
-		 * 
-		 * @param {orion.textview.Annotation} remove the annotations to be removed.
-		 * @param {orion.textview.Annotation} add the annotations to be added.
-		 * 
-		 * @see #addAnnotation
-		 * @see #removeAnnotation
-		 */
-		replaceAnnotations: function(remove, add) {
-			var annotations = this._annotations, i, index, annotation, removed = [];
-			if (remove) {
-				for (i = remove.length - 1; i >= 0; i--) {
-					annotation = remove[i];
-					index = this._getAnnotationIndex(annotation);
-					if (index < 0) { continue; }
-					annotations.splice(index, 1);
-					removed.splice(0, 0, annotation);
-				}
-			}
-			if (!add) { add = []; }
-			for (i = 0; i < add.length; i++) {
-				annotation = add[i];
-				index = this._binarySearch(annotations, annotation.start);
-				annotations.splice(index, 0, annotation);
-			}
-			var e = {
-				type: "Changed",
-				removed: removed,
-				added: add,
-				changed: []
-			};
-			this.onChanged(e);
-		},
-		/**
-		 * Sets the text model of the annotation model.  The annotation
-		 * model listens for changes in the text model to update and remove
-		 * annotations that are affected by the change.
-		 * 
-		 * @param {orion.textview.TextModel} textModel the text model.
-		 * 
-		 * @see #getTextModel
-		 */
-		setTextModel: function(textModel) {
-			if (this._model) {
-				this._model.removeEventListener("Changed", this._listener.onChanged);
-			}
-			this._model = textModel;
-			if (this._model) {
-				this._model.addEventListener("Changed", this._listener.onChanged);
-			}
-		},
-		/** @ignore */
-		_binarySearch: function (array, offset) {
-			var high = array.length, low = -1, index;
-			while (high - low > 1) {
-				index = Math.floor((high + low) / 2);
-				if (offset <= array[index].start) {
-					high = index;
-				} else {
-					low = index;
-				}
-			}
-			return high;
-		},
-		/** @ignore */
-		_getAnnotationIndex: function(annotation) {
-			var annotations = this._annotations;
-			var index = this._binarySearch(annotations, annotation.start);
-			while (index < annotations.length && annotations[index].start === annotation.start) {
-				if (annotations[index] === annotation) {
-					return index;
-				}
-				index++;
-			}
-			return -1;
-		},
-		/** @ignore */
-		_onChanged: function(modelChangedEvent) {
-			var start = modelChangedEvent.start;
-			var addedCharCount = modelChangedEvent.addedCharCount;
-			var removedCharCount = modelChangedEvent.removedCharCount;
-			var annotations = this._annotations, end = start + removedCharCount;
-			//TODO binary search does not work for range intersection when there are overlaping ranges, need interval search tree for this
-			var startIndex = 0;
-			if (!(0 <= startIndex && startIndex < annotations.length)) { return; }
-			var e = {
-				type: "Changed",
-				added: [],
-				removed: [],
-				changed: [],
-				textModelChangedEvent: modelChangedEvent
-			};
-			var changeCount = addedCharCount - removedCharCount, i;
-			for (i = startIndex; i < annotations.length; i++) {
-				var annotation = annotations[i];
-				if (annotation.start >= end) {
-					annotation.start += changeCount;
-					annotation.end += changeCount;
-					e.changed.push(annotation);
-				} else if (annotation.end <= start) {
-					//nothing
-				} else if (annotation.start < start && end < annotation.end) {
-					annotation.end += changeCount;
-					e.changed.push(annotation);
-				} else {
-					annotations.splice(i, 1);
-					e.removed.push(annotation);
-					i--;
-				}
-			}
-			if (e.added.length > 0 || e.removed.length > 0 || e.changed.length > 0) {
-				this.onChanged(e);
-			}
-		}
-	};
-	mEventTarget.EventTarget.addMixin(AnnotationModel.prototype);
-
-	/**
-	 * Constructs a new styler for annotations.
-	 * 
-	 * @param {orion.textview.TextView} view The styler view.
-	 * @param {orion.textview.AnnotationModel} view The styler annotation model.
-	 * 
-	 * @class This object represents a styler for annotation attached to a text view.
-	 * @name orion.textview.AnnotationStyler
-	 * @borrows orion.textview.AnnotationTypeList#addAnnotationType as #addAnnotationType
-	 * @borrows orion.textview.AnnotationTypeList#getAnnotationTypePriority as #getAnnotationTypePriority
-	 * @borrows orion.textview.AnnotationTypeList#getAnnotationsByType as #getAnnotationsByType
-	 * @borrows orion.textview.AnnotationTypeList#isAnnotationTypeVisible as #isAnnotationTypeVisible
-	 * @borrows orion.textview.AnnotationTypeList#removeAnnotationType as #removeAnnotationType
-	 */
-	function AnnotationStyler (view, annotationModel) {
-		this._view = view;
-		this._annotationModel = annotationModel;
-		var self = this;
-		this._listener = {
-			onDestroy: function(e) {
-				self._onDestroy(e);
-			},
-			onLineStyle: function(e) {
-				self._onLineStyle(e);
-			},
-			onChanged: function(e) {
-				self._onAnnotationModelChanged(e);
-			}
-		};
-		view.addEventListener("Destroy", this._listener.onDestroy);
-		view.addEventListener("LineStyle", this._listener.onLineStyle);
-		annotationModel.addEventListener("Changed", this._listener.onChanged);
-	}
-	AnnotationStyler.prototype = /** @lends orion.textview.AnnotationStyler.prototype */ {
-		/**
-		 * Destroys the styler. 
-		 * <p>
-		 * Removes all listeners added by this styler.
-		 * </p>
-		 */
-		destroy: function() {
-			var view = this._view;
-			if (view) {
-				view.removeEventListener("Destroy", this._listener.onDestroy);
-				view.removeEventListener("LineStyle", this._listener.onLineStyle);
-				this.view = null;
-			}
-			var annotationModel = this._annotationModel;
-			if (annotationModel) {
-				annotationModel.removeEventListener("Changed", this._listener.onChanged);
-				annotationModel = null;
-			}
-		},
-		_mergeStyle: function(result, style) {
-			if (style) {
-				if (!result) { result = {}; }
-				if (result.styleClass && style.styleClass && result.styleClass !== style.styleClass) {
-					result.styleClass += " " + style.styleClass;
-				} else {
-					result.styleClass = style.styleClass;
-				}
-				var prop;
-				if (style.style) {
-					if (!result.style) { result.style  = {}; }
-					for (prop in style.style) {
-						if (!result.style[prop]) {
-							result.style[prop] = style.style[prop];
-						}
-					}
-				}
-				if (style.attributes) {
-					if (!result.attributes) { result.attributes  = {}; }
-					for (prop in style.attributes) {
-						if (!result.attributes[prop]) {
-							result.attributes[prop] = style.attributes[prop];
-						}
-					}
-				}
-			}
-			return result;
-		},
-		_mergeStyleRanges: function(ranges, styleRange) {
-			if (!ranges) { return; }
-			for (var i=0; i<ranges.length; i++) {
-				var range = ranges[i];
-				if (styleRange.end <= range.start) { break; }
-				if (styleRange.start >= range.end) { continue; }
-				var mergedStyle = this._mergeStyle({}, range.style);
-				mergedStyle = this._mergeStyle(mergedStyle, styleRange.style);
-				if (styleRange.start <= range.start && styleRange.end >= range.end) {
-					ranges[i] = {start: range.start, end: range.end, style: mergedStyle};
-				} else if (styleRange.start > range.start && styleRange.end < range.end) {
-					ranges.splice(i, 1,
-						{start: range.start, end: styleRange.start, style: range.style},
-						{start: styleRange.start, end: styleRange.end, style: mergedStyle},
-						{start: styleRange.end, end: range.end, style: range.style});
-					i += 2;
-				} else if (styleRange.start > range.start) {
-					ranges.splice(i, 1,
-						{start: range.start, end: styleRange.start, style: range.style},
-						{start: styleRange.start, end: range.end, style: mergedStyle});
-					i += 1;
-				} else if (styleRange.end < range.end) {
-					ranges.splice(i, 1,
-						{start: range.start, end: styleRange.end, style: mergedStyle},
-						{start: styleRange.end, end: range.end, style: range.style});
-					i += 1;
-				}
-			}
-		},
-		_onAnnotationModelChanged: function(e) {
-			if (e.textModelChangedEvent) {
-				return;
-			}
-			var view = this._view;
-			if (!view) { return; }
-			var self = this;
-			var model = view.getModel();
-			function redraw(changes) {
-				for (var i = 0; i < changes.length; i++) {
-					if (!self.isAnnotationTypeVisible(changes[i].type)) { continue; }
-					var start = changes[i].start;
-					var end = changes[i].end;
-					if (model.getBaseModel) {
-						start = model.mapOffset(start, true);
-						end = model.mapOffset(end, true);
-					}
-					if (start !== -1 && end !== -1) {
-						view.redrawRange(start, end);
-					}
-				}
-			}
-			redraw(e.added);
-			redraw(e.removed);
-			redraw(e.changed);
-		},
-		_onDestroy: function(e) {
-			this.destroy();
-		},
-		_onLineStyle: function (e) {
-			var annotationModel = this._annotationModel;
-			var viewModel = this._view.getModel();
-			var baseModel = annotationModel.getTextModel();
-			var start = e.lineStart;
-			var end = e.lineStart + e.lineText.length;
-			if (baseModel !== viewModel) {
-				start = viewModel.mapOffset(start);
-				end = viewModel.mapOffset(end);
-			}
-			var annotations = annotationModel.getAnnotations(start, end);
-			while (annotations.hasNext()) {
-				var annotation = annotations.next();
-				if (!this.isAnnotationTypeVisible(annotation.type)) { continue; }
-				if (annotation.rangeStyle) {
-					var annotationStart = annotation.start;
-					var annotationEnd = annotation.end;
-					if (baseModel !== viewModel) {
-						annotationStart = viewModel.mapOffset(annotationStart, true);
-						annotationEnd = viewModel.mapOffset(annotationEnd, true);
-					}
-					this._mergeStyleRanges(e.ranges, {start: annotationStart, end: annotationEnd, style: annotation.rangeStyle});
-				}
-				if (annotation.lineStyle) {
-					e.style = this._mergeStyle({}, e.style);
-					e.style = this._mergeStyle(e.style, annotation.lineStyle);
-				}
-			}
-		}
-	};
-	AnnotationTypeList.addMixin(AnnotationStyler.prototype);
-	
-	return {
-		FoldingAnnotation: FoldingAnnotation,
-		AnnotationTypeList: AnnotationTypeList,
-		AnnotationModel: AnnotationModel,
-		AnnotationStyler: AnnotationStyler
-	};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-
-/*global define setTimeout clearTimeout setInterval clearInterval Node */
-
-define("orion/textview/rulers", ['orion/textview/annotations', 'orion/textview/tooltip'], function(mAnnotations, mTooltip) {
-
-	/**
-	 * Constructs a new ruler. 
-	 * <p>
-	 * The default implementation does not implement all the methods in the interface
-	 * and is useful only for objects implementing rulers.
-	 * <p/>
-	 * 
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {String} [rulerOverview="page"] the overview for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle] the style for the ruler. 
-	 * 
-	 * @class This interface represents a ruler for the text view.
-	 * <p>
-	 * A Ruler is a graphical element that is placed either on the left or on the right side of 
-	 * the view. It can be used to provide the view with per line decoration such as line numbering,
-	 * bookmarks, breakpoints, folding disclosures, etc. 
-	 * </p><p>
-	 * There are two types of rulers: page and document. A page ruler only shows the content for the lines that are
-	 * visible, while a document ruler always shows the whole content.
-	 * </p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.LineNumberRuler}<br/>
-	 * {@link orion.textview.AnnotationRuler}<br/>
-	 * {@link orion.textview.OverviewRuler}<br/> 
-	 * {@link orion.textview.TextView}<br/>
-	 * {@link orion.textview.TextView#addRuler}
-	 * </p>		 
-	 * @name orion.textview.Ruler
-	 * @borrows orion.textview.AnnotationTypeList#addAnnotationType as #addAnnotationType
-	 * @borrows orion.textview.AnnotationTypeList#getAnnotationTypePriority as #getAnnotationTypePriority
-	 * @borrows orion.textview.AnnotationTypeList#getAnnotationsByType as #getAnnotationsByType
-	 * @borrows orion.textview.AnnotationTypeList#isAnnotationTypeVisible as #isAnnotationTypeVisible
-	 * @borrows orion.textview.AnnotationTypeList#removeAnnotationType as #removeAnnotationType
-	 */
-	function Ruler (annotationModel, rulerLocation, rulerOverview, rulerStyle) {
-		this._location = rulerLocation || "left";
-		this._overview = rulerOverview || "page";
-		this._rulerStyle = rulerStyle;
-		this._view = null;
-		var self = this;
-		this._listener = {
-			onTextModelChanged: function(e) {
-				self._onTextModelChanged(e);
-			},
-			onAnnotationModelChanged: function(e) {
-				self._onAnnotationModelChanged(e);
-			}
-		};
-		this.setAnnotationModel(annotationModel);
-	}
-	Ruler.prototype = /** @lends orion.textview.Ruler.prototype */ {
-		/**
-		 * Returns the annotations for a given line range merging multiple
-		 * annotations when necessary.
-		 * <p>
-		 * This method is called by the text view when the ruler is redrawn.
-		 * </p>
-		 *
-		 * @param {Number} startLine the start line index
-		 * @param {Number} endLine the end line index
-		 * @return {orion.textview.Annotation[]} the annotations for the line range. The array might be sparse.
-		 */
-		getAnnotations: function(startLine, endLine) {
-			var annotationModel = this._annotationModel;
-			if (!annotationModel) { return []; }
-			var model = this._view.getModel();
-			var start = model.getLineStart(startLine);
-			var end = model.getLineEnd(endLine - 1);
-			var baseModel = model;
-			if (model.getBaseModel) {
-				baseModel = model.getBaseModel();
-				start = model.mapOffset(start);
-				end = model.mapOffset(end);
-			}
-			var result = [];
-			var annotations = this.getAnnotationsByType(annotationModel, start, end);
-			for (var i = 0; i < annotations.length; i++) {
-				var annotation = annotations[i];
-				var annotationLineStart = baseModel.getLineAtOffset(annotation.start);
-				var annotationLineEnd = baseModel.getLineAtOffset(Math.max(annotation.start, annotation.end - 1));
-				for (var lineIndex = annotationLineStart; lineIndex<=annotationLineEnd; lineIndex++) {
-					var visualLineIndex = lineIndex;
-					if (model !== baseModel) {
-						var ls = baseModel.getLineStart(lineIndex);
-						ls = model.mapOffset(ls, true);
-						if (ls === -1) { continue; }
-						visualLineIndex = model.getLineAtOffset(ls);
-					}
-					if (!(startLine <= visualLineIndex && visualLineIndex < endLine)) { continue; }
-					var rulerAnnotation = this._mergeAnnotation(result[visualLineIndex], annotation, lineIndex - annotationLineStart, annotationLineEnd - annotationLineStart + 1);
-					if (rulerAnnotation) {
-						result[visualLineIndex] = rulerAnnotation;
-					}
-				}
-			}
-			if (!this._multiAnnotation && this._multiAnnotationOverlay) {
-				for (var k in result) {
-					if (result[k]._multiple) {
-						result[k].html = result[k].html + this._multiAnnotationOverlay.html;
-					}
-				}
-			}
-			return result;
-		},
-		/**
-		 * Returns the annotation model.
-		 *
-		 * @returns {orion.textview.AnnotationModel} the ruler annotation model.
-		 *
-		 * @see #setAnnotationModel
-		 */
-		getAnnotationModel: function() {
-			return this._annotationModel;
-		},
-		/**
-		 * Returns the ruler location.
-		 *
-		 * @returns {String} the ruler location, which is either "left" or "right".
-		 *
-		 * @see #getOverview
-		 */
-		getLocation: function() {
-			return this._location;
-		},
-		/**
-		 * Returns the ruler overview type.
-		 *
-		 * @returns {String} the overview type, which is either "page" or "document".
-		 *
-		 * @see #getLocation
-		 */
-		getOverview: function() {
-			return this._overview;
-		},
-		/**
-		 * Returns the style information for the ruler.
-		 *
-		 * @returns {orion.textview.Style} the style information.
-		 */
-		getRulerStyle: function() {
-			return this._rulerStyle;
-		},
-		/**
-		 * Returns the widest annotation which determines the width of the ruler.
-		 * <p>
-		 * If the ruler does not have a fixed width it should provide the widest
-		 * annotation to avoid the ruler from changing size as the view scrolls.
-		 * </p>
-		 * <p>
-		 * This method is called by the text view when the ruler is redrawn.
-		 * </p>
-		 *
-		 * @returns {orion.textview.Annotation} the widest annotation.
-		 *
-		 * @see #getAnnotations
-		 */
-		getWidestAnnotation: function() {
-			return null;
-		},
-		/**
-		 * Sets the annotation model for the ruler.
-		 *
-		 * @param {orion.textview.AnnotationModel} annotationModel the annotation model.
-		 *
-		 * @see #getAnnotationModel
-		 */
-		setAnnotationModel: function (annotationModel) {
-			if (this._annotationModel) {
-				this._annotationModel.removEventListener("Changed", this._listener.onAnnotationModelChanged); 
-			}
-			this._annotationModel = annotationModel;
-			if (this._annotationModel) {
-				this._annotationModel.addEventListener("Changed", this._listener.onAnnotationModelChanged); 
-			}
-		},
-		/**
-		 * Sets the annotation that is displayed when a given line contains multiple
-		 * annotations.  This annotation is used when there are different types of
-		 * annotations in a given line.
-		 *
-		 * @param {orion.textview.Annotation} annotation the annotation for lines with multiple annotations.
-		 * 
-		 * @see #setMultiAnnotationOverlay
-		 */
-		setMultiAnnotation: function(annotation) {
-			this._multiAnnotation = annotation;
-		},
-		/**
-		 * Sets the annotation that overlays a line with multiple annotations.  This annotation is displayed on
-		 * top of the computed annotation for a given line when there are multiple annotations of the same type
-		 * in the line. It is also used when the multiple annotation is not set.
-		 *
-		 * @param {orion.textview.Annotation} annotation the annotation overlay for lines with multiple annotations.
-		 * 
-		 * @see #setMultiAnnotation
-		 */
-		setMultiAnnotationOverlay: function(annotation) {
-			this._multiAnnotationOverlay = annotation;
-		},
-		/**
-		 * Sets the view for the ruler.
-		 * <p>
-		 * This method is called by the text view when the ruler
-		 * is added to the view.
-		 * </p>
-		 *
-		 * @param {orion.textview.TextView} view the text view.
-		 */
-		setView: function (view) {
-			if (this._onTextModelChanged && this._view) {
-				this._view.removeEventListener("ModelChanged", this._listener.onTextModelChanged); 
-			}
-			this._view = view;
-			if (this._onTextModelChanged && this._view) {
-				this._view.addEventListener("ModelChanged", this._listener.onTextModelChanged);
-			}
-		},
-		/**
-		 * This event is sent when the user clicks a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the click event.
-		 */
-		onClick: function(lineIndex, e) {
-		},
-		/**
-		 * This event is sent when the user double clicks a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the double click event.
-		 */
-		onDblClick: function(lineIndex, e) {
-		},
-		/**
-		 * This event is sent when the user moves the mouse over a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the mouse move event.
-		 */
-		onMouseMove: function(lineIndex, e) {
-			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
-			if (!tooltip) { return; }
-			if (tooltip.isVisible() && this._tooltipLineIndex === lineIndex) { return; }
-			this._tooltipLineIndex = lineIndex;
-			var self = this;
-			tooltip.setTarget({
-				y: e.clientY,
-				getTooltipInfo: function() {
-					return self._getTooltipInfo(self._tooltipLineIndex, this.y);
-				}
-			});
-		},
-		/**
-		 * This event is sent when the mouse pointer enters a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the mouse over event.
-		 */
-		onMouseOver: function(lineIndex, e) {
-			this.onMouseMove(lineIndex, e);
-		},
-		/**
-		 * This event is sent when the mouse pointer exits a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the mouse out event.
-		 */
-		onMouseOut: function(lineIndex, e) {
-			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
-			if (!tooltip) { return; }
-			tooltip.setTarget(null);
-		},
-		/** @ignore */
-		_getTooltipInfo: function(lineIndex, y) {
-			if (lineIndex === undefined) { return; }
-			var view = this._view;
-			var model = view.getModel();
-			var annotationModel = this._annotationModel;
-			var annotations = [];
-			if (annotationModel) {
-				var start = model.getLineStart(lineIndex);
-				var end = model.getLineEnd(lineIndex);
-				if (model.getBaseModel) {
-					start = model.mapOffset(start);
-					end = model.mapOffset(end);
-				}
-				annotations = this.getAnnotationsByType(annotationModel, start, end);
-			}
-			var contents = this._getTooltipContents(lineIndex, annotations);
-			if (!contents) { return null; }
-			var info = {
-				contents: contents,
-				anchor: this.getLocation()
-			};
-			var rect = view.getClientArea();
-			if (this.getOverview() === "document") {
-				rect.y = view.convert({y: y}, "view", "document").y;
-			} else {
-				rect.y = view.getLocationAtOffset(model.getLineStart(lineIndex)).y;
-			}
-			view.convert(rect, "document", "page");
-			info.x = rect.x;
-			info.y = rect.y;
-			if (info.anchor === "right") {
-				info.x += rect.width;
-			}
-			info.maxWidth = rect.width;
-			info.maxHeight = rect.height - (rect.y - view._parent.getBoundingClientRect().top);
-			return info;
-		},
-		/** @ignore */
-		_getTooltipContents: function(lineIndex, annotations) {
-			return annotations;
-		},
-		/** @ignore */
-		_onAnnotationModelChanged: function(e) {
-			var view = this._view;
-			if (!view) { return; }
-			var model = view.getModel(), self = this;
-			var lineCount = model.getLineCount();
-			if (e.textModelChangedEvent) {
-				var start = e.textModelChangedEvent.start;
-				if (model.getBaseModel) { start = model.mapOffset(start, true); }
-				var startLine = model.getLineAtOffset(start);
-				view.redrawLines(startLine, lineCount, self);
-				return;
-			}
-			function redraw(changes) {
-				for (var i = 0; i < changes.length; i++) {
-					if (!self.isAnnotationTypeVisible(changes[i].type)) { continue; }
-					var start = changes[i].start;
-					var end = changes[i].end;
-					if (model.getBaseModel) {
-						start = model.mapOffset(start, true);
-						end = model.mapOffset(end, true);
-					}
-					if (start !== -1 && end !== -1) {
-						view.redrawLines(model.getLineAtOffset(start), model.getLineAtOffset(Math.max(start, end - 1)) + 1, self);
-					}
-				}
-			}
-			redraw(e.added);
-			redraw(e.removed);
-			redraw(e.changed);
-		},
-		/** @ignore */
-		_mergeAnnotation: function(result, annotation, annotationLineIndex, annotationLineCount) {
-			if (!result) { result = {}; }
-			if (annotationLineIndex === 0) {
-				if (result.html && annotation.html) {
-					if (annotation.html !== result.html) {
-						if (!result._multiple && this._multiAnnotation) {
-							result.html = this._multiAnnotation.html;
-						}
-					} 
-					result._multiple = true;
-				} else {
-					result.html = annotation.html;
-				}
-			}
-			result.style = this._mergeStyle(result.style, annotation.style);
-			return result;
-		},
-		/** @ignore */
-		_mergeStyle: function(result, style) {
-			if (style) {
-				if (!result) { result = {}; }
-				if (result.styleClass && style.styleClass && result.styleClass !== style.styleClass) {
-					result.styleClass += " " + style.styleClass;
-				} else {
-					result.styleClass = style.styleClass;
-				}
-				var prop;
-				if (style.style) {
-					if (!result.style) { result.style  = {}; }
-					for (prop in style.style) {
-						if (!result.style[prop]) {
-							result.style[prop] = style.style[prop];
-						}
-					}
-				}
-				if (style.attributes) {
-					if (!result.attributes) { result.attributes  = {}; }
-					for (prop in style.attributes) {
-						if (!result.attributes[prop]) {
-							result.attributes[prop] = style.attributes[prop];
-						}
-					}
-				}
-			}
-			return result;
-		}
-	};
-	mAnnotations.AnnotationTypeList.addMixin(Ruler.prototype);
-
-	/**
-	 * Constructs a new line numbering ruler. 
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 * @param {orion.textview.Style} [oddStyle={style: {backgroundColor: "white"}] the style for lines with odd line index.
-	 * @param {orion.textview.Style} [evenStyle={backgroundColor: "white"}] the style for lines with even line index.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements a line numbering ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.Ruler}
-	 * </p>
-	 * @name orion.textview.LineNumberRuler
-	 */
-	function LineNumberRuler (annotationModel, rulerLocation, rulerStyle, oddStyle, evenStyle) {
-		Ruler.call(this, annotationModel, rulerLocation, "page", rulerStyle);
-		this._oddStyle = oddStyle || {style: {backgroundColor: "white"}};
-		this._evenStyle = evenStyle || {style: {backgroundColor: "white"}};
-		this._numOfDigits = 0;
-	}
-	LineNumberRuler.prototype = new Ruler(); 
-	/** @ignore */
-	LineNumberRuler.prototype.getAnnotations = function(startLine, endLine) {
-		var result = Ruler.prototype.getAnnotations.call(this, startLine, endLine);
-		var model = this._view.getModel();
-		for (var lineIndex = startLine; lineIndex < endLine; lineIndex++) {
-			var style = lineIndex & 1 ? this._oddStyle : this._evenStyle;
-			var mapLine = lineIndex;
-			if (model.getBaseModel) {
-				var lineStart = model.getLineStart(mapLine);
-				mapLine = model.getBaseModel().getLineAtOffset(model.mapOffset(lineStart));
-			}
-			if (!result[lineIndex]) { result[lineIndex] = {}; }
-			result[lineIndex].html = (mapLine + 1) + "";
-			if (!result[lineIndex].style) { result[lineIndex].style = style; }
-		}
-		return result;
-	};
-	/** @ignore */
-	LineNumberRuler.prototype.getWidestAnnotation = function() {
-		var lineCount = this._view.getModel().getLineCount();
-		return this.getAnnotations(lineCount - 1, lineCount)[lineCount - 1];
-	};
-	/** @ignore */
-	LineNumberRuler.prototype._onTextModelChanged = function(e) {
-		var start = e.start;
-		var model = this._view.getModel();
-		var lineCount = model.getBaseModel ? model.getBaseModel().getLineCount() : model.getLineCount();
-		var numOfDigits = (lineCount+"").length;
-		if (this._numOfDigits !== numOfDigits) {
-			this._numOfDigits = numOfDigits;
-			var startLine = model.getLineAtOffset(start);
-			this._view.redrawLines(startLine,  model.getLineCount(), this);
-		}
-	};
-	
-	/** 
-	 * @class This is class represents an annotation for the AnnotationRuler. 
-	 * <p> 
-	 * <b>See:</b><br/> 
-	 * {@link orion.textview.AnnotationRuler}
-	 * </p> 
-	 * 
-	 * @name orion.textview.Annotation 
-	 * 
-	 * @property {String} [html=""] The html content for the annotation, typically contains an image.
-	 * @property {orion.textview.Style} [style] the style for the annotation.
-	 * @property {orion.textview.Style} [overviewStyle] the style for the annotation in the overview ruler.
-	 */ 
-	/**
-	 * Constructs a new annotation ruler. 
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 * @param {orion.textview.Annotation} [defaultAnnotation] the default annotation.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements an annotation ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.Ruler}<br/>
-	 * {@link orion.textview.Annotation}
-	 * </p>
-	 * @name orion.textview.AnnotationRuler
-	 */
-	function AnnotationRuler (annotationModel, rulerLocation, rulerStyle) {
-		Ruler.call(this, annotationModel, rulerLocation, "page", rulerStyle);
-	}
-	AnnotationRuler.prototype = new Ruler();
-	
-	/**
-	 * Constructs a new overview ruler. 
-	 * <p>
-	 * The overview ruler is used in conjunction with a AnnotationRuler, for each annotation in the 
-	 * AnnotationRuler this ruler displays a mark in the overview. Clicking on the mark causes the 
-	 * view to scroll to the annotated line.
-	 * </p>
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements an overview ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.AnnotationRuler} <br/>
-	 * {@link orion.textview.Ruler} 
-	 * </p>
-	 * @name orion.textview.OverviewRuler
-	 */
-	function OverviewRuler (annotationModel, rulerLocation, rulerStyle) {
-		Ruler.call(this, annotationModel, rulerLocation, "document", rulerStyle);
-	}
-	OverviewRuler.prototype = new Ruler();
-	
-	/** @ignore */
-	OverviewRuler.prototype.getRulerStyle = function() {
-		var result = {style: {lineHeight: "1px", fontSize: "1px"}};
-		result = this._mergeStyle(result, this._rulerStyle);
-		return result;
-	};
-	/** @ignore */	
-	OverviewRuler.prototype.onClick = function(lineIndex, e) {
-		if (lineIndex === undefined) { return; }
-		this._view.setTopIndex(lineIndex);
-	};
-	/** @ignore */
-	OverviewRuler.prototype._getTooltipContents = function(lineIndex, annotations) {
-		if (annotations.length === 0) {
-			var model = this._view.getModel();
-			var mapLine = lineIndex;
-			if (model.getBaseModel) {
-				var lineStart = model.getLineStart(mapLine);
-				mapLine = model.getBaseModel().getLineAtOffset(model.mapOffset(lineStart));
-			}
-			return "Line: " + (mapLine + 1);
-		}
-		return Ruler.prototype._getTooltipContents.call(this, lineIndex, annotations);
-	};
-	/** @ignore */
-	OverviewRuler.prototype._mergeAnnotation = function(previousAnnotation, annotation, annotationLineIndex, annotationLineCount) {
-		if (annotationLineIndex !== 0) { return undefined; }
-		var result = previousAnnotation;
-		if (!result) {
-			//TODO annotationLineCount does not work when there are folded lines
-			var height = 3 * annotationLineCount;
-			result = {html: "&nbsp;", style: { style: {height: height + "px"}}};
-			result.style = this._mergeStyle(result.style, annotation.overviewStyle);
-		}
-		return result;
-	};
-
-	/**
-	 * Constructs a new folding ruler. 
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements an overview ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.AnnotationRuler} <br/>
-	 * {@link orion.textview.Ruler} 
-	 * </p>
-	 * @name orion.textview.OverviewRuler
-	 */
-	function FoldingRuler (annotationModel, rulerLocation, rulerStyle) {
-		AnnotationRuler.call(this, annotationModel, rulerLocation, rulerStyle);
-	}
-	FoldingRuler.prototype = new AnnotationRuler();
-	
-	/** @ignore */
-	FoldingRuler.prototype.onClick =  function(lineIndex, e) {
-		if (lineIndex === undefined) { return; }
-		var annotationModel = this._annotationModel;
-		if (!annotationModel) { return; }
-		var view = this._view;
-		var model = view.getModel();
-		var start = model.getLineStart(lineIndex);
-		var end = model.getLineEnd(lineIndex, true);
-		if (model.getBaseModel) {
-			start = model.mapOffset(start);
-			end = model.mapOffset(end);
-		}
-		var annotation, iter = annotationModel.getAnnotations(start, end);
-		while (!annotation && iter.hasNext()) {
-			var a = iter.next();
-			if (!this.isAnnotationTypeVisible(a.type)) { continue; }
-			annotation = a;
-		}
-		if (annotation) {
-			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
-			if (tooltip) {
-				tooltip.setTarget(null);
-			}
-			if (annotation.expanded) {
-				annotation.collapse();
-			} else {
-				annotation.expand();
-			}
-			this._annotationModel.modifyAnnotation(annotation);
-		}
-	};
-	/** @ignore */
-	FoldingRuler.prototype._getTooltipContents = function(lineIndex, annotations) {
-		if (annotations.length === 1) {
-			if (annotations[0].expanded) {
-				return null;
-			}
-		}
-		return AnnotationRuler.prototype._getTooltipContents.call(this, lineIndex, annotations);
-	};
-	/** @ignore */
-	FoldingRuler.prototype._onAnnotationModelChanged = function(e) {
-		if (e.textModelChangedEvent) {
-			AnnotationRuler.prototype._onAnnotationModelChanged.call(this, e);
-			return;
-		}
-		var view = this._view;
-		if (!view) { return; }
-		var model = view.getModel(), self = this, i;
-		var lineCount = model.getLineCount(), lineIndex = lineCount;
-		function redraw(changes) {
-			for (i = 0; i < changes.length; i++) {
-				if (!self.isAnnotationTypeVisible(changes[i].type)) { continue; }
-				var start = changes[i].start;
-				if (model.getBaseModel) {
-					start = model.mapOffset(start, true);
-				}
-				if (start !== -1) {
-					lineIndex = Math.min(lineIndex, model.getLineAtOffset(start));
-				}
-			}
-		}
-		redraw(e.added);
-		redraw(e.removed);
-		redraw(e.changed);
-		var rulers = view.getRulers();
-		for (i = 0; i < rulers.length; i++) {
-			view.redrawLines(lineIndex, lineCount, rulers[i]);
-		}
-	};
-	
-	return {
-		Ruler: Ruler,
-		AnnotationRuler: AnnotationRuler,
-		LineNumberRuler: LineNumberRuler,
-		OverviewRuler: OverviewRuler,
-		FoldingRuler: FoldingRuler
-	};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-
-/*global define */
-
-define("orion/textview/undoStack", [], function() {
-
-	/** 
-	 * Constructs a new Change object.
-	 * 
-	 * @class 
-	 * @name orion.textview.Change
-	 * @private
-	 */
-	function Change(offset, text, previousText) {
-		this.offset = offset;
-		this.text = text;
-		this.previousText = previousText;
-	}
-	Change.prototype = {
-		/** @ignore */
-		undo: function (view, select) {
-			this._doUndoRedo(this.offset, this.previousText, this.text, view, select);
-		},
-		/** @ignore */
-		redo: function (view, select) {
-			this._doUndoRedo(this.offset, this.text, this.previousText, view, select);
-		},
-		_doUndoRedo: function(offset, text, previousText, view, select) {
-			var model = view.getModel();
-			/* 
-			* TODO UndoStack should be changing the text in the base model.
-			* This is code needs to change when modifications in the base
-			* model are supported properly by the projection model.
-			*/
-			if (model.mapOffset && view.annotationModel) {
-				var mapOffset = model.mapOffset(offset, true);
-				if (mapOffset < 0) {
-					var annotationModel = view.annotationModel;
-					var iter = annotationModel.getAnnotations(offset, offset + 1);
-					while (iter.hasNext()) {
-						var annotation = iter.next();
-						if (annotation.type === "orion.annotation.folding") {
-							annotation.expand();
-							mapOffset = model.mapOffset(offset, true);
-							break;
-						}
-					}
-				}
-				if (mapOffset < 0) { return; }
-				offset = mapOffset;
-			}
-			view.setText(text, offset, offset + previousText.length);
-			if (select) {
-				view.setSelection(offset, offset + text.length);
-			}
-		}
-	};
-
-	/** 
-	 * Constructs a new CompoundChange object.
-	 * 
-	 * @class 
-	 * @name orion.textview.CompoundChange
-	 * @private
-	 */
-	function CompoundChange () {
-		this.changes = [];
-	}
-	CompoundChange.prototype = {
-		/** @ignore */
-		add: function (change) {
-			this.changes.push(change);
-		},
-		/** @ignore */
-		end: function (view) {
-			this.endSelection = view.getSelection();
-			this.endCaret = view.getCaretOffset();
-		},
-		/** @ignore */
-		undo: function (view, select) {
-			for (var i=this.changes.length - 1; i >= 0; i--) {
-				this.changes[i].undo(view, false);
-			}
-			if (select) {
-				var start = this.startSelection.start;
-				var end = this.startSelection.end;
-				view.setSelection(this.startCaret ? start : end, this.startCaret ? end : start);
-			}
-		},
-		/** @ignore */
-		redo: function (view, select) {
-			for (var i = 0; i < this.changes.length; i++) {
-				this.changes[i].redo(view, false);
-			}
-			if (select) {
-				var start = this.endSelection.start;
-				var end = this.endSelection.end;
-				view.setSelection(this.endCaret ? start : end, this.endCaret ? end : start);
-			}
-		},
-		/** @ignore */
-		start: function (view) {
-			this.startSelection = view.getSelection();
-			this.startCaret = view.getCaretOffset();
-		}
-	};
-
-	/**
-	 * Constructs a new UndoStack on a text view.
-	 *
-	 * @param {orion.textview.TextView} view the text view for the undo stack.
-	 * @param {Number} [size=100] the size for the undo stack.
-	 *
-	 * @name orion.textview.UndoStack
-	 * @class The UndoStack is used to record the history of a text model associated to an view. Every
-	 * change to the model is added to stack, allowing the application to undo and redo these changes.
-	 *
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.TextView}<br/>
-	 * </p>
-	 */
-	function UndoStack (view, size) {
-		this.view = view;
-		this.size = size !== undefined ? size : 100;
-		this.reset();
-		var model = view.getModel();
-		if (model.getBaseModel) {
-			model = model.getBaseModel();
-		}
-		this.model = model;
-		var self = this;
-		this._listener = {
-			onChanging: function(e) {
-				self._onChanging(e);
-			},
-			onDestroy: function(e) {
-				self._onDestroy(e);
-			}
-		};
-		model.addEventListener("Changing", this._listener.onChanging);
-		view.addEventListener("Destroy", this._listener.onDestroy);
-	}
-	UndoStack.prototype = /** @lends orion.textview.UndoStack.prototype */ {
-		/**
-		 * Adds a change to the stack.
-		 * 
-		 * @param change the change to add.
-		 * @param {Number} change.offset the offset of the change
-		 * @param {String} change.text the new text of the change
-		 * @param {String} change.previousText the previous text of the change
-		 */
-		add: function (change) {
-			if (this.compoundChange) {
-				this.compoundChange.add(change);
-			} else {
-				var length = this.stack.length;
-				this.stack.splice(this.index, length-this.index, change);
-				this.index++;
-				if (this.stack.length > this.size) {
-					this.stack.shift();
-					this.index--;
-					this.cleanIndex--;
-				}
-			}
-		},
-		/** 
-		 * Marks the current state of the stack as clean.
-		 *
-		 * <p>
-		 * This function is typically called when the content of view associated with the stack is saved.
-		 * </p>
-		 *
-		 * @see #isClean
-		 */
-		markClean: function() {
-			this.endCompoundChange();
-			this._commitUndo();
-			this.cleanIndex = this.index;
-		},
-		/**
-		 * Returns true if current state of stack is the same
-		 * as the state when markClean() was called.
-		 *
-		 * <p>
-		 * For example, the application calls markClean(), then calls undo() four times and redo() four times.
-		 * At this point isClean() returns true.  
-		 * </p>
-		 * <p>
-		 * This function is typically called to determine if the content of the view associated with the stack
-		 * has changed since the last time it was saved.
-		 * </p>
-		 *
-		 * @return {Boolean} returns if the state is the same as the state when markClean() was called.
-		 *
-		 * @see #markClean
-		 */
-		isClean: function() {
-			return this.cleanIndex === this.getSize().undo;
-		},
-		/**
-		 * Returns true if there is at least one change to undo.
-		 *
-		 * @return {Boolean} returns true if there is at least one change to undo.
-		 *
-		 * @see #canRedo
-		 * @see #undo
-		 */
-		canUndo: function() {
-			return this.getSize().undo > 0;
-		},
-		/**
-		 * Returns true if there is at least one change to redo.
-		 *
-		 * @return {Boolean} returns true if there is at least one change to redo.
-		 *
-		 * @see #canUndo
-		 * @see #redo
-		 */
-		canRedo: function() {
-			return this.getSize().redo > 0;
-		},
-		/**
-		 * Finishes a compound change.
-		 *
-		 * @see #startCompoundChange
-		 */
-		endCompoundChange: function() {
-			if (this.compoundChange) {
-				this.compoundChange.end(this.view);
-			}
-			this.compoundChange = undefined;
-		},
-		/**
-		 * Returns the sizes of the stack.
-		 *
-		 * @return {object} a object where object.undo is the number of changes that can be un-done, 
-		 *  and object.redo is the number of changes that can be re-done.
-		 *
-		 * @see #canUndo
-		 * @see #canRedo
-		 */
-		getSize: function() {
-			var index = this.index;
-			var length = this.stack.length;
-			if (this._undoStart !== undefined) {
-				index++;
-			}
-			return {undo: index, redo: (length - index)};
-		},
-		/**
-		 * Undo the last change in the stack.
-		 *
-		 * @return {Boolean} returns true if a change was un-done.
-		 *
-		 * @see #redo
-		 * @see #canUndo
-		 */
-		undo: function() {
-			this._commitUndo();
-			if (this.index <= 0) {
-				return false;
-			}
-			var change = this.stack[--this.index];
-			this._ignoreUndo = true;
-			change.undo(this.view, true);
-			this._ignoreUndo = false;
-			return true;
-		},
-		/**
-		 * Redo the last change in the stack.
-		 *
-		 * @return {Boolean} returns true if a change was re-done.
-		 *
-		 * @see #undo
-		 * @see #canRedo
-		 */
-		redo: function() {
-			this._commitUndo();
-			if (this.index >= this.stack.length) {
-				return false;
-			}
-			var change = this.stack[this.index++];
-			this._ignoreUndo = true;
-			change.redo(this.view, true);
-			this._ignoreUndo = false;
-			return true;
-		},
-		/**
-		 * Reset the stack to its original state. All changes in the stack are thrown away.
-		 */
-		reset: function() {
-			this.index = this.cleanIndex = 0;
-			this.stack = [];
-			this._undoStart = undefined;
-			this._undoText = "";
-			this._undoType = 0;
-			this._ignoreUndo = false;
-			this._compoundChange = undefined;
-		},
-		/**
-		 * Starts a compound change. 
-		 * <p>
-		 * All changes added to stack from the time startCompoundChange() is called
-		 * to the time that endCompoundChange() is called are compound on one change that can be un-done or re-done
-		 * with one single call to undo() or redo().
-		 * </p>
-		 *
-		 * @see #endCompoundChange
-		 */
-		startCompoundChange: function() {
-			this._commitUndo();
-			var change = new CompoundChange();
-			this.add(change);
-			this.compoundChange = change;
-			this.compoundChange.start(this.view);
-		},
-		_commitUndo: function () {
-			if (this._undoStart !== undefined) {
-				if (this._undoType === -1) {
-					this.add(new Change(this._undoStart, "", this._undoText, ""));
-				} else {
-					this.add(new Change(this._undoStart, this._undoText, ""));
-				}
-				this._undoStart = undefined;
-				this._undoText = "";
-				this._undoType = 0;
-			}
-		},
-		_onDestroy: function(evt) {
-			this.model.removeEventListener("Changing", this._listener.onChanging);
-			this.view.removeEventListener("Destroy", this._listener.onDestroy);
-		},
-		_onChanging: function(e) {
-			var newText = e.text;
-			var start = e.start;
-			var removedCharCount = e.removedCharCount;
-			var addedCharCount = e.addedCharCount;
-			if (this._ignoreUndo) {
-				return;
-			}
-			if (this._undoStart !== undefined && 
-				!((addedCharCount === 1 && removedCharCount === 0 && this._undoType === 1 && start === this._undoStart + this._undoText.length) ||
-					(addedCharCount === 0 && removedCharCount === 1 && this._undoType === -1 && (((start + 1) === this._undoStart) || (start === this._undoStart)))))
-			{
-				this._commitUndo();
-			}
-			if (!this.compoundChange) {
-				if (addedCharCount === 1 && removedCharCount === 0) {
-					if (this._undoStart === undefined) {
-						this._undoStart = start;
-					}
-					this._undoText = this._undoText + newText;
-					this._undoType = 1;
-					return;
-				} else if (addedCharCount === 0 && removedCharCount === 1) {
-					var deleting = this._undoText.length > 0 && this._undoStart === start;
-					this._undoStart = start;
-					this._undoType = -1;
-					if (deleting) {
-						this._undoText = this._undoText + this.model.getText(start, start + removedCharCount);
-					} else {
-						this._undoText = this.model.getText(start, start + removedCharCount) + this._undoText;
-					}
-					return;
-				}
-			}
-			this.add(new Change(start, newText, this.model.getText(start, start + removedCharCount)));
-		}
-	};
-	
-	return {
-		UndoStack: UndoStack
-	};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- ******************************************************************************/
- 
-/*global define window*/
-
-define("orion/textview/textModel", ['orion/textview/eventTarget'], function(mEventTarget) {
-	var isWindows = window.navigator.platform.indexOf("Win") !== -1;
-
-	/**
-	 * Constructs a new TextModel with the given text and default line delimiter.
-	 *
-	 * @param {String} [text=""] the text that the model will store
-	 * @param {String} [lineDelimiter=platform delimiter] the line delimiter used when inserting new lines to the model.
-	 *
-	 * @name orion.textview.TextModel
-	 * @class The TextModel is an interface that provides text for the view. Applications may
-	 * implement the TextModel interface to provide a custom store for the view content. The
-	 * view interacts with its text model in order to access and update the text that is being
-	 * displayed and edited in the view. This is the default implementation.
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.TextView}<br/>
-	 * {@link orion.textview.TextView#setModel}
-	 * </p>
-	 * @borrows orion.textview.EventTarget#addEventListener as #addEventListener
-	 * @borrows orion.textview.EventTarget#removeEventListener as #removeEventListener
-	 * @borrows orion.textview.EventTarget#dispatchEvent as #dispatchEvent
-	 */
-	function TextModel(text, lineDelimiter) {
-		this._lastLineIndex = -1;
-		this._text = [""];
-		this._lineOffsets = [0];
-		this.setText(text);
-		this.setLineDelimiter(lineDelimiter);
-	}
-
-	TextModel.prototype = /** @lends orion.textview.TextModel.prototype */ {
-		/**
-		 * Returns the number of characters in the model.
-		 *
-		 * @returns {Number} the number of characters in the model.
-		 */
-		getCharCount: function() {
-			var count = 0;
-			for (var i = 0; i<this._text.length; i++) {
-				count += this._text[i].length;
-			}
-			return count;
-		},
-		/**
-		 * Returns the text of the line at the given index.
-		 * <p>
-		 * The valid indices are 0 to line count exclusive.  Returns <code>null</code> 
-		 * if the index is out of range. 
-		 * </p>
-		 *
-		 * @param {Number} lineIndex the zero based index of the line.
-		 * @param {Boolean} [includeDelimiter=false] whether or not to include the line delimiter. 
-		 * @returns {String} the line text or <code>null</code> if out of range.
-		 *
-		 * @see #getLineAtOffset
-		 */
-		getLine: function(lineIndex, includeDelimiter) {
-			var lineCount = this.getLineCount();
-			if (!(0 <= lineIndex && lineIndex < lineCount)) {
-				return null;
-			}
-			var start = this._lineOffsets[lineIndex];
-			if (lineIndex + 1 < lineCount) {
-				var text = this.getText(start, this._lineOffsets[lineIndex + 1]);
-				if (includeDelimiter) {
-					return text;
-				}
-				var end = text.length, c;
-				while (((c = text.charCodeAt(end - 1)) === 10) || (c === 13)) {
-					end--;
-				}
-				return text.substring(0, end);
-			} else {
-				return this.getText(start); 
-			}
-		},
-		/**
-		 * Returns the line index at the given character offset.
-		 * <p>
-		 * The valid offsets are 0 to char count inclusive. The line index for
-		 * char count is <code>line count - 1</code>. Returns <code>-1</code> if
-		 * the offset is out of range.
-		 * </p>
-		 *
-		 * @param {Number} offset a character offset.
-		 * @returns {Number} the zero based line index or <code>-1</code> if out of range.
-		 */
-		getLineAtOffset: function(offset) {
-			var charCount = this.getCharCount();
-			if (!(0 <= offset && offset <= charCount)) {
-				return -1;
-			}
-			var lineCount = this.getLineCount();
-			if (offset === charCount) {
-				return lineCount - 1; 
-			}
-			var lineStart, lineEnd;
-			var index = this._lastLineIndex;
-			if (0 <= index && index < lineCount) {
-				lineStart = this._lineOffsets[index];
-				lineEnd = index + 1 < lineCount ? this._lineOffsets[index + 1] : charCount;
-				if (lineStart <= offset && offset < lineEnd) {
-					return index;
-				}
-			}
-			var high = lineCount;
-			var low = -1;
-			while (high - low > 1) {
-				index = Math.floor((high + low) / 2);
-				lineStart = this._lineOffsets[index];
-				lineEnd = index + 1 < lineCount ? this._lineOffsets[index + 1] : charCount;
-				if (offset <= lineStart) {
-					high = index;
-				} else if (offset < lineEnd) {
-					high = index;
-					break;
-				} else {
-					low = index;
-				}
-			}
-			this._lastLineIndex = high;
-			return high;
-		},
-		/**
-		 * Returns the number of lines in the model.
-		 * <p>
-		 * The model always has at least one line.
-		 * </p>
-		 *
-		 * @returns {Number} the number of lines.
-		 */
-		getLineCount: function() {
-			return this._lineOffsets.length;
-		},
-		/**
-		 * Returns the line delimiter that is used by the view
-		 * when inserting new lines. New lines entered using key strokes 
-		 * and paste operations use this line delimiter.
-		 *
-		 * @return {String} the line delimiter that is used by the view when inserting new lines.
-		 */
-		getLineDelimiter: function() {
-			return this._lineDelimiter;
-		},
-		/**
-		 * Returns the end character offset for the given line. 
-		 * <p>
-		 * The end offset is not inclusive. This means that when the line delimiter is included, the 
-		 * offset is either the start offset of the next line or char count. When the line delimiter is
-		 * not included, the offset is the offset of the line delimiter.
-		 * </p>
-		 * <p>
-		 * The valid indices are 0 to line count exclusive.  Returns <code>-1</code> 
-		 * if the index is out of range. 
-		 * </p>
-		 *
-		 * @param {Number} lineIndex the zero based index of the line.
-		 * @param {Boolean} [includeDelimiter=false] whether or not to include the line delimiter. 
-		 * @return {Number} the line end offset or <code>-1</code> if out of range.
-		 *
-		 * @see #getLineStart
-		 */
-		getLineEnd: function(lineIndex, includeDelimiter) {
-			var lineCount = this.getLineCount();
-			if (!(0 <= lineIndex && lineIndex < lineCount)) {
-				return -1;
-			}
-			if (lineIndex + 1 < lineCount) {
-				var end = this._lineOffsets[lineIndex + 1];
-				if (includeDelimiter) {
-					return end;
-				}
-				var text = this.getText(Math.max(this._lineOffsets[lineIndex], end - 2), end);
-				var i = text.length, c;
-				while (((c = text.charCodeAt(i - 1)) === 10) || (c === 13)) {
-					i--;
-				}
-				return end - (text.length - i);
-			} else {
-				return this.getCharCount();
-			}
-		},
-		/**
-		 * Returns the start character offset for the given line.
-		 * <p>
-		 * The valid indices are 0 to line count exclusive.  Returns <code>-1</code> 
-		 * if the index is out of range. 
-		 * </p>
-		 *
-		 * @param {Number} lineIndex the zero based index of the line.
-		 * @return {Number} the line start offset or <code>-1</code> if out of range.
-		 *
-		 * @see #getLineEnd
-		 */
-		getLineStart: function(lineIndex) {
-			if (!(0 <= lineIndex && lineIndex < this.getLineCount())) {
-				return -1;
-			}
-			return this._lineOffsets[lineIndex];
-		},
-		/**
-		 * Returns the text for the given range.
-		 * <p>
-		 * The end offset is not inclusive. This means that character at the end offset
-		 * is not included in the returned text.
-		 * </p>
-		 *
-		 * @param {Number} [start=0] the zero based start offset of text range.
-		 * @param {Number} [end=char count] the zero based end offset of text range.
-		 *
-		 * @see #setText
-		 */
-		getText: function(start, end) {
-			if (start === undefined) { start = 0; }
-			if (end === undefined) { end = this.getCharCount(); }
-			if (start === end) { return ""; }
-			var offset = 0, chunk = 0, length;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (start <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var firstOffset = offset;
-			var firstChunk = chunk;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (end <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var lastOffset = offset;
-			var lastChunk = chunk;
-			if (firstChunk === lastChunk) {
-				return this._text[firstChunk].substring(start - firstOffset, end - lastOffset);
-			}
-			var beforeText = this._text[firstChunk].substring(start - firstOffset);
-			var afterText = this._text[lastChunk].substring(0, end - lastOffset);
-			return beforeText + this._text.slice(firstChunk+1, lastChunk).join("") + afterText; 
-		},
-		/**
-		 * Notifies all listeners that the text is about to change.
-		 * <p>
-		 * This notification is intended to be used only by the view. Application clients should
-		 * use {@link orion.textview.TextView#event:onModelChanging}.
-		 * </p>
-		 * <p>
-		 * NOTE: This method is not meant to called directly by application code. It is called internally by the TextModel
-		 * as part of the implementation of {@link #setText}. This method is included in the public API for documentation
-		 * purposes and to allow integration with other toolkit frameworks.
-		 * </p>
-		 *
-		 * @param {orion.textview.ModelChangingEvent} modelChangingEvent the changing event
-		 */
-		onChanging: function(modelChangingEvent) {
-			return this.dispatchEvent(modelChangingEvent);
-		},
-		/**
-		 * Notifies all listeners that the text has changed.
-		 * <p>
-		 * This notification is intended to be used only by the view. Application clients should
-		 * use {@link orion.textview.TextView#event:onModelChanged}.
-		 * </p>
-		 * <p>
-		 * NOTE: This method is not meant to called directly by application code. It is called internally by the TextModel
-		 * as part of the implementation of {@link #setText}. This method is included in the public API for documentation
-		 * purposes and to allow integration with other toolkit frameworks.
-		 * </p>
-		 *
-		 * @param {orion.textview.ModelChangedEvent} modelChangedEvent the changed event
-		 */
-		onChanged: function(modelChangedEvent) {
-			return this.dispatchEvent(modelChangedEvent);
-		},
-		/**
-		 * Sets the line delimiter that is used by the view
-		 * when new lines are inserted in the model due to key
-		 * strokes  and paste operations.
-		 * <p>
-		 * If lineDelimiter is "auto", the delimiter is computed to be
-		 * the first delimiter found the in the current text. If lineDelimiter
-		 * is undefined or if there are no delimiters in the current text, the
-		 * platform delimiter is used.
-		 * </p>
-		 *
-		 * @param {String} lineDelimiter the line delimiter that is used by the view when inserting new lines.
-		 */
-		setLineDelimiter: function(lineDelimiter) {
-			if (lineDelimiter === "auto") {
-				lineDelimiter = undefined;
-				if (this.getLineCount() > 1) {
-					lineDelimiter = this.getText(this.getLineEnd(0), this.getLineEnd(0, true));
-				}
-			}
-			this._lineDelimiter = lineDelimiter ? lineDelimiter : (isWindows ? "\r\n" : "\n"); 
-		},
-		/**
-		 * Replaces the text in the given range with the given text.
-		 * <p>
-		 * The end offset is not inclusive. This means that the character at the 
-		 * end offset is not replaced.
-		 * </p>
-		 * <p>
-		 * The text model must notify the listeners before and after the
-		 * the text is changed by calling {@link #onChanging} and {@link #onChanged}
-		 * respectively. 
-		 * </p>
-		 *
-		 * @param {String} [text=""] the new text.
-		 * @param {Number} [start=0] the zero based start offset of text range.
-		 * @param {Number} [end=char count] the zero based end offset of text range.
-		 *
-		 * @see #getText
-		 */
-		setText: function(text, start, end) {
-			if (text === undefined) { text = ""; }
-			if (start === undefined) { start = 0; }
-			if (end === undefined) { end = this.getCharCount(); }
-			if (start === end && text === "") { return; }
-			var startLine = this.getLineAtOffset(start);
-			var endLine = this.getLineAtOffset(end);
-			var eventStart = start;
-			var removedCharCount = end - start;
-			var removedLineCount = endLine - startLine;
-			var addedCharCount = text.length;
-			var addedLineCount = 0;
-			var lineCount = this.getLineCount();
-			
-			var cr = 0, lf = 0, index = 0;
-			var newLineOffsets = [];
-			while (true) {
-				if (cr !== -1 && cr <= index) { cr = text.indexOf("\r", index); }
-				if (lf !== -1 && lf <= index) { lf = text.indexOf("\n", index); }
-				if (lf === -1 && cr === -1) { break; }
-				if (cr !== -1 && lf !== -1) {
-					if (cr + 1 === lf) {
-						index = lf + 1;
-					} else {
-						index = (cr < lf ? cr : lf) + 1;
-					}
-				} else if (cr !== -1) {
-					index = cr + 1;
-				} else {
-					index = lf + 1;
-				}
-				newLineOffsets.push(start + index);
-				addedLineCount++;
-			}
-		
-			var modelChangingEvent = {
-				type: "Changing",
-				text: text,
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanging(modelChangingEvent);
-			
-			//TODO this should be done the loops below to avoid getText()
-			if (newLineOffsets.length === 0) {
-				var startLineOffset = this.getLineStart(startLine), endLineOffset;
-				if (endLine + 1 < lineCount) {
-					endLineOffset = this.getLineStart(endLine + 1);
-				} else {
-					endLineOffset = this.getCharCount();
-				}
-				if (start !== startLineOffset) {
-					text = this.getText(startLineOffset, start) + text;
-					start = startLineOffset;
-				}
-				if (end !== endLineOffset) {
-					text = text + this.getText(end, endLineOffset);
-					end = endLineOffset;
-				}
-			}
-			
-			var changeCount = addedCharCount - removedCharCount;
-			for (var j = startLine + removedLineCount + 1; j < lineCount; j++) {
-				this._lineOffsets[j] += changeCount;
-			}
-			var args = [startLine + 1, removedLineCount].concat(newLineOffsets);
-			Array.prototype.splice.apply(this._lineOffsets, args);
-			
-			var offset = 0, chunk = 0, length;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (start <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var firstOffset = offset;
-			var firstChunk = chunk;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (end <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var lastOffset = offset;
-			var lastChunk = chunk;
-			var firstText = this._text[firstChunk];
-			var lastText = this._text[lastChunk];
-			var beforeText = firstText.substring(0, start - firstOffset);
-			var afterText = lastText.substring(end - lastOffset);
-			var params = [firstChunk, lastChunk - firstChunk + 1];
-			if (beforeText) { params.push(beforeText); }
-			if (text) { params.push(text); }
-			if (afterText) { params.push(afterText); }
-			Array.prototype.splice.apply(this._text, params);
-			if (this._text.length === 0) { this._text = [""]; }
-			
-			var modelChangedEvent = {
-				type: "Changed",
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanged(modelChangedEvent);
-		}
-	};
-	mEventTarget.EventTarget.addMixin(TextModel.prototype);
-	
-	return {TextModel: TextModel};
-});/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- ******************************************************************************/
-
-/*global define */
-
-define("orion/textview/projectionTextModel", ['orion/textview/textModel', 'orion/textview/eventTarget'], function(mTextModel, mEventTarget) {
-
-	/**
-	 * @class This object represents a projection range. A projection specifies a
-	 * range of text and the replacement text. The range of text is relative to the
-	 * base text model associated to a projection model.
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.ProjectionTextModel}<br/>
-	 * {@link orion.textview.ProjectionTextModel#addProjection}<br/>
-	 * </p>		 
-	 * @name orion.textview.Projection
-	 * 
-	 * @property {Number} start The start offset of the projection range. 
-	 * @property {Number} end The end offset of the projection range. This offset is exclusive.
-	 * @property {String|orion.textview.TextModel} [text=""] The projection text to be inserted
-	 */
-	/**
-	 * Constructs a new <code>ProjectionTextModel</code> based on the specified <code>TextModel</code>.
-	 *
-	 * @param {orion.textview.TextModel} baseModel The base text model.
-	 *
-	 * @name orion.textview.ProjectionTextModel
-	 * @class The <code>ProjectionTextModel</code> represents a projection of its base text
-	 * model. Projection ranges can be added to the projection text model to hide and/or insert
-	 * ranges to the base text model.
-	 * <p>
-	 * The contents of the projection text model is modified when changes occur in the base model,
-	 * projection model or by calls to {@link #addProjection} and {@link #removeProjection}.
-	 * </p>
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.TextView}<br/>
-	 * {@link orion.textview.TextModel}
-	 * {@link orion.textview.TextView#setModel}
-	 * </p>
-	 * @borrows orion.textview.EventTarget#addEventListener as #addEventListener
-	 * @borrows orion.textview.EventTarget#removeEventListener as #removeEventListener
-	 * @borrows orion.textview.EventTarget#dispatchEvent as #dispatchEvent
-	 */
-	function ProjectionTextModel(baseModel) {
-		this._model = baseModel;	/* Base Model */
-		this._projections = [];
-	}
-
-	ProjectionTextModel.prototype = /** @lends orion.textview.ProjectionTextModel.prototype */ {
-		/**
-		 * Adds a projection range to the model.
-		 * <p>
-		 * The model must notify the listeners before and after the the text is
-		 * changed by calling {@link #onChanging} and {@link #onChanged} respectively. 
-		 * </p>
-		 * @param {orion.textview.Projection} projection The projection range to be added.
-		 * 
-		 * @see #removeProjection
-		 */
-		addProjection: function(projection) {
-			if (!projection) {return;}
-			//start and end can't overlap any exist projection
-			var model = this._model, projections = this._projections;
-			projection._lineIndex = model.getLineAtOffset(projection.start);
-			projection._lineCount = model.getLineAtOffset(projection.end) - projection._lineIndex;
-			var text = projection.text;
-			if (!text) { text = ""; }
-			if (typeof text === "string") {
-				projection._model = new mTextModel.TextModel(text, model.getLineDelimiter());
-			} else {
-				projection._model = text;
-			}
-			var eventStart = this.mapOffset(projection.start, true);
-			var removedCharCount = projection.end - projection.start;
-			var removedLineCount = projection._lineCount;
-			var addedCharCount = projection._model.getCharCount();
-			var addedLineCount = projection._model.getLineCount() - 1;
-			var modelChangingEvent = {
-				type: "Changing",
-				text: projection._model.getText(),
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanging(modelChangingEvent);
-			var index = this._binarySearch(projections, projection.start);
-			projections.splice(index, 0, projection);
-			var modelChangedEvent = {
-				type: "Changed",
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanged(modelChangedEvent);
-		},
-		/**
-		 * Returns all projection ranges of this model.
-		 * 
-		 * @return {orion.textview.Projection[]} The projection ranges.
-		 * 
-		 * @see #addProjection
-		 */
-		getProjections: function() {
-			return this._projections.slice(0);
-		},
-		/**
-		 * Gets the base text model.
-		 *
-		 * @return {orion.textview.TextModel} The base text model.
-		 */
-		getBaseModel: function() {
-			return this._model;
-		},
-		/**
-		 * Maps offsets between the projection model and its base model.
-		 *
-		 * @param {Number} offset The offset to be mapped.
-		 * @param {Boolean} [baseOffset=false] <code>true</code> if <code>offset</code> is in base model and
-		 *	should be mapped to the projection model.
-		 * @return {Number} The mapped offset
-		 */
-		mapOffset: function(offset, baseOffset) {
-			var projections = this._projections, delta = 0, i, projection;
-			if (baseOffset) {
-				for (i = 0; i < projections.length; i++) {
-					projection = projections[i];
-					if (projection.start > offset) { break; }
-					if (projection.end > offset) { return -1; }
-					delta += projection._model.getCharCount() - (projection.end - projection.start);
-				}
-				return offset + delta;
-			}
-			for (i = 0; i < projections.length; i++) {
-				projection = projections[i];
-				if (projection.start > offset - delta) { break; }
-				var charCount = projection._model.getCharCount();
-				if (projection.start + charCount > offset - delta) {
-					return -1;
-				}
-				delta += charCount - (projection.end - projection.start);
-			}
-			return offset - delta;
-		},
-		/**
-		 * Removes a projection range from the model.
-		 * <p>
-		 * The model must notify the listeners before and after the the text is
-		 * changed by calling {@link #onChanging} and {@link #onChanged} respectively. 
-		 * </p>
-		 * 
-		 * @param {orion.textview.Projection} projection The projection range to be removed.
-		 * 
-		 * @see #addProjection
-		 */
-		removeProjection: function(projection) {
-			//TODO remove listeners from model
-			var i, delta = 0;
-			for (i = 0; i < this._projections.length; i++) {
-				var p = this._projections[i];
-				if (p === projection) {
-					projection = p;
-					break;
-				}
-				delta += p._model.getCharCount() - (p.end - p.start);
-			}
-			if (i < this._projections.length) {
-				var model = this._model;
-				var eventStart = projection.start + delta;
-				var addedCharCount = projection.end - projection.start;
-				var addedLineCount = projection._lineCount;
-				var removedCharCount = projection._model.getCharCount();
-				var removedLineCount = projection._model.getLineCount() - 1;
-				var modelChangingEvent = {
-					type: "Changing",
-					text: model.getText(projection.start, projection.end),
-					start: eventStart,
-					removedCharCount: removedCharCount,
-					addedCharCount: addedCharCount,
-					removedLineCount: removedLineCount,
-					addedLineCount: addedLineCount
-				};
-				this.onChanging(modelChangingEvent);
-				this._projections.splice(i, 1);
-				var modelChangedEvent = {
-					type: "Changed",
-					start: eventStart,
-					removedCharCount: removedCharCount,
-					addedCharCount: addedCharCount,
-					removedLineCount: removedLineCount,
-					addedLineCount: addedLineCount
-				};
-				this.onChanged(modelChangedEvent);
-			}
-		},
-		/** @ignore */
-		_binarySearch: function (array, offset) {
-			var high = array.length, low = -1, index;
-			while (high - low > 1) {
-				index = Math.floor((high + low) / 2);
-				if (offset <= array[index].start) {
-					high = index;
-				} else {
-					low = index;
-				}
-			}
-			return high;
-		},
-		/**
-		 * @see orion.textview.TextModel#getCharCount
-		 */
-		getCharCount: function() {
-			var count = this._model.getCharCount(), projections = this._projections;
-			for (var i = 0; i < projections.length; i++) {
-				var projection = projections[i];
-				count += projection._model.getCharCount() - (projection.end - projection.start);
-			}
-			return count;
-		},
-		/**
-		 * @see orion.textview.TextModel#getLine
-		 */
-		getLine: function(lineIndex, includeDelimiter) {
-			if (lineIndex < 0) { return null; }
-			var model = this._model, projections = this._projections;
-			var delta = 0, result = [], offset = 0, i, lineCount, projection;
-			for (i = 0; i < projections.length; i++) {
-				projection = projections[i];
-				if (projection._lineIndex >= lineIndex - delta) { break; }
-				lineCount = projection._model.getLineCount() - 1;
-				if (projection._lineIndex + lineCount >= lineIndex - delta) {
-					var projectionLineIndex = lineIndex - (projection._lineIndex + delta);
-					if (projectionLineIndex < lineCount) {
-						return projection._model.getLine(projectionLineIndex, includeDelimiter);
-					} else {
-						result.push(projection._model.getLine(lineCount));
-					}
-				}
-				offset = projection.end;
-				delta += lineCount - projection._lineCount;
-			}
-			offset = Math.max(offset, model.getLineStart(lineIndex - delta));
-			for (; i < projections.length; i++) {
-				projection = projections[i];
-				if (projection._lineIndex > lineIndex - delta) { break; }
-				result.push(model.getText(offset, projection.start));
-				lineCount = projection._model.getLineCount() - 1;
-				if (projection._lineIndex + lineCount > lineIndex - delta) {
-					result.push(projection._model.getLine(0, includeDelimiter));
-					return result.join("");
-				}
-				result.push(projection._model.getText());
-				offset = projection.end;
-				delta += lineCount - projection._lineCount;
-			}
-			var end = model.getLineEnd(lineIndex - delta, includeDelimiter);
-			if (offset < end) {
-				result.push(model.getText(offset, end));
-			}
-			return result.join("");
-		},
-		/**
-		 * @see orion.textview.TextModel#getLineAtOffset
-		 */
-		getLineAtOffset: function(offset) {
-			var model = this._model, projections = this._projections;
-			var delta = 0, lineDelta = 0;
-			for (var i = 0; i < projections.length; i++) {
-				var projection = projections[i];
-				if (projection.start > offset - delta) { break; }
-				var charCount = projection._model.getCharCount();
-				if (projection.start + charCount > offset - delta) {
-					var projectionOffset = offset - (projection.start + delta);
-					lineDelta += projection._model.getLineAtOffset(projectionOffset);
-					delta += projectionOffset;
-					break;
-				}
-				lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
-				delta += charCount - (projection.end - projection.start);
-			}
-			return model.getLineAtOffset(offset - delta) + lineDelta;
-		},
-		/**
-		 * @see orion.textview.TextModel#getLineCount
-		 */
-		getLineCount: function() {
-			var model = this._model, projections = this._projections;
-			var count = model.getLineCount();
-			for (var i = 0; i < projections.length; i++) {
-				var projection = projections[i];
-				count += projection._model.getLineCount() - 1 - projection._lineCount;
-			}
-			return count;
-		},
-		/**
-		 * @see orion.textview.TextModel#getLineDelimiter
-		 */
-		getLineDelimiter: function() {
-			return this._model.getLineDelimiter();
-		},
-		/**
-		 * @see orion.textview.TextModel#getLineEnd
-		 */
-		getLineEnd: function(lineIndex, includeDelimiter) {
-			if (lineIndex < 0) { return -1; }
-			var model = this._model, projections = this._projections;
-			var delta = 0, offsetDelta = 0;
-			for (var i = 0; i < projections.length; i++) {
-				var projection = projections[i];
-				if (projection._lineIndex > lineIndex - delta) { break; }
-				var lineCount = projection._model.getLineCount() - 1;
-				if (projection._lineIndex + lineCount > lineIndex - delta) {
-					var projectionLineIndex = lineIndex - (projection._lineIndex + delta);
-					return projection._model.getLineEnd (projectionLineIndex, includeDelimiter) + projection.start + offsetDelta;
-				}
-				offsetDelta += projection._model.getCharCount() - (projection.end - projection.start);
-				delta += lineCount - projection._lineCount;
-			}
-			return model.getLineEnd(lineIndex - delta, includeDelimiter) + offsetDelta;
-		},
-		/**
-		 * @see orion.textview.TextModel#getLineStart
-		 */
-		getLineStart: function(lineIndex) {
-			if (lineIndex < 0) { return -1; }
-			var model = this._model, projections = this._projections;
-			var delta = 0, offsetDelta = 0;
-			for (var i = 0; i < projections.length; i++) {
-				var projection = projections[i];
-				if (projection._lineIndex >= lineIndex - delta) { break; }
-				var lineCount = projection._model.getLineCount() - 1;
-				if (projection._lineIndex + lineCount >= lineIndex - delta) {
-					var projectionLineIndex = lineIndex - (projection._lineIndex + delta);
-					return projection._model.getLineStart (projectionLineIndex) + projection.start + offsetDelta;
-				}
-				offsetDelta += projection._model.getCharCount() - (projection.end - projection.start);
-				delta += lineCount - projection._lineCount;
-			}
-			return model.getLineStart(lineIndex - delta) + offsetDelta;
-		},
-		/**
-		 * @see orion.textview.TextModel#getText
-		 */
-		getText: function(start, end) {
-			if (start === undefined) { start = 0; }
-			var model = this._model, projections = this._projections;
-			var delta = 0, result = [], i, projection, charCount;
-			for (i = 0; i < projections.length; i++) {
-				projection = projections[i];
-				if (projection.start > start - delta) { break; }
-				charCount = projection._model.getCharCount();
-				if (projection.start + charCount > start - delta) {
-					if (end !== undefined && projection.start + charCount > end - delta) {
-						return projection._model.getText(start - (projection.start + delta), end - (projection.start + delta));
-					} else {
-						result.push(projection._model.getText(start - (projection.start + delta)));
-						start = projection.end + delta + charCount - (projection.end - projection.start);
-					}
-				}
-				delta += charCount - (projection.end - projection.start);
-			}
-			var offset = start - delta;
-			if (end !== undefined) {
-				for (; i < projections.length; i++) {
-					projection = projections[i];
-					if (projection.start > end - delta) { break; }
-					result.push(model.getText(offset, projection.start));
-					charCount = projection._model.getCharCount();
-					if (projection.start + charCount > end - delta) {
-						result.push(projection._model.getText(0, end - (projection.start + delta)));
-						return result.join("");
-					}
-					result.push(projection._model.getText());
-					offset = projection.end;
-					delta += charCount - (projection.end - projection.start);
-				}
-				result.push(model.getText(offset, end - delta));
-			} else {
-				for (; i < projections.length; i++) {
-					projection = projections[i];
-					result.push(model.getText(offset, projection.start));
-					result.push(projection._model.getText());
-					offset = projection.end;
-				}
-				result.push(model.getText(offset));
-			}
-			return result.join("");
-		},
-		/** @ignore */
-		_onChanging: function(text, start, removedCharCount, addedCharCount, removedLineCount, addedLineCount) {
-			var model = this._model, projections = this._projections, i, projection, delta = 0, lineDelta;
-			var end = start + removedCharCount;
-			for (; i < projections.length; i++) {
-				projection = projections[i];
-				if (projection.start > start) { break; }
-				delta += projection._model.getCharCount() - (projection.end - projection.start);
-			}
-			/*TODO add stuff saved by setText*/
-			var mapStart = start + delta, rangeStart = i;
-			for (; i < projections.length; i++) {
-				projection = projections[i];
-				if (projection.start > end) { break; }
-				delta += projection._model.getCharCount() - (projection.end - projection.start);
-				lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
-			}
-			/*TODO add stuff saved by setText*/
-			var mapEnd = end + delta, rangeEnd = i;
-			this.onChanging(mapStart, mapEnd - mapStart, addedCharCount/*TODO add stuff saved by setText*/, removedLineCount + lineDelta/*TODO add stuff saved by setText*/, addedLineCount/*TODO add stuff saved by setText*/);
-			projections.splice(projections, rangeEnd - rangeStart);
-			var count = text.length - (mapEnd - mapStart);
-			for (; i < projections.length; i++) {
-				projection = projections[i];
-				projection.start += count;
-				projection.end += count;
-				projection._lineIndex = model.getLineAtOffset(projection.start);
-			}
-		},
-		/**
-		 * @see orion.textview.TextModel#onChanging
-		 */
-		onChanging: function(modelChangingEvent) {
-			return this.dispatchEvent(modelChangingEvent);
-		},
-		/**
-		 * @see orion.textview.TextModel#onChanged
-		 */
-		onChanged: function(modelChangedEvent) {
-			return this.dispatchEvent(modelChangedEvent);
-		},
-		/**
-		 * @see orion.textview.TextModel#setLineDelimiter
-		 */
-		setLineDelimiter: function(lineDelimiter) {
-			this._model.setLineDelimiter(lineDelimiter);
-		},
-		/**
-		 * @see orion.textview.TextModel#setText
-		 */
-		setText: function(text, start, end) {
-			if (text === undefined) { text = ""; }
-			if (start === undefined) { start = 0; }
-			var eventStart = start, eventEnd = end;
-			var model = this._model, projections = this._projections;
-			var delta = 0, lineDelta = 0, i, projection, charCount, startProjection, endProjection, startLineDelta = 0;
-			for (i = 0; i < projections.length; i++) {
-				projection = projections[i];
-				if (projection.start > start - delta) { break; }
-				charCount = projection._model.getCharCount();
-				if (projection.start + charCount > start - delta) {
-					if (end !== undefined && projection.start + charCount > end - delta) {
-						projection._model.setText(text, start - (projection.start + delta), end - (projection.start + delta));
-						//TODO events - special case
-						return;
-					} else {
-						startLineDelta = projection._model.getLineCount() - 1 - projection._model.getLineAtOffset(start - (projection.start + delta));
-						startProjection = {
-							projection: projection,
-							start: start - (projection.start + delta)
-						};
-						start = projection.end + delta + charCount - (projection.end - projection.start);
-					}
-				}
-				lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
-				delta += charCount - (projection.end - projection.start);
-			}
-			var mapStart = start - delta, rangeStart = i, startLine = model.getLineAtOffset(mapStart) + lineDelta - startLineDelta;
-			if (end !== undefined) {
-				for (; i < projections.length; i++) {
-					projection = projections[i];
-					if (projection.start > end - delta) { break; }
-					charCount = projection._model.getCharCount();
-					if (projection.start + charCount > end - delta) {
-						lineDelta += projection._model.getLineAtOffset(end - (projection.start + delta));
-						charCount = end - (projection.start + delta);
-						end = projection.end + delta;
-						endProjection = {
-							projection: projection,
-							end: charCount
-						};
-						break;
-					}
-					lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
-					delta += charCount - (projection.end - projection.start);
-				}
-			} else {
-				for (; i < projections.length; i++) {
-					projection = projections[i];
-					lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
-					delta += projection._model.getCharCount() - (projection.end - projection.start);
-				}
-				end = eventEnd = model.getCharCount() + delta;
-			}
-			var mapEnd = end - delta, rangeEnd = i, endLine = model.getLineAtOffset(mapEnd) + lineDelta;
-			
-			//events
-			var removedCharCount = eventEnd - eventStart;
-			var removedLineCount = endLine - startLine;
-			var addedCharCount = text.length;
-			var addedLineCount = 0;
-			var cr = 0, lf = 0, index = 0;
-			while (true) {
-				if (cr !== -1 && cr <= index) { cr = text.indexOf("\r", index); }
-				if (lf !== -1 && lf <= index) { lf = text.indexOf("\n", index); }
-				if (lf === -1 && cr === -1) { break; }
-				if (cr !== -1 && lf !== -1) {
-					if (cr + 1 === lf) {
-						index = lf + 1;
-					} else {
-						index = (cr < lf ? cr : lf) + 1;
-					}
-				} else if (cr !== -1) {
-					index = cr + 1;
-				} else {
-					index = lf + 1;
-				}
-				addedLineCount++;
-			}
-			
-			var modelChangingEvent = {
-				type: "Changing",
-				text: text,
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanging(modelChangingEvent);
-			
-//			var changeLineCount = model.getLineAtOffset(mapEnd) - model.getLineAtOffset(mapStart) + addedLineCount;
-			model.setText(text, mapStart, mapEnd);
-			if (startProjection) {
-				projection = startProjection.projection;
-				projection._model.setText("", startProjection.start);
-			}		
-			if (endProjection) {
-				projection = endProjection.projection;
-				projection._model.setText("", 0, endProjection.end);
-				projection.start = projection.end;
-				projection._lineCount = 0;
-			}
-			projections.splice(rangeStart, rangeEnd - rangeStart);
-			var changeCount = text.length - (mapEnd - mapStart);
-			for (i = rangeEnd; i < projections.length; i++) {
-				projection = projections[i];
-				projection.start += changeCount;
-				projection.end += changeCount;
-//				if (projection._lineIndex + changeLineCount !== model.getLineAtOffset(projection.start)) {
-//					log("here");
-//				}
-				projection._lineIndex = model.getLineAtOffset(projection.start);
-//				projection._lineIndex += changeLineCount;
-			}
-			
-			var modelChangedEvent = {
-				type: "Changed",
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanged(modelChangedEvent);
-		}
-	};
-	mEventTarget.EventTarget.addMixin(ProjectionTextModel.prototype);
-
-	return {ProjectionTextModel: ProjectionTextModel};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-
-/*global define setTimeout clearTimeout setInterval clearInterval Node */
-
-define("orion/textview/tooltip", ['orion/textview/textView', 'orion/textview/textModel', 'orion/textview/projectionTextModel'], function(mTextView, mTextModel, mProjectionTextModel) {
-
-	/** @private */
-	function Tooltip (view) {
-		this._view = view;
-		//TODO add API to get the parent of the view
-		this._create(view._parent.ownerDocument);
-		view.addEventListener("Destroy", this, this.destroy);
-	}
-	Tooltip.getTooltip = function(view) {
-		if (!view._tooltip) {
-			 view._tooltip = new Tooltip(view);
-		}
-		return view._tooltip;
-	};
-	Tooltip.prototype = /** @lends orion.textview.Tooltip.prototype */ {
-		_create: function(document) {
-			if (this._domNode) { return; }
-			this._document = document;
-			var domNode = this._domNode = document.createElement("DIV");
-			domNode.className = "viewTooltip";
-			var viewParent = this._viewParent = document.createElement("DIV");
-			domNode.appendChild(viewParent);
-			var htmlParent = this._htmlParent = document.createElement("DIV");
-			domNode.appendChild(htmlParent);
-			document.body.appendChild(domNode);
-			this.hide();
-		},
-		destroy: function() {
-			if (!this._domNode) { return; }
-			if (this._contentsView) {
-				this._contentsView.destroy();
-				this._contentsView = null;
-				this._emptyModel = null;
-			}
-			var parent = this._domNode.parentNode;
-			if (parent) { parent.removeChild(this._domNode); }
-			this._domNode = null;
-		},
-		hide: function() {
-			if (this._contentsView) {
-				this._contentsView.setModel(this._emptyModel);
-			}
-			if (this._viewParent) {
-				this._viewParent.style.left = "-10000px";
-				this._viewParent.style.position = "fixed";
-				this._viewParent.style.visibility = "hidden";
-			}
-			if (this._htmlParent) {
-				this._htmlParent.style.left = "-10000px";
-				this._htmlParent.style.position = "fixed";
-				this._htmlParent.style.visibility = "hidden";
-				this._htmlParent.innerHTML = "";
-			}
-			if (this._domNode) {
-				this._domNode.style.visibility = "hidden";
-			}
-			if (this._showTimeout) {
-				clearTimeout(this._showTimeout);
-				this._showTimeout = null;
-			}
-			if (this._hideTimeout) {
-				clearTimeout(this._hideTimeout);
-				this._hideTimeout = null;
-			}
-			if (this._fadeTimeout) {
-				clearInterval(this._fadeTimeout);
-				this._fadeTimeout = null;
-			}
-		},
-		isVisible: function() {
-			return this._domNode && this._domNode.style.visibility === "visible";
-		},
-		setTarget: function(target) {
-			if (this.target === target) { return; }
-			this._target = target;
-			this.hide();
-			if (target) {
-				var self = this;
-				self._showTimeout = setTimeout(function() {
-					self.show(true);
-				}, 1000);
-			}
-		},
-		show: function(autoHide) {
-			if (!this._target) { return; }
-			var info = this._target.getTooltipInfo();
-			if (!info) { return; }
-			var domNode = this._domNode;
-			domNode.style.left = domNode.style.right = domNode.style.width = domNode.style.height = "auto";
-			var contents = info.contents, contentsDiv;
-			if (contents instanceof Array) {
-				contents = this._getAnnotationContents(contents);
-			}
-			if (typeof contents === "string") {
-				(contentsDiv = this._htmlParent).innerHTML = contents;
-			} else if (contents instanceof Node) {
-				(contentsDiv = this._htmlParent).appendChild(contents);
-			} else if (contents instanceof mProjectionTextModel.ProjectionTextModel) {
-				if (!this._contentsView) {
-					this._emptyModel = new mTextModel.TextModel("");
-					//TODO need hook into setup.js (or editor.js) to create a text view (and styler)
-					var newView = this._contentsView = new mTextView.TextView({
-						model: this._emptyModel,
-						parent: this._viewParent,
-						tabSize: 4,
-						sync: true,
-						stylesheet: ["/orion/textview/tooltip.css", "/orion/textview/rulers.css",
-							"/examples/textview/textstyler.css", "/css/default-theme.css"]
-					});
-					//TODO this is need to avoid IE from getting focus
-					newView._clientDiv.contentEditable = false;
-					//TODO need to find a better way of sharing the styler for multiple views
-					var view = this._view;
-					var listener = {
-						onLineStyle: function(e) {
-							view.onLineStyle(e);
-						}
-					};
-					newView.addEventListener("LineStyle", listener.onLineStyle);
-				}
-				var contentsView = this._contentsView;
-				contentsView.setModel(contents);
-				var size = contentsView.computeSize();
-				contentsDiv = this._viewParent;
-				//TODO always make the width larger than the size of the scrollbar to avoid bug in updatePage
-				contentsDiv.style.width = (size.width + 20) + "px";
-				contentsDiv.style.height = size.height + "px";
-			} else {
-				return;
-			}
-			contentsDiv.style.left = "auto";
-			contentsDiv.style.position = "static";
-			contentsDiv.style.visibility = "visible";
-			var left = parseInt(this._getNodeStyle(domNode, "padding-left", "0"), 10);
-			left += parseInt(this._getNodeStyle(domNode, "border-left-width", "0"), 10);
-			if (info.anchor === "right") {
-				var right = parseInt(this._getNodeStyle(domNode, "padding-right", "0"), 10);
-				right += parseInt(this._getNodeStyle(domNode, "border-right-width", "0"), 10);
-				domNode.style.right = (domNode.ownerDocument.body.getBoundingClientRect().right - info.x + left + right) + "px";
-			} else {
-				domNode.style.left = (info.x - left) + "px";
-			}
-			var top = parseInt(this._getNodeStyle(domNode, "padding-top", "0"), 10);
-			top += parseInt(this._getNodeStyle(domNode, "border-top-width", "0"), 10);
-			domNode.style.top = (info.y - top) + "px";
-			domNode.style.maxWidth = info.maxWidth + "px";
-			domNode.style.maxHeight = info.maxHeight + "px";
-			domNode.style.opacity = "1";
-			domNode.style.visibility = "visible";
-			if (autoHide) {
-				var self = this;
-				self._hideTimeout = setTimeout(function() {
-					var opacity = parseFloat(self._getNodeStyle(domNode, "opacity", "1"));
-					self._fadeTimeout = setInterval(function() {
-						if (domNode.style.visibility === "visible" && opacity > 0) {
-							opacity -= 0.1;
-							domNode.style.opacity = opacity;
-							return;
-						}
-						self.hide();
-					}, 50);
-				}, 5000);
-			}
-		},
-		_getAnnotationContents: function(annotations) {
-			if (annotations.length === 0) {
-				return null;
-			}
-			var model = this._view.getModel(), annotation;
-			var baseModel = model.getBaseModel ? model.getBaseModel() : model;
-			function getText(start, end) {
-				var textStart = baseModel.getLineStart(baseModel.getLineAtOffset(start));
-				var textEnd = baseModel.getLineEnd(baseModel.getLineAtOffset(end), true);
-				return baseModel.getText(textStart, textEnd);
-			}
-			var title;
-			if (annotations.length === 1) {
-				annotation = annotations[0];
-				if (annotation.title) {
-					title = annotation.title.replace(/</g, "&lt;").replace(/>/g, "&gt;");
-					return "<div>" + annotation.html + "&nbsp;<span style='vertical-align:middle;'>" + title + "</span><div>";
-				} else {
-					var newModel = new mProjectionTextModel.ProjectionTextModel(baseModel);
-					var lineStart = baseModel.getLineStart(baseModel.getLineAtOffset(annotation.start));
-					newModel.addProjection({start: annotation.end, end: newModel.getCharCount()});
-					newModel.addProjection({start: 0, end: lineStart});
-					return newModel;
-				}
-			} else {
-				var tooltipHTML = "<div><em>Multiple annotations:</em></div>";
-				for (var i = 0; i < annotations.length; i++) {
-					annotation = annotations[i];
-					title = annotation.title;
-					if (!title) {
-						title = getText(annotation.start, annotation.end);
-					}
-					title = title.replace(/</g, "&lt;").replace(/>/g, "&gt;");
-					tooltipHTML += "<div>" + annotation.html + "&nbsp;<span style='vertical-align:middle;'>" + title + "</span><div>";
-				}
-				return tooltipHTML;
-			}
-		},
-		_getNodeStyle: function(node, prop, defaultValue) {
-			var value;
-			if (node) {
-				value = node.style[prop];
-				if (!value) {
-					if (node.currentStyle) {
-						var index = 0, p = prop;
-						while ((index = p.indexOf("-", index)) !== -1) {
-							p = p.substring(0, index) + p.substring(index + 1, index + 2).toUpperCase() + p.substring(index + 2);
-						}
-						value = node.currentStyle[p];
-					} else {
-						var css = node.ownerDocument.defaultView.getComputedStyle(node, null);
-						value = css ? css.getPropertyValue(prop) : null;
-					}
-				}
-			}
-			return value || defaultValue;
-		}
-	};
-	return {Tooltip: Tooltip};
-});
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- *		Mihai Sucan (Mozilla Foundation) - fix for Bug#334583 Bug#348471 Bug#349485 Bug#350595 Bug#360726 Bug#361180 Bug#362835 Bug#362428 Bug#362286 Bug#354270 Bug#361474 Bug#363945 Bug#366312 Bug#370584
- ******************************************************************************/
-
-/*global window document navigator setTimeout clearTimeout XMLHttpRequest define DOMException */
-
-define("orion/textview/textView", ['orion/textview/textModel', 'orion/textview/keyBinding', 'orion/textview/eventTarget'], function(mTextModel, mKeyBinding, mEventTarget) {
-
-	/** @private */
-	function addHandler(node, type, handler, capture) {
-		if (typeof node.addEventListener === "function") {
-			node.addEventListener(type, handler, capture === true);
-		} else {
-			node.attachEvent("on" + type, handler);
-		}
-	}
-	/** @private */
-	function removeHandler(node, type, handler, capture) {
-		if (typeof node.removeEventListener === "function") {
-			node.removeEventListener(type, handler, capture === true);
-		} else {
-			node.detachEvent("on" + type, handler);
-		}
-	}
-	var userAgent = navigator.userAgent;
-	var isIE;
-	if (document.selection && window.ActiveXObject && /MSIE/.test(userAgent)) {
-		isIE = document.documentMode ? document.documentMode : 7;
-	}
-	var isFirefox = parseFloat(userAgent.split("Firefox/")[1] || userAgent.split("Minefield/")[1]) || undefined;
-	var isOpera = userAgent.indexOf("Opera") !== -1;
-	var isChrome = userAgent.indexOf("Chrome") !== -1;
-	var isSafari = userAgent.indexOf("Safari") !== -1 && !isChrome;
-	var isWebkit = userAgent.indexOf("WebKit") !== -1;
-	var isPad = userAgent.indexOf("iPad") !== -1;
-	var isMac = navigator.platform.indexOf("Mac") !== -1;
-	var isWindows = navigator.platform.indexOf("Win") !== -1;
-	var isLinux = navigator.platform.indexOf("Linux") !== -1;
-	var isW3CEvents = typeof window.document.documentElement.addEventListener === "function";
-	var isRangeRects = (!isIE || isIE >= 9) && typeof window.document.createRange().getBoundingClientRect === "function";
-	var platformDelimiter = isWindows ? "\r\n" : "\n";
-	
-	/** 
-	 * Constructs a new Selection object.
-	 * 
-	 * @class A Selection represents a range of selected text in the view.
-	 * @name orion.textview.Selection
-	 */
-	function Selection (start, end, caret) {
-		/**
-		 * The selection start offset.
-		 *
-		 * @name orion.textview.Selection#start
-		 */
-		this.start = start;
-		/**
-		 * The selection end offset.
-		 *
-		 * @name orion.textview.Selection#end
-		 */
-		this.end = end;
-		/** @private */
-		this.caret = caret; //true if the start, false if the caret is at end
-	}
-	Selection.prototype = /** @lends orion.textview.Selection.prototype */ {
-		/** @private */
-		clone: function() {
-			return new Selection(this.start, this.end, this.caret);
-		},
-		/** @private */
-		collapse: function() {
-			if (this.caret) {
-				this.end = this.start;
-			} else {
-				this.start = this.end;
-			}
-		},
-		/** @private */
-		extend: function (offset) {
-			if (this.caret) {
-				this.start = offset;
-			} else {
-				this.end = offset;
-			}
-			if (this.start > this.end) {
-				var tmp = this.start;
-				this.start = this.end;
-				this.end = tmp;
-				this.caret = !this.caret;
-			}
-		},
-		/** @private */
-		setCaret: function(offset) {
-			this.start = offset;
-			this.end = offset;
-			this.caret = false;
-		},
-		/** @private */
-		getCaret: function() {
-			return this.caret ? this.start : this.end;
-		},
-		/** @private */
-		toString: function() {
-			return "start=" + this.start + " end=" + this.end + (this.caret ? " caret is at start" : " caret is at end");
-		},
-		/** @private */
-		isEmpty: function() {
-			return this.start === this.end;
-		},
-		/** @private */
-		equals: function(object) {
-			return this.caret === object.caret && this.start === object.start && this.end === object.end;
-		}
-	};
-	/**
-	 * @class This object describes the options for the text view.
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.TextView}<br/>
-	 * {@link orion.textview.TextView#setOptions}
-	 * {@link orion.textview.TextView#getOptions}	 
-	 * </p>		 
-	 * @name orion.textview.TextViewOptions
-	 *
-	 * @property {String|DOMElement} parent the parent element for the view, it can be either a DOM element or an ID for a DOM element.
-	 * @property {orion.textview.TextModel} [model] the text model for the view. If it is not set the view creates an empty {@link orion.textview.TextModel}.
-	 * @property {Boolean} [readonly=false] whether or not the view is read-only.
-	 * @property {Boolean} [fullSelection=true] whether or not the view is in full selection mode.
-	 * @property {Boolean} [sync=false] whether or not the view creation should be synchronous (if possible).
-	 * @property {Boolean} [expandTab=false] whether or not the tab key inserts white spaces.
-	 * @property {String|String[]} [stylesheet] one or more stylesheet for the view. Each stylesheet can be either a URI or a string containing the CSS rules.
-	 * @property {String} [themeClass] the CSS class for the view theming.
-	 * @property {Number} [tabSize] The number of spaces in a tab.
-	 */
-	/**
-	 * Constructs a new text view.
-	 * 
-	 * @param {orion.textview.TextViewOptions} options the view options.
-	 * 
-	 * @class A TextView is a user interface for editing text.
-	 * @name orion.textview.TextView
-	 * @borrows orion.textview.EventTarget#addEventListener as #addEventListener
-	 * @borrows orion.textview.EventTarget#removeEventListener as #removeEventListener
-	 * @borrows orion.textview.EventTarget#dispatchEvent as #dispatchEvent
-	 */
-	function TextView (options) {
-		this._init(options);
-	}
-	
-	TextView.prototype = /** @lends orion.textview.TextView.prototype */ {
-		/**
-		 * Adds a ruler to the text view.
-		 *
-		 * @param {orion.textview.Ruler} ruler the ruler.
-		 */
-		addRuler: function (ruler) {
-			this._rulers.push(ruler);
-			ruler.setView(this);
-			this._createRuler(ruler);
-			this._updatePage();
-		},
-		computeSize: function() {
-			var w = 0, h = 0;
-			var model = this._model, clientDiv = this._clientDiv;
-			if (!clientDiv) { return {width: w, height: h}; }
-			var clientWidth = clientDiv.style.width;
-			/*
-			* Feature in WekKit. Webkit limits the width of the lines
-			* computed below to the width of the client div.  This causes
-			* the lines to be wrapped even though "pre" is set.  The fix
-			* is to set the width of the client div to a larger number
-			* before computing the lines width.  Note that this value is
-			* reset to the appropriate value further down.
-			*/
-			if (isWebkit) {
-				clientDiv.style.width = (0x7FFFF).toString() + "px";
-			}
-			var lineCount = model.getLineCount();
-			var document = this._frameDocument;
-			for (var lineIndex=0; lineIndex<lineCount; lineIndex++) {
-				var child = this._getLineNode(lineIndex), dummy = null;
-				if (!child || child.lineChanged || child.lineRemoved) {
-					child = dummy = this._createLine(clientDiv, null, document, lineIndex, model);
-				}
-				var rect = this._getLineBoundingClientRect(child);
-				w = Math.max(w, rect.right - rect.left);
-				h += rect.bottom - rect.top;
-				if (dummy) { clientDiv.removeChild(dummy); }
-			}
-			if (isWebkit) {
-				clientDiv.style.width = clientWidth;
-			}
-			var viewPadding = this._getViewPadding();
-			w += viewPadding.right - viewPadding.left;
-			h += viewPadding.bottom - viewPadding.top;
-			return {width: w, height: h};
-		},
-		/**
-		 * Converts the given rectangle from one coordinate spaces to another.
-		 * <p>The supported coordinate spaces are:
-		 * <ul>
-		 *   <li>"document" - relative to document, the origin is the top-left corner of first line</li>
-		 *   <li>"page" - relative to html page that contains the text view</li>
-		 *   <li>"view" - relative to text view, the origin is the top-left corner of the view container</li>
-		 * </ul>
-		 * </p>
-		 * <p>All methods in the view that take or return a position are in the document coordinate space.</p>
-		 *
-		 * @param rect the rectangle to convert.
-		 * @param rect.x the x of the rectangle.
-		 * @param rect.y the y of the rectangle.
-		 * @param rect.width the width of the rectangle.
-		 * @param rect.height the height of the rectangle.
-		 * @param {String} from the source coordinate space.
-		 * @param {String} to the destination coordinate space.
-		 *
-		 * @see #getLocationAtOffset
-		 * @see #getOffsetAtLocation
-		 * @see #getTopPixel
-		 * @see #setTopPixel
-		 */
-		convert: function(rect, from, to) {
-			if (!this._clientDiv) { return; }
-			var scroll = this._getScroll();
-			var viewPad = this._getViewPadding();
-			var frame = this._frame.getBoundingClientRect();
-			var viewRect = this._viewDiv.getBoundingClientRect();
-			switch(from) {
-				case "document":
-					if (rect.x !== undefined) {
-						rect.x += - scroll.x + viewRect.left + viewPad.left;
-					}
-					if (rect.y !== undefined) {
-						rect.y += - scroll.y + viewRect.top + viewPad.top;
-					}
-					break;
-				case "page":
-					if (rect.x !== undefined) {
-						rect.x += - frame.left;
-					}
-					if (rect.y !== undefined) {
-						rect.y += - frame.top;
-					}
-					break;
-			}
-			//At this point rect is in the widget coordinate space
-			switch (to) {
-				case "document":
-					if (rect.x !== undefined) {
-						rect.x += scroll.x - viewRect.left - viewPad.left;
-					}
-					if (rect.y !== undefined) {
-						rect.y += scroll.y - viewRect.top - viewPad.top;
-					}
-					break;
-				case "page":
-					if (rect.x !== undefined) {
-						rect.x += frame.left;
-					}
-					if (rect.y !== undefined) {
-						rect.y += frame.top;
-					}
-					break;
-			}
-			return rect;
-		},
-		/**
-		 * Destroys the text view. 
-		 * <p>
-		 * Removes the view from the page and frees all resources created by the view.
-		 * Calling this function causes the "Destroy" event to be fire so that all components
-		 * attached to view can release their references.
-		 * </p>
-		 *
-		 * @see #onDestroy
-		 */
-		destroy: function() {
-			/* Destroy rulers*/
-			for (var i=0; i< this._rulers.length; i++) {
-				this._rulers[i].setView(null);
-			}
-			this.rulers = null;
-			
-			/*
-			* Note that when the frame is removed, the unload event is trigged
-			* and the view contents and handlers is released properly by
-			* destroyView().
-			*/
-			this._destroyFrame();
-
-			var e = {type: "Destroy"};
-			this.onDestroy(e);
-
-			this._parent = null;
-			this._parentDocument = null;
-			this._model = null;
-			this._selection = null;
-			this._doubleClickSelection = null;
-			this._keyBindings = null;
-			this._actions = null;
-		},
-		/**
-		 * Gives focus to the text view.
-		 */
-		focus: function() {
-			if (!this._clientDiv) { return; }
-			/*
-			* Feature in Chrome. When focus is called in the clientDiv without
-			* setting selection the browser will set the selection to the first dom 
-			* element, which can be above the client area. When this happen the 
-			* browser also scrolls the window to show that element.
-			* The fix is to call _updateDOMSelection() before calling focus().
-			*/
-			this._updateDOMSelection();
-			if (isPad) {
-				this._textArea.focus();
-			} else {
-				if (isOpera) { this._clientDiv.blur(); }
-				this._clientDiv.focus();
-			}
-			/*
-			* Feature in Safari. When focus is called the browser selects the clientDiv
-			* itself. The fix is to call _updateDOMSelection() after calling focus().
-			*/
-			this._updateDOMSelection();
-		},
-		/**
-		 * Check if the text view has focus.
-		 *
-		 * @returns {Boolean} <code>true</code> if the text view has focus, otherwise <code>false</code>.
-		 */
-		hasFocus: function() {
-			return this._hasFocus;
-		},
-		/**
-		 * Returns all action names defined in the text view.
-		 * <p>
-		 * There are two types of actions, the predefined actions of the view 
-		 * and the actions added by application code.
-		 * </p>
-		 * <p>
-		 * The predefined actions are:
-		 * <ul>
-		 *   <li>Navigation actions. These actions move the caret collapsing the selection.</li>
-		 *     <ul>
-		 *       <li>"lineUp" - moves the caret up by one line</li>
-		 *       <li>"lineDown" - moves the caret down by one line</li>
-		 *       <li>"lineStart" - moves the caret to beginning of the current line</li>
-		 *       <li>"lineEnd" - moves the caret to end of the current line </li>
-		 *       <li>"charPrevious" - moves the caret to the previous character</li>
-		 *       <li>"charNext" - moves the caret to the next character</li>
-		 *       <li>"pageUp" - moves the caret up by one page</li>
-		 *       <li>"pageDown" - moves the caret down by one page</li>
-		 *       <li>"wordPrevious" - moves the caret to the previous word</li>
-		 *       <li>"wordNext" - moves the caret to the next word</li>
-		 *       <li>"textStart" - moves the caret to the beginning of the document</li>
-		 *       <li>"textEnd" - moves the caret to the end of the document</li>
-		 *     </ul>
-		 *   <li>Selection actions. These actions move the caret extending the selection.</li>
-		 *     <ul>
-		 *       <li>"selectLineUp" - moves the caret up by one line</li>
-		 *       <li>"selectLineDown" - moves the caret down by one line</li>
-		 *       <li>"selectLineStart" - moves the caret to beginning of the current line</li>
-		 *       <li>"selectLineEnd" - moves the caret to end of the current line </li>
-		 *       <li>"selectCharPrevious" - moves the caret to the previous character</li>
-		 *       <li>"selectCharNext" - moves the caret to the next character</li>
-		 *       <li>"selectPageUp" - moves the caret up by one page</li>
-		 *       <li>"selectPageDown" - moves the caret down by one page</li>
-		 *       <li>"selectWordPrevious" - moves the caret to the previous word</li>
-		 *       <li>"selectWordNext" - moves the caret to the next word</li>
-		 *       <li>"selectTextStart" - moves the caret to the beginning of the document</li>
-		 *       <li>"selectTextEnd" - moves the caret to the end of the document</li>
-		 *       <li>"selectAll" - selects the entire document</li>
-		 *     </ul>
-		 *   <li>Edit actions. These actions modify the text view text</li>
-		 *     <ul>
-		 *       <li>"deletePrevious" - deletes the character preceding the caret</li>
-		 *       <li>"deleteNext" - deletes the charecter following the caret</li>
-		 *       <li>"deleteWordPrevious" - deletes the word preceding the caret</li>
-		 *       <li>"deleteWordNext" - deletes the word following the caret</li>
-		 *       <li>"tab" - inserts a tab character at the caret</li>
-		 *       <li>"enter" - inserts a line delimiter at the caret</li>
-		 *     </ul>
-		 *   <li>Clipboard actions.</li>
-		 *     <ul>
-		 *       <li>"copy" - copies the selected text to the clipboard</li>
-		 *       <li>"cut" - copies the selected text to the clipboard and deletes the selection</li>
-		 *       <li>"paste" - replaces the selected text with the clipboard contents</li>
-		 *     </ul>
-		 * </ul>
-		 * </p>
-		 *
-		 * @param {Boolean} [defaultAction=false] whether or not the predefined actions are included.
-		 * @returns {String[]} an array of action names defined in the text view.
-		 *
-		 * @see #invokeAction
-		 * @see #setAction
-		 * @see #setKeyBinding
-		 * @see #getKeyBindings
-		 */
-		getActions: function (defaultAction) {
-			var result = [];
-			var actions = this._actions;
-			for (var i = 0; i < actions.length; i++) {
-				if (!defaultAction && actions[i].defaultHandler) { continue; }
-				result.push(actions[i].name);
-			}
-			return result;
-		},
-		/**
-		 * Returns the bottom index.
-		 * <p>
-		 * The bottom index is the line that is currently at the bottom of the view.  This
-		 * line may be partially visible depending on the vertical scroll of the view. The parameter
-		 * <code>fullyVisible</code> determines whether to return only fully visible lines. 
-		 * </p>
-		 *
-		 * @param {Boolean} [fullyVisible=false] if <code>true</code>, returns the index of the last fully visible line. This
-		 *    parameter is ignored if the view is not big enough to show one line.
-		 * @returns {Number} the index of the bottom line.
-		 *
-		 * @see #getTopIndex
-		 * @see #setTopIndex
-		 */
-		getBottomIndex: function(fullyVisible) {
-			if (!this._clientDiv) { return 0; }
-			return this._getBottomIndex(fullyVisible);
-		},
-		/**
-		 * Returns the bottom pixel.
-		 * <p>
-		 * The bottom pixel is the pixel position that is currently at
-		 * the bottom edge of the view.  This position is relative to the
-		 * beginning of the document.
-		 * </p>
-		 *
-		 * @returns {Number} the bottom pixel.
-		 *
-		 * @see #getTopPixel
-		 * @see #setTopPixel
-		 * @see #convert
-		 */
-		getBottomPixel: function() {
-			if (!this._clientDiv) { return 0; }
-			return this._getScroll().y + this._getClientHeight();
-		},
-		/**
-		 * Returns the caret offset relative to the start of the document.
-		 *
-		 * @returns the caret offset relative to the start of the document.
-		 *
-		 * @see #setCaretOffset
-		 * @see #setSelection
-		 * @see #getSelection
-		 */
-		getCaretOffset: function () {
-			var s = this._getSelection();
-			return s.getCaret();
-		},
-		/**
-		 * Returns the client area.
-		 * <p>
-		 * The client area is the portion in pixels of the document that is visible. The
-		 * client area position is relative to the beginning of the document.
-		 * </p>
-		 *
-		 * @returns the client area rectangle {x, y, width, height}.
-		 *
-		 * @see #getTopPixel
-		 * @see #getBottomPixel
-		 * @see #getHorizontalPixel
-		 * @see #convert
-		 */
-		getClientArea: function() {
-			if (!this._clientDiv) { return {x: 0, y: 0, width: 0, height: 0}; }
-			var scroll = this._getScroll();
-			return {x: scroll.x, y: scroll.y, width: this._getClientWidth(), height: this._getClientHeight()};
-		},
-		/**
-		 * Returns the horizontal pixel.
-		 * <p>
-		 * The horizontal pixel is the pixel position that is currently at
-		 * the left edge of the view.  This position is relative to the
-		 * beginning of the document.
-		 * </p>
-		 *
-		 * @returns {Number} the horizontal pixel.
-		 *
-		 * @see #setHorizontalPixel
-		 * @see #convert
-		 */
-		getHorizontalPixel: function() {
-			if (!this._clientDiv) { return 0; }
-			return this._getScroll().x;
-		},
-		/**
-		 * Returns all the key bindings associated to the given action name.
-		 *
-		 * @param {String} name the action name.
-		 * @returns {orion.textview.KeyBinding[]} the array of key bindings associated to the given action name.
-		 *
-		 * @see #setKeyBinding
-		 * @see #setAction
-		 */
-		getKeyBindings: function (name) {
-			var result = [];
-			var keyBindings = this._keyBindings;
-			for (var i = 0; i < keyBindings.length; i++) {
-				if (keyBindings[i].name === name) {
-					result.push(keyBindings[i].keyBinding);
-				}
-			}
-			return result;
-		},
-		/**
-		 * Returns the line height for a given line index.  Returns the default line
-		 * height if the line index is not specified.
-		 *
-		 * @param {Number} [lineIndex] the line index.
-		 * @returns {Number} the height of the line in pixels.
-		 *
-		 * @see #getLinePixel
-		 */
-		getLineHeight: function(lineIndex) {
-			if (!this._clientDiv) { return 0; }
-			return this._getLineHeight();
-		},
-		/**
-		 * Returns the top pixel position of a given line index relative to the beginning
-		 * of the document.
-		 * <p>
-		 * Clamps out of range indices.
-		 * </p>
-		 *
-		 * @param {Number} lineIndex the line index.
-		 * @returns {Number} the pixel position of the line.
-		 *
-		 * @see #setTopPixel
-		 * @see #convert
-		 */
-		getLinePixel: function(lineIndex) {
-			if (!this._clientDiv) { return 0; }
-			lineIndex = Math.min(Math.max(0, lineIndex), this._model.getLineCount());
-			var lineHeight = this._getLineHeight();
-			return lineHeight * lineIndex;
-		},
-		/**
-		 * Returns the {x, y} pixel location of the top-left corner of the character
-		 * bounding box at the specified offset in the document.  The pixel location
-		 * is relative to the document.
-		 * <p>
-		 * Clamps out of range offsets.
-		 * </p>
-		 *
-		 * @param {Number} offset the character offset
-		 * @returns the {x, y} pixel location of the given offset.
-		 *
-		 * @see #getOffsetAtLocation
-		 * @see #convert
-		 */
-		getLocationAtOffset: function(offset) {
-			if (!this._clientDiv) { return {x: 0, y: 0}; }
-			var model = this._model;
-			offset = Math.min(Math.max(0, offset), model.getCharCount());
-			var lineIndex = model.getLineAtOffset(offset);
-			var scroll = this._getScroll();
-			var viewRect = this._viewDiv.getBoundingClientRect();
-			var viewPad = this._getViewPadding();
-			var x = this._getOffsetToX(offset) + scroll.x - viewRect.left - viewPad.left;
-			var y = this.getLinePixel(lineIndex);
-			return {x: x, y: y};
-		},
-		/**
-		 * Returns the specified view options.
-		 * <p>
-		 * The returned value is either a <code>orion.textview.TextViewOptions</code> or an option value. An option value is returned when only one string paremeter
-		 * is specified. A <code>orion.textview.TextViewOptions</code> is returned when there are no paremeters, or the parameters are a list of options names or a
-		 * <code>orion.textview.TextViewOptions</code>. All view options are returned when there no paremeters.
-		 * </p>
-		 *
-		 * @param {String|orion.textview.TextViewOptions} [options] The options to return.
-		 * @return {Object|orion.textview.TextViewOptions} The requested options or an option value.
-		 *
-		 * @see #setOptions
-		 */
-		getOptions: function() {
-			var options;
-			if (arguments.length === 0) {
-				options = this._defaultOptions();
-			} else if (arguments.length === 1) {
-				var arg = arguments[0];
-				if (typeof arg === "string") {
-					return this._clone(this["_" + arg]);
-				}
-				options = arg;
-			} else {
-				options = {};
-				for (var index in arguments) {
-					if (arguments.hasOwnProperty(index)) {
-						options[arguments[index]] = undefined;
-					}
-				}
-			}
-			for (var option in options) {
-				if (options.hasOwnProperty(option)) {
-					options[option] = this._clone(this["_" + option]);
-				}
-			}
-			return options;
-		},
-		/**
-		 * Returns the text model of the text view.
-		 *
-		 * @returns {orion.textview.TextModel} the text model of the view.
-		 */
-		getModel: function() {
-			return this._model;
-		},
-		/**
-		 * Returns the character offset nearest to the given pixel location.  The
-		 * pixel location is relative to the document.
-		 *
-		 * @param x the x of the location
-		 * @param y the y of the location
-		 * @returns the character offset at the given location.
-		 *
-		 * @see #getLocationAtOffset
-		 */
-		getOffsetAtLocation: function(x, y) {
-			if (!this._clientDiv) { return 0; }
-			var scroll = this._getScroll();
-			var viewRect = this._viewDiv.getBoundingClientRect();
-			var viewPad = this._getViewPadding();
-			var lineIndex = this._getYToLine(y - scroll.y);
-			x += -scroll.x + viewRect.left + viewPad.left;
-			var offset = this._getXToOffset(lineIndex, x);
-			return offset;
-		},
-		/**
-		 * Get the view rulers.
-		 *
-		 * @returns the view rulers
-		 *
-		 * @see #addRuler
-		 */
-		getRulers: function() {
-			return this._rulers.slice(0);
-		},
-		/**
-		 * Returns the text view selection.
-		 * <p>
-		 * The selection is defined by a start and end character offset relative to the
-		 * document. The character at end offset is not included in the selection.
-		 * </p>
-		 * 
-		 * @returns {orion.textview.Selection} the view selection
-		 *
-		 * @see #setSelection
-		 */
-		getSelection: function () {
-			var s = this._getSelection();
-			return {start: s.start, end: s.end};
-		},
-		/**
-		 * Returns the text for the given range.
-		 * <p>
-		 * The text does not include the character at the end offset.
-		 * </p>
-		 *
-		 * @param {Number} [start=0] the start offset of text range.
-		 * @param {Number} [end=char count] the end offset of text range.
-		 *
-		 * @see #setText
-		 */
-		getText: function(start, end) {
-			var model = this._model;
-			return model.getText(start, end);
-		},
-		/**
-		 * Returns the top index.
-		 * <p>
-		 * The top index is the line that is currently at the top of the view.  This
-		 * line may be partially visible depending on the vertical scroll of the view. The parameter
-		 * <code>fullyVisible</code> determines whether to return only fully visible lines. 
-		 * </p>
-		 *
-		 * @param {Boolean} [fullyVisible=false] if <code>true</code>, returns the index of the first fully visible line. This
-		 *    parameter is ignored if the view is not big enough to show one line.
-		 * @returns {Number} the index of the top line.
-		 *
-		 * @see #getBottomIndex
-		 * @see #setTopIndex
-		 */
-		getTopIndex: function(fullyVisible) {
-			if (!this._clientDiv) { return 0; }
-			return this._getTopIndex(fullyVisible);
-		},
-		/**
-		 * Returns the top pixel.
-		 * <p>
-		 * The top pixel is the pixel position that is currently at
-		 * the top edge of the view.  This position is relative to the
-		 * beginning of the document.
-		 * </p>
-		 *
-		 * @returns {Number} the top pixel.
-		 *
-		 * @see #getBottomPixel
-		 * @see #setTopPixel
-		 * @see #convert
-		 */
-		getTopPixel: function() {
-			if (!this._clientDiv) { return 0; }
-			return this._getScroll().y;
-		},
-		/**
-		 * Executes the action handler associated with the given name.
-		 * <p>
-		 * The application defined action takes precedence over predefined actions unless
-		 * the <code>defaultAction</code> paramater is <code>true</code>.
-		 * </p>
-		 * <p>
-		 * If the application defined action returns <code>false</code>, the text view predefined
-		 * action is executed if present.
-		 * </p>
-		 *
-		 * @param {String} name the action name.
-		 * @param {Boolean} [defaultAction] whether to always execute the predefined action.
-		 * @returns {Boolean} <code>true</code> if the action was executed.
-		 *
-		 * @see #setAction
-		 * @see #getActions
-		 */
-		invokeAction: function (name, defaultAction) {
-			if (!this._clientDiv) { return; }
-			var actions = this._actions;
-			for (var i = 0; i < actions.length; i++) {
-				var a = actions[i];
-				if (a.name && a.name === name) {
-					if (!defaultAction && a.userHandler) {
-						if (a.userHandler()) { return; }
-					}
-					if (a.defaultHandler) { return a.defaultHandler(); }
-					return false;
-				}
-			}
-			return false;
-		},
-		/**
-		* Returns if the view is loaded.
-		* <p>
-		* @returns {Boolean} <code>true</code> if the view is loaded.
-		*
-		* @see #onLoad
-		*/
-		isLoaded: function () {
-			return !!this._clientDiv;
-		},
-		/** 
-		 * @class This is the event sent when the user right clicks or otherwise invokes the context menu of the view. 
-		 * <p> 
-		 * <b>See:</b><br/> 
-		 * {@link orion.textview.TextView}<br/> 
-		 * {@link orion.textview.TextView#event:onContextMenu} 
-		 * </p> 
-		 * 
-		 * @name orion.textview.ContextMenuEvent 
-		 * 
-		 * @property {Number} x The pointer location on the x axis, relative to the document the user is editing. 
-		 * @property {Number} y The pointer location on the y axis, relative to the document the user is editing. 
-		 * @property {Number} screenX The pointer location on the x axis, relative to the screen. This is copied from the DOM contextmenu event.screenX property. 
-		 * @property {Number} screenY The pointer location on the y axis, relative to the screen. This is copied from the DOM contextmenu event.screenY property. 
-		 */ 
-		/** 
-		 * This event is sent when the user invokes the view context menu. 
-		 * 
-		 * @event 
-		 * @param {orion.textview.ContextMenuEvent} contextMenuEvent the event 
-		 */ 
-		onContextMenu: function(contextMenuEvent) {
-			return this.dispatchEvent(contextMenuEvent); 
-		}, 
-		onDragStart: function(dragEvent) {
-			return this.dispatchEvent(dragEvent);
-		},
-		onDrag: function(dragEvent) {
-			return this.dispatchEvent(dragEvent);
-		},
-		onDragEnd: function(dragEvent) {
-			return this.dispatchEvent(dragEvent);
-		},
-		onDragEnter: function(dragEvent) {
-			return this.dispatchEvent(dragEvent);
-		},
-		onDragOver: function(dragEvent) {
-			return this.dispatchEvent(dragEvent);
-		},
-		onDragLeave: function(dragEvent) {
-			return this.dispatchEvent(dragEvent);
-		},
-		onDrop: function(dragEvent) {
-			return this.dispatchEvent(dragEvent);
-		},
-		/**
-		 * @class This is the event sent when the text view is destroyed.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onDestroy}
-		 * </p>
-		 * @name orion.textview.DestroyEvent
-		 */
-		/**
-		 * This event is sent when the text view has been destroyed.
-		 *
-		 * @event
-		 * @param {orion.textview.DestroyEvent} destroyEvent the event
-		 *
-		 * @see #destroy
-		 */
-		onDestroy: function(destroyEvent) {
-			return this.dispatchEvent(destroyEvent);
-		},
-		/**
-		 * @class This object is used to define style information for the text view.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onLineStyle}
-		 * </p>		 
-		 * @name orion.textview.Style
-		 * 
-		 * @property {String} styleClass A CSS class name.
-		 * @property {Object} style An object with CSS properties.
-		 * @property {String} tagName A DOM tag name.
-		 * @property {Object} attributes An object with DOM attributes.
-		 */
-		/**
-		 * @class This object is used to style range.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onLineStyle}
-		 * </p>		 
-		 * @name orion.textview.StyleRange
-		 * 
-		 * @property {Number} start The start character offset, relative to the document, where the style should be applied.
-		 * @property {Number} end The end character offset (exclusive), relative to the document, where the style should be applied.
-		 * @property {orion.textview.Style} style The style for the range.
-		 */
-		/**
-		 * @class This is the event sent when the text view needs the style information for a line.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onLineStyle}
-		 * </p>		 
-		 * @name orion.textview.LineStyleEvent
-		 * 
-		 * @property {orion.textview.TextView} textView The text view.		 
-		 * @property {Number} lineIndex The line index.
-		 * @property {String} lineText The line text.
-		 * @property {Number} lineStart The character offset, relative to document, of the first character in the line.
-		 * @property {orion.textview.Style} style The style for the entire line (output argument).
-		 * @property {orion.textview.StyleRange[]} ranges An array of style ranges for the line (output argument).		 
-		 */
-		/**
-		 * This event is sent when the text view needs the style information for a line.
-		 *
-		 * @event
-		 * @param {orion.textview.LineStyleEvent} lineStyleEvent the event
-		 */
-		onLineStyle: function(lineStyleEvent) {
-			return this.dispatchEvent(lineStyleEvent);
-		},
-		/**
-		 * @class This is the event sent when the text view has loaded its contents.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onLoad}
-		 * </p>		 
-		 * @name orion.textview.LoadEvent
-		 */
-		/**
-		 * This event is sent when the text view has loaded its contents.
-		 *
-		 * @event
-		 * @param {orion.textview.LoadEvent} loadEvent the event
-		 */
-		onLoad: function(loadEvent) {
-			return this.dispatchEvent(loadEvent);
-		},
-		/**
-		 * @class This is the event sent when the text in the model has changed.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onModelChanged}<br/>
-		 * {@link orion.textview.TextModel#onChanged}
-		 * </p>
-		 * @name orion.textview.ModelChangedEvent
-		 * 
-		 * @property {Number} start The character offset in the model where the change has occurred.
-		 * @property {Number} removedCharCount The number of characters removed from the model.
-		 * @property {Number} addedCharCount The number of characters added to the model.
-		 * @property {Number} removedLineCount The number of lines removed from the model.
-		 * @property {Number} addedLineCount The number of lines added to the model.
-		 */
-		/**
-		 * This event is sent when the text in the model has changed.
-		 *
-		 * @event
-		 * @param {orion.textview.ModelChangedEvent} modelChangedEvent the event
-		 */
-		onModelChanged: function(modelChangedEvent) {
-			return this.dispatchEvent(modelChangedEvent);
-		},
-		/**
-		 * @class This is the event sent when the text in the model is about to change.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onModelChanging}<br/>
-		 * {@link orion.textview.TextModel#onChanging}
-		 * </p>
-		 * @name orion.textview.ModelChangingEvent
-		 * 
-		 * @property {String} text The text that is about to be inserted in the model.
-		 * @property {Number} start The character offset in the model where the change will occur.
-		 * @property {Number} removedCharCount The number of characters being removed from the model.
-		 * @property {Number} addedCharCount The number of characters being added to the model.
-		 * @property {Number} removedLineCount The number of lines being removed from the model.
-		 * @property {Number} addedLineCount The number of lines being added to the model.
-		 */
-		/**
-		 * This event is sent when the text in the model is about to change.
-		 *
-		 * @event
-		 * @param {orion.textview.ModelChangingEvent} modelChangingEvent the event
-		 */
-		onModelChanging: function(modelChangingEvent) {
-			return this.dispatchEvent(modelChangingEvent);
-		},
-		/**
-		 * @class This is the event sent when the text is modified by the text view.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onModify}
-		 * </p>
-		 * @name orion.textview.ModifyEvent
-		 */
-		/**
-		 * This event is sent when the text view has changed text in the model.
-		 * <p>
-		 * If the text is changed directly through the model API, this event
-		 * is not sent.
-		 * </p>
-		 *
-		 * @event
-		 * @param {orion.textview.ModifyEvent} modifyEvent the event
-		 */
-		onModify: function(modifyEvent) {
-			return this.dispatchEvent(modifyEvent);
-		},
-		onMouseDown: function(mouseEvent) {
-			return this.dispatchEvent(mouseEvent);
-		},
-		onMouseUp: function(mouseEvent) {
-			return this.dispatchEvent(mouseEvent);
-		},
-		onMouseMove: function(mouseEvent) {
-			return this.dispatchEvent(mouseEvent);
-		},
-		onMouseOver: function(mouseEvent) {
-			return this.dispatchEvent(mouseEvent);
-		},
-		onMouseOut: function(mouseEvent) {
-			return this.dispatchEvent(mouseEvent);
-		},
-		/**
-		 * @class This is the event sent when the selection changes in the text view.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onSelection}
-		 * </p>		 
-		 * @name orion.textview.SelectionEvent
-		 * 
-		 * @property {orion.textview.Selection} oldValue The old selection.
-		 * @property {orion.textview.Selection} newValue The new selection.
-		 */
-		/**
-		 * This event is sent when the text view selection has changed.
-		 *
-		 * @event
-		 * @param {orion.textview.SelectionEvent} selectionEvent the event
-		 */
-		onSelection: function(selectionEvent) {
-			return this.dispatchEvent(selectionEvent);
-		},
-		/**
-		 * @class This is the event sent when the text view scrolls.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onScroll}
-		 * </p>		 
-		 * @name orion.textview.ScrollEvent
-		 * 
-		 * @property oldValue The old scroll {x,y}.
-		 * @property newValue The new scroll {x,y}.
-		 */
-		/**
-		 * This event is sent when the text view scrolls vertically or horizontally.
-		 *
-		 * @event
-		 * @param {orion.textview.ScrollEvent} scrollEvent the event
-		 */
-		onScroll: function(scrollEvent) {
-			return this.dispatchEvent(scrollEvent);
-		},
-		/**
-		 * @class This is the event sent when the text is about to be modified by the text view.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onVerify}
-		 * </p>
-		 * @name orion.textview.VerifyEvent
-		 * 
-		 * @property {String} text The text being inserted.
-		 * @property {Number} start The start offset of the text range to be replaced.
-		 * @property {Number} end The end offset (exclusive) of the text range to be replaced.
-		 */
-		/**
-		 * This event is sent when the text view is about to change text in the model.
-		 * <p>
-		 * If the text is changed directly through the model API, this event
-		 * is not sent.
-		 * </p>
-		 * <p>
-		 * Listeners are allowed to change these parameters. Setting text to null
-		 * or undefined stops the change.
-		 * </p>
-		 *
-		 * @event
-		 * @param {orion.textview.VerifyEvent} verifyEvent the event
-		 */
-		onVerify: function(verifyEvent) {
-			return this.dispatchEvent(verifyEvent);
-		},
-		/**
-		 * @class This is the event sent when the text view has unloaded its contents.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onLoad}
-		 * </p>		 
-		 * @name orion.textview.UnloadEvent
-		 */
-		/**
-		 * This event is sent when the text view has unloaded its contents.
-		 *
-		 * @event
-		 * @param {orion.textview.UnloadEvent} unloadEvent the event
-		 */
-		onUnload: function(unloadEvent) {
-			return this.dispatchEvent(unloadEvent);
-		},
-		/**
-		 * @class This is the event sent when the text view is focused.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onFocus}<br/>
-		 * </p>
-		 * @name orion.textview.FocusEvent
-		 */
-		/**
-		 * This event is sent when the text view is focused.
-		 *
-		 * @event
-		 * @param {orion.textview.FocusEvent} focusEvent the event
-		 */
-		onFocus: function(focusEvent) {
-			return this.dispatchEvent(focusEvent);
-		},
-		/**
-		 * @class This is the event sent when the text view goes out of focus.
-		 * <p>
-		 * <b>See:</b><br/>
-		 * {@link orion.textview.TextView}<br/>
-		 * {@link orion.textview.TextView#event:onBlur}<br/>
-		 * </p>
-		 * @name orion.textview.BlurEvent
-		 */
-		/**
-		 * This event is sent when the text view goes out of focus.
-		 *
-		 * @event
-		 * @param {orion.textview.BlurEvent} blurEvent the event
-		 */
-		onBlur: function(blurEvent) {
-			return this.dispatchEvent(blurEvent);
-		},
-		/**
-		 * Redraws the entire view, including rulers.
-		 *
-		 * @see #redrawLines
-		 * @see #redrawRange
-		 * @see #setRedraw
-		 */
-		redraw: function() {
-			if (this._redrawCount > 0) { return; }
-			var lineCount = this._model.getLineCount();
-			var rulers = this.getRulers();
-			for (var i = 0; i < rulers.length; i++) {
-				this.redrawLines(0, lineCount, rulers[i]);
-			}
-			this.redrawLines(0, lineCount); 
-		},
-		/**
-		 * Redraws the text in the given line range.
-		 * <p>
-		 * The line at the end index is not redrawn.
-		 * </p>
-		 *
-		 * @param {Number} [startLine=0] the start line
-		 * @param {Number} [endLine=line count] the end line
-		 *
-		 * @see #redraw
-		 * @see #redrawRange
-		 * @see #setRedraw
-		 */
-		redrawLines: function(startLine, endLine, ruler) {
-			if (this._redrawCount > 0) { return; }
-			if (startLine === undefined) { startLine = 0; }
-			if (endLine === undefined) { endLine = this._model.getLineCount(); }
-			if (startLine === endLine) { return; }
-			var div = this._clientDiv;
-			if (!div) { return; }
-			if (ruler) {
-				var location = ruler.getLocation();//"left" or "right"
-				var divRuler = location === "left" ? this._leftDiv : this._rightDiv;
-				var cells = divRuler.firstChild.rows[0].cells;
-				for (var i = 0; i < cells.length; i++) {
-					if (cells[i].firstChild._ruler === ruler) {
-						div = cells[i].firstChild;
-						break;
-					}
-				}
-			}
-			if (ruler) {
-				div.rulerChanged = true;
-			}
-			if (!ruler || ruler.getOverview() === "page") {
-				var child = div.firstChild;
-				while (child) {
-					var lineIndex = child.lineIndex;
-					if (startLine <= lineIndex && lineIndex < endLine) {
-						child.lineChanged = true;
-					}
-					child = child.nextSibling;
-				}
-			}
-			if (!ruler) {
-				if (startLine <= this._maxLineIndex && this._maxLineIndex < endLine) {
-					this._checkMaxLineIndex = this._maxLineIndex;
-					this._maxLineIndex = -1;
-					this._maxLineWidth = 0;
-				}
-			}
-			this._queueUpdatePage();
-		},
-		/**
-		 * Redraws the text in the given range.
-		 * <p>
-		 * The character at the end offset is not redrawn.
-		 * </p>
-		 *
-		 * @param {Number} [start=0] the start offset of text range
-		 * @param {Number} [end=char count] the end offset of text range
-		 *
-		 * @see #redraw
-		 * @see #redrawLines
-		 * @see #setRedraw
-		 */
-		redrawRange: function(start, end) {
-			if (this._redrawCount > 0) { return; }
-			var model = this._model;
-			if (start === undefined) { start = 0; }
-			if (end === undefined) { end = model.getCharCount(); }
-			var startLine = model.getLineAtOffset(start);
-			var endLine = model.getLineAtOffset(Math.max(start, end - 1)) + 1;
-			this.redrawLines(startLine, endLine);
-		},
-		/**
-		 * Removes a ruler from the text view.
-		 *
-		 * @param {orion.textview.Ruler} ruler the ruler.
-		 */
-		removeRuler: function (ruler) {
-			var rulers = this._rulers;
-			for (var i=0; i<rulers.length; i++) {
-				if (rulers[i] === ruler) {
-					rulers.splice(i, 1);
-					ruler.setView(null);
-					this._destroyRuler(ruler);
-					this._updatePage();
-					break;
-				}
-			}
-		},
-		/**
-		 * Associates an application defined handler to an action name.
-		 * <p>
-		 * If the action name is a predefined action, the given handler executes before
-		 * the default action handler.  If the given handler returns <code>true</code>, the
-		 * default action handler is not called.
-		 * </p>
-		 *
-		 * @param {String} name the action name.
-		 * @param {Function} handler the action handler.
-		 *
-		 * @see #getActions
-		 * @see #invokeAction
-		 */
-		setAction: function(name, handler) {
-			if (!name) { return; }
-			var actions = this._actions;
-			for (var i = 0; i < actions.length; i++) {
-				var a = actions[i];
-				if (a.name === name) {
-					a.userHandler = handler;
-					return;
-				}
-			}
-			actions.push({name: name, userHandler: handler});
-		},
-		/**
-		 * Associates a key binding with the given action name. Any previous
-		 * association with the specified key binding is overwriten. If the
-		 * action name is <code>null</code>, the association is removed.
-		 * 
-		 * @param {orion.textview.KeyBinding} keyBinding the key binding
-		 * @param {String} name the action
-		 */
-		setKeyBinding: function(keyBinding, name) {
-			var keyBindings = this._keyBindings;
-			for (var i = 0; i < keyBindings.length; i++) {
-				var kb = keyBindings[i]; 
-				if (kb.keyBinding.equals(keyBinding)) {
-					if (name) {
-						kb.name = name;
-					} else {
-						if (kb.predefined) {
-							kb.name = null;
-						} else {
-							var oldName = kb.name; 
-							keyBindings.splice(i, 1);
-							var index = 0;
-							while (index < keyBindings.length && oldName !== keyBindings[index].name) {
-								index++;
-							}
-							if (index === keyBindings.length) {
-								/* <p>
-								 * Removing all the key bindings associated to an user action will cause
-								 * the user action to be removed. TextView predefined actions are never
-								 * removed (so they can be reinstalled in the future). 
-								 * </p>
-								 */
-								var actions = this._actions;
-								for (var j = 0; j < actions.length; j++) {
-									if (actions[j].name === oldName) {
-										if (!actions[j].defaultHandler) {
-											actions.splice(j, 1);
-										}
-									}
-								}
-							}
-						}
-					}
-					return;
-				}
-			}
-			if (name) {
-				keyBindings.push({keyBinding: keyBinding, name: name});
-			}
-		},
-		/**
-		 * Sets the caret offset relative to the start of the document.
-		 *
-		 * @param {Number} caret the caret offset relative to the start of the document.
-		 * @param {Boolean} [show=true] if <code>true</code>, the view will scroll if needed to show the caret location.
-		 *
-		 * @see #getCaretOffset
-		 * @see #setSelection
-		 * @see #getSelection
-		 */
-		setCaretOffset: function(offset, show) {
-			var charCount = this._model.getCharCount();
-			offset = Math.max(0, Math.min (offset, charCount));
-			var selection = new Selection(offset, offset, false);
-			this._setSelection (selection, show === undefined || show);
-		},
-		/**
-		 * Sets the horizontal pixel.
-		 * <p>
-		 * The horizontal pixel is the pixel position that is currently at
-		 * the left edge of the view.  This position is relative to the
-		 * beginning of the document.
-		 * </p>
-		 *
-		 * @param {Number} pixel the horizontal pixel.
-		 *
-		 * @see #getHorizontalPixel
-		 * @see #convert
-		 */
-		setHorizontalPixel: function(pixel) {
-			if (!this._clientDiv) { return; }
-			pixel = Math.max(0, pixel);
-			this._scrollView(pixel - this._getScroll().x, 0);
-		},
-		/**
-		 * Sets whether the view should update the DOM.
-		 * <p>
-		 * This can be used to improve the performance.
-		 * </p><p>
-		 * When the flag is set to <code>true</code>,
-		 * the entire view is marked as needing to be redrawn. 
-		 * Nested calls to this method are stacked.
-		 * </p>
-		 *
-		 * @param {Boolean} redraw the new redraw state
-		 * 
-		 * @see #redraw
-		 */
-		setRedraw: function(redraw) {
-			if (redraw) {
-				if (--this._redrawCount === 0) {
-					this.redraw();
-				}
-			} else {
-				this._redrawCount++;
-			}
-		},
-		/**
-		 * Sets the text model of the text view.
-		 *
-		 * @param {orion.textview.TextModel} model the text model of the view.
-		 */
-		setModel: function(model) {
-			if (!model) { return; }
-			if (model === this._model) { return; }
-			this._model.removeEventListener("Changing", this._modelListener.onChanging);
-			this._model.removeEventListener("Changed", this._modelListener.onChanged);
-			var oldLineCount = this._model.getLineCount();
-			var oldCharCount = this._model.getCharCount();
-			var newLineCount = model.getLineCount();
-			var newCharCount = model.getCharCount();
-			var newText = model.getText();
-			var e = {
-				type: "ModelChanging",
-				text: newText,
-				start: 0,
-				removedCharCount: oldCharCount,
-				addedCharCount: newCharCount,
-				removedLineCount: oldLineCount,
-				addedLineCount: newLineCount
-			};
-			this.onModelChanging(e);
-			this._model = model;
-			e = {
-				type: "ModelChanged",
-				start: 0,
-				removedCharCount: oldCharCount,
-				addedCharCount: newCharCount,
-				removedLineCount: oldLineCount,
-				addedLineCount: newLineCount
-			};
-			this.onModelChanged(e); 
-			this._model.addEventListener("Changing", this._modelListener.onChanging);
-			this._model.addEventListener("Changed", this._modelListener.onChanged);
-			this._reset();
-			this._updatePage();
-		},
-		/**
-		 * Sets the view options for the view.
-		 *
-		 * @param {orion.textview.TextViewOptions} options the view options.
-		 * 
-		 * @see #getOptions
-		 */
-		setOptions: function (options) {
-			var defaultOptions = this._defaultOptions();
-			var recreate = false, option, created = this._clientDiv;
-			if (created) {
-				for (option in options) {
-					if (options.hasOwnProperty(option)) {
-						if (defaultOptions[option].recreate) {
-							recreate = true;
-							break;
-						}
-					}
-				}
-			}
-			var changed = false;
-			for (option in options) {
-				if (options.hasOwnProperty(option)) {
-					var newValue = options[option], oldValue = this["_" + option];
-					if (this._compare(oldValue, newValue)) { continue; }
-					changed = true;
-					if (!recreate) {
-						var update = defaultOptions[option].update;
-						if (created && update) {
-							if (update.call(this, newValue)) {
-								recreate = true;
-							}
-							continue;
-						}
-					}
-					this["_" + option] = this._clone(newValue);
-				}
-			}
-			if (changed) {
-				if (recreate) {
-					var oldParent = this._frame.parentNode;
-					oldParent.removeChild(this._frame);
-					this._parent.appendChild(this._frame);
-				}
-			}
-		},
-		/**
-		 * Sets the text view selection.
-		 * <p>
-		 * The selection is defined by a start and end character offset relative to the
-		 * document. The character at end offset is not included in the selection.
-		 * </p>
-		 * <p>
-		 * The caret is always placed at the end offset. The start offset can be
-		 * greater than the end offset to place the caret at the beginning of the
-		 * selection.
-		 * </p>
-		 * <p>
-		 * Clamps out of range offsets.
-		 * </p>
-		 * 
-		 * @param {Number} start the start offset of the selection
-		 * @param {Number} end the end offset of the selection
-		 * @param {Boolean} [show=true] if <code>true</code>, the view will scroll if needed to show the caret location.
-		 *
-		 * @see #getSelection
-		 */
-		setSelection: function (start, end, show) {
-			var caret = start > end;
-			if (caret) {
-				var tmp = start;
-				start = end;
-				end = tmp;
-			}
-			var charCount = this._model.getCharCount();
-			start = Math.max(0, Math.min (start, charCount));
-			end = Math.max(0, Math.min (end, charCount));
-			var selection = new Selection(start, end, caret);
-			this._setSelection(selection, show === undefined || show);
-		},
-		/**
-		 * Replaces the text in the given range with the given text.
-		 * <p>
-		 * The character at the end offset is not replaced.
-		 * </p>
-		 * <p>
-		 * When both <code>start</code> and <code>end</code> parameters
-		 * are not specified, the text view places the caret at the beginning
-		 * of the document and scrolls to make it visible.
-		 * </p>
-		 *
-		 * @param {String} text the new text.
-		 * @param {Number} [start=0] the start offset of text range.
-		 * @param {Number} [end=char count] the end offset of text range.
-		 *
-		 * @see #getText
-		 */
-		setText: function (text, start, end) {
-			var reset = start === undefined && end === undefined;
-			if (start === undefined) { start = 0; }
-			if (end === undefined) { end = this._model.getCharCount(); }
-			this._modifyContent({text: text, start: start, end: end, _code: true}, !reset);
-			if (reset) {
-				this._columnX = -1;
-				this._setSelection(new Selection (0, 0, false), true);
-				
-				/*
-				* Bug in Firefox.  For some reason, the caret does not show after the
-				* view is refreshed.  The fix is to toggle the contentEditable state and
-				* force the clientDiv to loose and receive focus if it is focused.
-				*/
-				if (isFirefox) {
-					this._fixCaret();
-				}
-			}
-		},
-		/**
-		 * Sets the top index.
-		 * <p>
-		 * The top index is the line that is currently at the top of the text view.  This
-		 * line may be partially visible depending on the vertical scroll of the view.
-		 * </p>
-		 *
-		 * @param {Number} topIndex the index of the top line.
-		 *
-		 * @see #getBottomIndex
-		 * @see #getTopIndex
-		 */
-		setTopIndex: function(topIndex) {
-			if (!this._clientDiv) { return; }
-			var model = this._model;
-			if (model.getCharCount() === 0) {
-				return;
-			}
-			var lineCount = model.getLineCount();
-			var lineHeight = this._getLineHeight();
-			var pageSize = Math.max(1, Math.min(lineCount, Math.floor(this._getClientHeight () / lineHeight)));
-			if (topIndex < 0) {
-				topIndex = 0;
-			} else if (topIndex > lineCount - pageSize) {
-				topIndex = lineCount - pageSize;
-			}
-			var pixel = topIndex * lineHeight - this._getScroll().y;
-			this._scrollView(0, pixel);
-		},
-		/**
-		 * Sets the top pixel.
-		 * <p>
-		 * The top pixel is the pixel position that is currently at
-		 * the top edge of the view.  This position is relative to the
-		 * beginning of the document.
-		 * </p>
-		 *
-		 * @param {Number} pixel the top pixel.
-		 *
-		 * @see #getBottomPixel
-		 * @see #getTopPixel
-		 * @see #convert
-		 */
-		setTopPixel: function(pixel) {
-			if (!this._clientDiv) { return; }
-			var lineHeight = this._getLineHeight();
-			var clientHeight = this._getClientHeight();
-			var lineCount = this._model.getLineCount();
-			pixel = Math.min(Math.max(0, pixel), lineHeight * lineCount - clientHeight);
-			this._scrollView(0, pixel - this._getScroll().y);
-		},
-		/**
-		 * Scrolls the selection into view if needed.
-		 *
-		 * @returns true if the view was scrolled. 
-		 *
-		 * @see #getSelection
-		 * @see #setSelection
-		 */
-		showSelection: function() {
-			return this._showCaret(true);
-		},
-		
-		/**************************************** Event handlers *********************************/
-		_handleBodyMouseDown: function (e) {
-			if (!e) { e = window.event; }
-			if (isFirefox && e.which === 1) {
-				this._clientDiv.contentEditable = false;
-				(this._overlayDiv || this._clientDiv).draggable = true;
-				this._ignoreBlur = true;
-			}
-			
-			/*
-			 * Prevent clicks outside of the view from taking focus 
-			 * away the view. Note that in Firefox and Opera clicking on the 
-			 * scrollbar also take focus from the view. Other browsers
-			 * do not have this problem and stopping the click over the 
-			 * scrollbar for them causes mouse capture problems.
-			 */
-			var topNode = isOpera || (isFirefox && !this._overlayDiv) ? this._clientDiv : this._overlayDiv || this._viewDiv;
-			
-			var temp = e.target ? e.target : e.srcElement;
-			while (temp) {
-				if (topNode === temp) {
-					return;
-				}
-				temp = temp.parentNode;
-			}
-			if (e.preventDefault) { e.preventDefault(); }
-			if (e.stopPropagation){ e.stopPropagation(); }
-			if (!isW3CEvents) {
-				/* In IE 8 is not possible to prevent the default handler from running
-				*  during mouse down event using usual API. The workaround is to use
-				*  setCapture/releaseCapture. 
-				*/ 
-				topNode.setCapture();
-				setTimeout(function() { topNode.releaseCapture(); }, 0);
-			}
-		},
-		_handleBodyMouseUp: function (e) {
-			if (!e) { e = window.event; }
-			if (isFirefox && e.which === 1) {
-				this._clientDiv.contentEditable = true;
-				(this._overlayDiv || this._clientDiv).draggable = false;
-				
-				/*
-				* Bug in Firefox.  For some reason, Firefox stops showing the caret
-				* in some cases. For example when the user cancels a drag operation 
-				* by pressing ESC.  The fix is to detect that the drag operation was
-				* cancelled,  toggle the contentEditable state and force the clientDiv
-				* to loose and receive focus if it is focused.
-				*/
-				this._fixCaret();
-				this._ignoreBlur = false;
-			}
-		},
-		_handleBlur: function (e) {
-			if (!e) { e = window.event; }
-			if (this._ignoreBlur) { return; }
-			this._hasFocus = false;
-			/*
-			* Bug in IE 8 and earlier. For some reason when text is deselected
-			* the overflow selection at the end of some lines does not get redrawn.
-			* The fix is to create a DOM element in the body to force a redraw.
-			*/
-			if (isIE < 9) {
-				if (!this._getSelection().isEmpty()) {
-					var document = this._frameDocument;
-					var child = document.createElement("DIV");
-					var body = document.body;
-					body.appendChild(child);
-					body.removeChild(child);
-				}
-			}
-			if (isFirefox || isIE) {
-				if (this._selDiv1) {
-					var color = isIE ? "transparent" : "#AFAFAF";
-					this._selDiv1.style.background = color;
-					this._selDiv2.style.background = color;
-					this._selDiv3.style.background = color;
-				}
-			}
-			if (!this._ignoreFocus) {
-				this.onBlur({type: "Blur"});
-			}
-		},
-		_handleContextMenu: function (e) {
-			if (!e) { e = window.event; }
-			if (isFirefox && this._lastMouseButton === 3) {
-				// We need to update the DOM selection, because on
-				// right-click the caret moves to the mouse location.
-				// See bug 366312.
-				var timeDiff = e.timeStamp - this._lastMouseTime;
-				if (timeDiff <= this._clickTime) {
-					this._updateDOMSelection();
-				}
-			}
-			if (this.isListening("ContextMenu")) {
-				var evt = this._createMouseEvent("ContextMenu", e);
-				evt.screenX = e.screenX;
-				evt.screenY = e.screenY;
-				this.onContextMenu(evt);
-			}
-			if (e.preventDefault) { e.preventDefault(); }
-			return false;
-		},
-		_handleCopy: function (e) {
-			if (this._ignoreCopy) { return; }
-			if (!e) { e = window.event; }
-			if (this._doCopy(e)) {
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleCut: function (e) {
-			if (!e) { e = window.event; }
-			if (this._doCut(e)) {
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleDOMAttrModified: function (e) {
-			if (!e) { e = window.event; }
-			var ancestor = false;
-			var parent = this._parent;
-			while (parent) {
-				if (parent === e.target) {
-					ancestor = true;
-					break;
-				}
-				parent = parent.parentNode;
-			}
-			if (!ancestor) { return; }
-			var state = this._getVisible();
-			if (state === "visible") {
-				this._createView();
-			} else if (state === "hidden") {
-				this._destroyView();
-			}
-		},
-		_handleDataModified: function(e) {
-			this._startIME();
-		},
-		_handleDblclick: function (e) {
-			if (!e) { e = window.event; }
-			var time = e.timeStamp ? e.timeStamp : new Date().getTime();
-			this._lastMouseTime = time;
-			if (this._clickCount !== 2) {
-				this._clickCount = 2;
-				this._handleMouse(e);
-			}
-		},
-		_handleDragStart: function (e) {
-			if (!e) { e = window.event; }
-			if (isFirefox) {
-				var self = this;
-				setTimeout(function() {
-					self._clientDiv.contentEditable = true;
-					self._clientDiv.draggable = false;
-					self._ignoreBlur = false;
-				}, 0);
-			}
-			if (this.isListening("DragStart") && this._dragOffset !== -1) {
-				this._isMouseDown = false;
-				this.onDragStart(this._createMouseEvent("DragStart", e));
-				this._dragOffset = -1;
-			} else {
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleDrag: function (e) {
-			if (!e) { e = window.event; }
-			if (this.isListening("Drag")) {
-				this.onDrag(this._createMouseEvent("Drag", e));
-			}
-		},
-		_handleDragEnd: function (e) {
-			if (!e) { e = window.event; }
-			this._dropTarget = false;
-			this._dragOffset = -1;
-			if (this.isListening("DragEnd")) {
-				this.onDragEnd(this._createMouseEvent("DragEnd", e));
-			}
-			if (isFirefox) {
-				this._fixCaret();
-				/*
-				* Bug in Firefox.  For some reason, Firefox stops showing the caret when the 
-				* selection is dropped onto itself. The fix is to detected the case and 
-				* call fixCaret() a second time.
-				*/
-				if (e.dataTransfer.dropEffect === "none" && !e.dataTransfer.mozUserCancelled) {
-					this._fixCaret();
-				}
-			}
-		},
-		_handleDragEnter: function (e) {
-			if (!e) { e = window.event; }
-			var prevent = true;
-			this._dropTarget = true;
-			if (this.isListening("DragEnter")) {
-				prevent = false;
-				this.onDragEnter(this._createMouseEvent("DragEnter", e));
-			}
-			/*
-			* Webkit will not send drop events if this event is not prevented, as spec in HTML5.
-			* Firefox and IE do not follow this spec for contentEditable. Note that preventing this 
-			* event will result is loss of functionality (insertion mark, etc).
-			*/
-			if (isWebkit || prevent) {
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleDragOver: function (e) {
-			if (!e) { e = window.event; }
-			var prevent = true;
-			if (this.isListening("DragOver")) {
-				prevent = false;
-				this.onDragOver(this._createMouseEvent("DragOver", e));
-			}
-			/*
-			* Webkit will not send drop events if this event is not prevented, as spec in HTML5.
-			* Firefox and IE do not follow this spec for contentEditable. Note that preventing this 
-			* event will result is loss of functionality (insertion mark, etc).
-			*/
-			if (isWebkit || prevent) {
-				if (prevent) { e.dataTransfer.dropEffect = "none"; }
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleDragLeave: function (e) {
-			if (!e) { e = window.event; }
-			this._dropTarget = false;
-			if (this.isListening("DragLeave")) {
-				this.onDragLeave(this._createMouseEvent("DragLeave", e));
-			}
-		},
-		_handleDrop: function (e) {
-			if (!e) { e = window.event; }
-			this._dropTarget = false;
-			if (this.isListening("Drop")) {
-				this.onDrop(this._createMouseEvent("Drop", e));
-			}
-			/*
-			* This event must be prevented otherwise the user agent will modify
-			* the DOM. Note that preventing the event on some user agents (i.e. IE)
-			* indicates that the operation is cancelled. This causes the dropEffect to 
-			* be set to none  in the dragend event causing the implementor to not execute
-			* the code responsible by the move effect.
-			*/
-			if (e.preventDefault) { e.preventDefault(); }
-			return false;
-		},
-		_handleDocFocus: function (e) {
-			if (!e) { e = window.event; }
-			this._clientDiv.focus();
-		},
-		_handleFocus: function (e) {
-			if (!e) { e = window.event; }
-			this._hasFocus = true;
-			/*
-			* Feature in IE.  The selection is not restored when the
-			* view gets focus and the caret is always placed at the
-			* beginning of the document.  The fix is to update the DOM
-			* selection during the focus event.
-			*/
-			if (isIE) {
-				this._updateDOMSelection();
-			}
-			if (isFirefox || isIE) {
-				if (this._selDiv1) {
-					var color = this._hightlightRGB;
-					this._selDiv1.style.background = color;
-					this._selDiv2.style.background = color;
-					this._selDiv3.style.background = color;
-				}
-			}
-			if (!this._ignoreFocus) {
-				this.onFocus({type: "Focus"});
-			}
-		},
-		_handleKeyDown: function (e) {
-			if (!e) { e = window.event; }
-			if (isPad) {
-				if (e.keyCode === 8) {
-					this._doBackspace({});
-					e.preventDefault();
-				}
-				return;
-			}
-			switch (e.keyCode) {
-				case 16: /* Shift */
-				case 17: /* Control */
-				case 18: /* Alt */
-				case 91: /* Command */
-					break;
-				default:
-					this._setLinksVisible(false);
-			}
-			if (e.keyCode === 229) {
-				if (this._readonly) {
-					if (e.preventDefault) { e.preventDefault(); }
-					return false;
-				}
-				var startIME = true;
-				
-				/*
-				* Bug in Safari. Some Control+key combinations send key events
-				* with keyCode equals to 229. This is unexpected and causes the
-				* view to start an IME composition. The fix is to ignore these
-				* events.
-				*/
-				if (isSafari && isMac) {
-					if (e.ctrlKey) {
-						startIME = false;
-					}
-				}
-				if (startIME) {
-					this._startIME();
-				}
-			} else {
-				this._commitIME();
-			}
-			/*
-			* Feature in Firefox. When a key is held down the browser sends 
-			* right number of keypress events but only one keydown. This is
-			* unexpected and causes the view to only execute an action
-			* just one time. The fix is to ignore the keydown event and 
-			* execute the actions from the keypress handler.
-			* Note: This only happens on the Mac and Linux (Firefox 3.6).
-			*
-			* Feature in Opera.  Opera sends keypress events even for non-printable
-			* keys.  The fix is to handle actions in keypress instead of keydown.
-			*/
-			if (((isMac || isLinux) && isFirefox < 4) || isOpera) {
-				this._keyDownEvent = e;
-				return true;
-			}
-			
-			if (this._doAction(e)) {
-				if (e.preventDefault) {
-					e.preventDefault(); 
-				} else {
-					e.cancelBubble = true;
-					e.returnValue = false;
-					e.keyCode = 0;
-				}
-				return false;
-			}
-		},
-		_handleKeyPress: function (e) {
-			if (!e) { e = window.event; }
-			/*
-			* Feature in Embedded WebKit.  Embedded WekKit on Mac runs in compatibility mode and
-			* generates key press events for these Unicode values (Function keys).  This does not
-			* happen in Safari or Chrome.  The fix is to ignore these key events.
-			*/
-			if (isMac && isWebkit) {
-				if ((0xF700 <= e.keyCode && e.keyCode <= 0xF7FF) || e.keyCode === 13 || e.keyCode === 8) {
-					if (e.preventDefault) { e.preventDefault(); }
-					return false;
-				}
-			}
-			if (((isMac || isLinux) && isFirefox < 4) || isOpera) {
-				if (this._doAction(this._keyDownEvent)) {
-					if (e.preventDefault) { e.preventDefault(); }
-					return false;
-				}
-			}
-			var ctrlKey = isMac ? e.metaKey : e.ctrlKey;
-			if (e.charCode !== undefined) {
-				if (ctrlKey) {
-					switch (e.charCode) {
-						/*
-						* In Firefox and Safari if ctrl+v, ctrl+c ctrl+x is canceled
-						* the clipboard events are not sent. The fix to allow
-						* the browser to handles these key events.
-						*/
-						case 99://c
-						case 118://v
-						case 120://x
-							return true;
-					}
-				}
-			}
-			var ignore = false;
-			if (isMac) {
-				if (e.ctrlKey || e.metaKey) { ignore = true; }
-			} else {
-				if (isFirefox) {
-					//Firefox clears the state mask when ALT GR generates input
-					if (e.ctrlKey || e.altKey) { ignore = true; }
-				} else {
-					//IE and Chrome only send ALT GR when input is generated
-					if (e.ctrlKey ^ e.altKey) { ignore = true; }
-				}
-			}
-			if (!ignore) {
-				var key = isOpera ? e.which : (e.charCode !== undefined ? e.charCode : e.keyCode);
-				if (key > 31) {
-					this._doContent(String.fromCharCode (key));
-					if (e.preventDefault) { e.preventDefault(); }
-					return false;
-				}
-			}
-		},
-		_handleKeyUp: function (e) {
-			if (!e) { e = window.event; }
-			var ctrlKey = isMac ? e.metaKey : e.ctrlKey;
-			if (!ctrlKey) {
-				this._setLinksVisible(false);
-			}
-			// don't commit for space (it happens during JP composition)  
-			if (e.keyCode === 13) {
-				this._commitIME();
-			}
-		},
-		_handleLinkClick: function (e) {
-			if (!e) { e = window.event; }
-			var ctrlKey = isMac ? e.metaKey : e.ctrlKey;
-			if (!ctrlKey) {
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleLoad: function (e) {
-			var state = this._getVisible();
-			if (state === "visible" || (state === "hidden" && isWebkit)) {
-				this._createView();
-			}
-		},
-		_handleMouse: function (e) {
-			var result = true;
-			var target = this._frameWindow;
-			if (isIE || (isFirefox && !this._overlayDiv)) { target = this._clientDiv; }
-			if (this._overlayDiv) {
-				if (this._hasFocus) {
-					this._ignoreFocus = true;
-				}
-				var self = this;
-				setTimeout(function () {
-					self.focus();
-					self._ignoreFocus = false;
-				}, 0);
-			}
-			if (this._clickCount === 1) {
-				result = this._setSelectionTo(e.clientX, e.clientY, e.shiftKey, !isOpera && this.isListening("DragStart"));
-				if (result) { this._setGrab(target); }
-			} else {
-				/*
-				* Feature in IE8 and older, the sequence of events in the IE8 event model
-				* for a doule-click is:
-				*
-				*	down
-				*	up
-				*	up
-				*	dblclick
-				*
-				* Given that the mouse down/up events are not balanced, it is not possible to
-				* grab on mouse down and ungrab on mouse up.  The fix is to grab on the first
-				* mouse down and ungrab on mouse move when the button 1 is not set.
-				*/
-				if (isW3CEvents) { this._setGrab(target); }
-				
-				this._doubleClickSelection = null;
-				this._setSelectionTo(e.clientX, e.clientY, e.shiftKey);
-				this._doubleClickSelection = this._getSelection();
-			}
-			return result;
-		},
-		_handleMouseDown: function (e) {
-			if (!e) { e = window.event; }
-			if (this.isListening("MouseDown")) {
-				this.onMouseDown(this._createMouseEvent("MouseDown", e));
-			}
-			if (this._linksVisible) {
-				var target = e.target || e.srcElement;
-				if (target.tagName !== "A") {
-					this._setLinksVisible(false);
-				} else {
-					return;
-				}
-			}
-			this._commitIME();
-
-			var button = e.which; // 1 - left, 2 - middle, 3 - right
-			if (!button) { 
-				// if IE 8 or older
-				if (e.button === 4) { button = 2; }
-				if (e.button === 2) { button = 3; }
-				if (e.button === 1) { button = 1; }
-			}
-
-			// For middle click we always need getTime(). See _getClipboardText().
-			var time = button !== 2 && e.timeStamp ? e.timeStamp : new Date().getTime();
-			var timeDiff = time - this._lastMouseTime;
-			var deltaX = Math.abs(this._lastMouseX - e.clientX);
-			var deltaY = Math.abs(this._lastMouseY - e.clientY);
-			var sameButton = this._lastMouseButton === button;
-			this._lastMouseX = e.clientX;
-			this._lastMouseY = e.clientY;
-			this._lastMouseTime = time;
-			this._lastMouseButton = button;
-
-			if (button === 1) {
-				this._isMouseDown = true;
-				if (sameButton && timeDiff <= this._clickTime && deltaX <= this._clickDist && deltaY <= this._clickDist) {
-					this._clickCount++;
-				} else {
-					this._clickCount = 1;
-				}
-				if (this._handleMouse(e) && (isOpera || isChrome || (isFirefox && !this._overlayDiv))) {
-					if (!this._hasFocus) {
-						this.focus();
-					}
-					e.preventDefault();
-				}
-			}
-		},
-		_handleMouseOver: function (e) {
-			if (!e) { e = window.event; }
-			if (this.isListening("MouseOver")) {
-				this.onMouseOver(this._createMouseEvent("MouseOver", e));
-			}
-		},
-		_handleMouseOut: function (e) {
-			if (!e) { e = window.event; }
-			if (this.isListening("MouseOut")) {
-				this.onMouseOut(this._createMouseEvent("MouseOut", e));
-			}
-		},
-		_handleMouseMove: function (e) {
-			if (!e) { e = window.event; }
-			if (this.isListening("MouseMove")) {
-				var topNode = this._overlayDiv || this._clientDiv;
-				var temp = e.target ? e.target : e.srcElement;
-				while (temp) {
-					if (topNode === temp) {
-						this.onMouseMove(this._createMouseEvent("MouseMove", e));
-						break;
-					}
-					temp = temp.parentNode;
-				}
-			}
-			if (this._dropTarget) {
-				return;
-			}
-			/*
-			* Bug in IE9. IE sends one mouse event when the user changes the text by
-			* pasting or undo.  These operations usually happen with the Ctrl key
-			* down which causes the view to enter link mode.  Link mode does not end
-			* because there are no further events.  The fix is to only enter link
-			* mode when the coordinates of the mouse move event have changed.
-			*/
-			var changed = this._linksVisible || this._lastMouseMoveX !== e.clientX || this._lastMouseMoveY !== e.clientY;
-			this._lastMouseMoveX = e.clientX;
-			this._lastMouseMoveY = e.clientY;
-			this._setLinksVisible(changed && !this._isMouseDown && (isMac ? e.metaKey : e.ctrlKey));
-
-			/*
-			* Feature in IE8 and older, the sequence of events in the IE8 event model
-			* for a doule-click is:
-			*
-			*	down
-			*	up
-			*	up
-			*	dblclick
-			*
-			* Given that the mouse down/up events are not balanced, it is not possible to
-			* grab on mouse down and ungrab on mouse up.  The fix is to grab on the first
-			* mouse down and ungrab on mouse move when the button 1 is not set.
-			*
-			* In order to detect double-click and drag gestures, it is necessary to send
-			* a mouse down event from mouse move when the button is still down and isMouseDown
-			* flag is not set.
-			*/
-			if (!isW3CEvents) {
-				if (e.button === 0) {
-					this._setGrab(null);
-					return true;
-				}
-				if (!this._isMouseDown && e.button === 1 && (this._clickCount & 1) !== 0) {
-					this._clickCount = 2;
-					return this._handleMouse(e, this._clickCount);
-				}
-			}
-			if (!this._isMouseDown || this._dragOffset !== -1) {
-				return;
-			}
-			
-			var x = e.clientX;
-			var y = e.clientY;
-			if (isChrome) {
-				if (e.currentTarget !== this._frameWindow) {
-					var rect = this._frame.getBoundingClientRect();
-					x -= rect.left;
-					y -= rect.top;
-				}
-			}
-			var viewPad = this._getViewPadding();
-			var viewRect = this._viewDiv.getBoundingClientRect();
-			var width = this._getClientWidth (), height = this._getClientHeight();
-			var leftEdge = viewRect.left + viewPad.left;
-			var topEdge = viewRect.top + viewPad.top;
-			var rightEdge = viewRect.left + viewPad.left + width;
-			var bottomEdge = viewRect.top + viewPad.top + height;
-			var model = this._model;
-			var caretLine = model.getLineAtOffset(this._getSelection().getCaret());
-			if (y < topEdge && caretLine !== 0) {
-				this._doAutoScroll("up", x, y - topEdge);
-			} else if (y > bottomEdge && caretLine !== model.getLineCount() - 1) {
-				this._doAutoScroll("down", x, y - bottomEdge);
-			} else if (x < leftEdge) {
-				this._doAutoScroll("left", x - leftEdge, y);
-			} else if (x > rightEdge) {
-				this._doAutoScroll("right", x - rightEdge, y);
-			} else {
-				this._endAutoScroll();
-				this._setSelectionTo(x, y, true);
-				/*
-				* Feature in IE. IE does redraw the selection background right
-				* away after the selection changes because of mouse move events.
-				* The fix is to call getBoundingClientRect() on the
-				* body element to force the selection to be redraw. Some how
-				* calling this method forces a redraw.
-				*/
-				if (isIE) {
-					var body = this._frameDocument.body;
-					body.getBoundingClientRect();
-				}
-			}
-		},
-		_createMouseEvent: function(type, e) {
-			var scroll = this._getScroll();
-			var viewRect = this._viewDiv.getBoundingClientRect();
-			var viewPad = this._getViewPadding();
-			var x = e.clientX + scroll.x - viewRect.left - viewPad.left;
-			var y = e.clientY + scroll.y - viewRect.top;
-			return {
-				type: type,
-				event: e,
-				x: x,
-				y: y
-			};
-		},
-		_handleMouseUp: function (e) {
-			if (!e) { e = window.event; }
-			if (this.isListening("MouseUp")) {
-				this.onMouseUp(this._createMouseEvent("MouseUp", e));
-			}
-			if (this._linksVisible) {
-				return;
-			}
-			var left = e.which ? e.button === 0 : e.button === 1;
-			if (left) {
-				if (this._dragOffset !== -1) {
-					var selection = this._getSelection();
-					selection.extend(this._dragOffset);
-					selection.collapse();
-					this._setSelection(selection, true, true);
-					this._dragOffset = -1;
-				}
-				this._isMouseDown = false;
-				this._endAutoScroll();
-				
-				/*
-				* Feature in IE8 and older, the sequence of events in the IE8 event model
-				* for a doule-click is:
-				*
-				*	down
-				*	up
-				*	up
-				*	dblclick
-				*
-				* Given that the mouse down/up events are not balanced, it is not possible to
-				* grab on mouse down and ungrab on mouse up.  The fix is to grab on the first
-				* mouse down and ungrab on mouse move when the button 1 is not set.
-				*/
-				if (isW3CEvents) { this._setGrab(null); }
-
-				/*
-				* Note that there cases when Firefox sets the DOM selection in mouse up.
-				* This happens for example after a cancelled drag operation.
-				*
-				* Note that on Chrome and IE, the caret stops blicking if mouse up is
-				* prevented.
-				*/
-				if (isFirefox) {
-					e.preventDefault();
-				}
-			}
-		},
-		_handleMouseWheel: function (e) {
-			if (!e) { e = window.event; }
-			var lineHeight = this._getLineHeight();
-			var pixelX = 0, pixelY = 0;
-			// Note: On the Mac the correct behaviour is to scroll by pixel.
-			if (isFirefox) {
-				var pixel;
-				if (isMac) {
-					pixel = e.detail * 3;
-				} else {
-					var limit = 256;
-					pixel = Math.max(-limit, Math.min(limit, e.detail)) * lineHeight;
-				}
-				if (e.axis === e.HORIZONTAL_AXIS) {
-					pixelX = pixel;
-				} else {
-					pixelY = pixel;
-				}
-			} else {
-				//Webkit
-				if (isMac) {
-					/*
-					* In Safari, the wheel delta is a multiple of 120. In order to
-					* convert delta to pixel values, it is necessary to divide delta
-					* by 40.
-					*
-					* In Chrome and Safari 5, the wheel delta depends on the type of the
-					* mouse. In general, it is the pixel value for Mac mice and track pads,
-					* but it is a multiple of 120 for other mice. There is no presise
-					* way to determine if it is pixel value or a multiple of 120.
-					* 
-					* Note that the current approach does not calculate the correct
-					* pixel value for Mac mice when the delta is a multiple of 120.
-					*/
-					var denominatorX = 40, denominatorY = 40;
-					if (e.wheelDeltaX % 120 !== 0) { denominatorX = 1; }
-					if (e.wheelDeltaY % 120 !== 0) { denominatorY = 1; }
-					pixelX = -e.wheelDeltaX / denominatorX;
-					if (-1 < pixelX && pixelX < 0) { pixelX = -1; }
-					if (0 < pixelX && pixelX < 1) { pixelX = 1; }
-					pixelY = -e.wheelDeltaY / denominatorY;
-					if (-1 < pixelY && pixelY < 0) { pixelY = -1; }
-					if (0 < pixelY && pixelY < 1) { pixelY = 1; }
-				} else {
-					pixelX = -e.wheelDeltaX;
-					var linesToScroll = 8;
-					pixelY = (-e.wheelDeltaY / 120 * linesToScroll) * lineHeight;
-				}
-			}
-			/* 
-			* Feature in Safari. If the event target is removed from the DOM 
-			* safari stops smooth scrolling. The fix is keep the element target
-			* in the DOM and remove it on a later time. 
-			*
-			* Note: Using a timer is not a solution, because the timeout needs to
-			* be at least as long as the gesture (which is too long).
-			*/
-			if (isSafari) {
-				var lineDiv = e.target;
-				while (lineDiv && lineDiv.lineIndex === undefined) {
-					lineDiv = lineDiv.parentNode;
-				}
-				this._mouseWheelLine = lineDiv;
-			}
-			var oldScroll = this._getScroll();
-			this._scrollView(pixelX, pixelY);
-			var newScroll = this._getScroll();
-			if (isSafari) { this._mouseWheelLine = null; }
-			if (oldScroll.x !== newScroll.x || oldScroll.y !== newScroll.y) {
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handlePaste: function (e) {
-			if (this._ignorePaste) { return; }
-			if (!e) { e = window.event; }
-			if (this._doPaste(e)) {
-				if (isIE) {
-					/*
-					 * Bug in IE,  
-					 */
-					var self = this;
-					this._ignoreFocus = true;
-					setTimeout(function() {
-						self._updateDOMSelection();
-						this._ignoreFocus = false;
-					}, 0);
-				}
-				if (e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleResize: function (e) {
-			if (!e) { e = window.event; }
-			var element = this._frameDocument.documentElement;
-			var newWidth = element.clientWidth;
-			var newHeight = element.clientHeight;
-			if (this._frameWidth !== newWidth || this._frameHeight !== newHeight) {
-				this._frameWidth = newWidth;
-				this._frameHeight = newHeight;
-				/*
-				* Feature in IE7. For some reason, sometimes Internet Explorer 7 
-				* returns incorrect values for element.getBoundingClientRect() when 
-				* inside a resize handler. The fix is to queue the work.
-				*/
-				if (isIE < 9) {
-					this._queueUpdatePage();
-				} else {
-					this._updatePage();
-				}
-			}
-		},
-		_handleRulerEvent: function (e) {
-			if (!e) { e = window.event; }
-			var target = e.target ? e.target : e.srcElement;
-			var lineIndex = target.lineIndex;
-			var element = target;
-			while (element && !element._ruler) {
-				if (lineIndex === undefined && element.lineIndex !== undefined) {
-					lineIndex = element.lineIndex;
-				}
-				element = element.parentNode;
-			}
-			var ruler = element ? element._ruler : null;
-			if (lineIndex === undefined && ruler && ruler.getOverview() === "document") {
-				var buttonHeight = isPad ? 0 : 17;
-				var clientHeight = this._getClientHeight ();
-				var lineCount = this._model.getLineCount ();
-				var viewPad = this._getViewPadding();
-				var trackHeight = clientHeight + viewPad.top + viewPad.bottom - 2 * buttonHeight;
-				lineIndex = Math.floor((e.clientY - buttonHeight) * lineCount / trackHeight);
-				if (!(0 <= lineIndex && lineIndex < lineCount)) {
-					lineIndex = undefined;
-				}
-			}
-			if (ruler) {
-				switch (e.type) {
-					case "click":
-						if (ruler.onClick) { ruler.onClick(lineIndex, e); }
-						break;
-					case "dblclick": 
-						if (ruler.onDblClick) { ruler.onDblClick(lineIndex, e); }
-						break;
-					case "mousemove": 
-						if (ruler.onMouseMove) { ruler.onMouseMove(lineIndex, e); }
-						break;
-					case "mouseover": 
-						if (ruler.onMouseOver) { ruler.onMouseOver(lineIndex, e); }
-						break;
-					case "mouseout": 
-						if (ruler.onMouseOut) { ruler.onMouseOut(lineIndex, e); }
-						break;
-				}
-			}
-		},
-		_handleScroll: function () {
-			var scroll = this._getScroll();
-			var oldX = this._hScroll;
-			var oldY = this._vScroll;
-			if (oldX !== scroll.x || oldY !== scroll.y) {
-				this._hScroll = scroll.x;
-				this._vScroll = scroll.y;
-				this._commitIME();
-				this._updatePage(oldY === scroll.y);
-				var e = {
-					type: "Scroll",
-					oldValue: {x: oldX, y: oldY},
-					newValue: scroll
-				};
-				this.onScroll(e);
-			}
-		},
-		_handleSelectStart: function (e) {
-			if (!e) { e = window.event; }
-			if (this._ignoreSelect) {
-				if (e && e.preventDefault) { e.preventDefault(); }
-				return false;
-			}
-		},
-		_handleUnload: function (e) {
-			if (!e) { e = window.event; }
-			this._destroyView();
-		},
-		_handleInput: function (e) {
-			var textArea = this._textArea;
-			this._doContent(textArea.value);
-			textArea.selectionStart = textArea.selectionEnd = 0;
-			textArea.value = "";
-			e.preventDefault();
-		},
-		_handleTextInput: function (e) {
-			this._doContent(e.data);
-			e.preventDefault();
-		},
-		_touchConvert: function (touch) {
-			var rect = this._frame.getBoundingClientRect();
-			var body = this._parentDocument.body;
-			return {left: touch.clientX - rect.left - body.scrollLeft, top: touch.clientY - rect.top - body.scrollTop};
-		},
-		_handleTextAreaClick: function (e) {
-			var pt = this._touchConvert(e);	
-			this._clickCount = 1;
-			this._ignoreDOMSelection = false;
-			this._setSelectionTo(pt.left, pt.top, false);
-			var textArea = this._textArea;
-			textArea.focus();
-		},
-		_handleTouchStart: function (e) {
-			var touches = e.touches, touch, pt, sel;
-			this._touchMoved = false;
-			this._touchStartScroll = undefined;
-			if (touches.length === 1) {
-				touch = touches[0];
-				var pageX = touch.pageX;
-				var pageY = touch.pageY;
-				this._touchStartX = pageX;
-				this._touchStartY = pageY;
-				this._touchStartTime = e.timeStamp;
-				this._touchStartScroll = this._getScroll();
-				sel = this._getSelection();
-				pt = this._touchConvert(touches[0]);
-				this._touchGesture = "none";
-				if (!sel.isEmpty()) {
-					if (this._hitOffset(sel.end, pt.left, pt.top)) {
-						this._touchGesture = "extendEnd";
-					} else if (this._hitOffset(sel.start, pt.left, pt.top)) {
-						this._touchGesture = "extendStart";
-					}
-				}
-				if (this._touchGesture === "none") {
-					var textArea = this._textArea;
-					textArea.value = "";
-					textArea.style.left = "-1000px";
-					textArea.style.top = "-1000px";
-					textArea.style.width = "3000px";
-					textArea.style.height = "3000px";
-				}
-			} else if (touches.length === 2) {
-				this._touchGesture = "select";
-				if (this._touchTimeout) {
-					clearTimeout(this._touchTimeout);
-					this._touchTimeout = null;
-				}
-				pt = this._touchConvert(touches[0]);
-				var offset1 = this._getXToOffset(this._getYToLine(pt.top), pt.left);
-				pt = this._touchConvert(touches[1]);
-				var offset2 = this._getXToOffset(this._getYToLine(pt.top), pt.left);
-				sel = this._getSelection();
-				sel.setCaret(offset1);
-				sel.extend(offset2);
-				this._setSelection(sel, true, true);
-			}
-			//Cannot prevent to show magnifier
-//			e.preventDefault();
-		},
-		_handleTouchMove: function (e) {
-			this._touchMoved = true;
-			var touches = e.touches, pt, sel;
-			if (touches.length === 1) {
-				var touch = touches[0];
-				var pageX = touch.pageX;
-				var pageY = touch.pageY;
-				var deltaX = this._touchStartX - pageX;
-				var deltaY = this._touchStartY - pageY;
-				pt = this._touchConvert(touch);
-				sel = this._getSelection();
-				if (this._touchGesture === "none") {
-					if ((e.timeStamp - this._touchStartTime) < 200 && (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5)) {
-						this._touchGesture = "scroll";
-					} else {
-						this._touchGesture = "caret";
-					}
-				}
-				if (this._touchGesture === "select") {
-					if (this._hitOffset(sel.end, pt.left, pt.top)) {
-						this._touchGesture = "extendEnd";
-					} else if (this._hitOffset(sel.start, pt.left, pt.top)) {
-						this._touchGesture = "extendStart";
-					} else {
-						this._touchGesture = "caret";
-					}
-				}
-				switch (this._touchGesture) {
-					case "scroll":
-						this._touchStartX = pageX;
-						this._touchStartY = pageY;
-						this._scrollView(deltaX, deltaY);
-						break;
-					case "extendStart":
-					case "extendEnd":
-						this._clickCount = 1;
-						var lineIndex = this._getYToLine(pt.top);
-						var offset = this._getXToOffset(lineIndex, pt.left);
-						sel.setCaret(this._touchGesture === "extendStart" ? sel.end : sel.start);
-						sel.extend(offset);
-						if (offset >= sel.end && this._touchGesture === "extendStart") {
-							this._touchGesture = "extendEnd";
-						}
-						if (offset <= sel.start && this._touchGesture === "extendEnd") {
-							this._touchGesture = "extendStart";
-						}
-						this._setSelection(sel, true, true);
-						break;
-					case "caret":
-						this._setSelectionTo(pt.left, pt.top, false);
-						break;
-				}
-			} else if (touches.length === 2) {
-				pt = this._touchConvert(touches[0]);
-				var offset1 = this._getXToOffset(this._getYToLine(pt.top), pt.left);
-				pt = this._touchConvert(touches[1]);
-				var offset2 = this._getXToOffset(this._getYToLine(pt.top), pt.left);
-				sel = this._getSelection();
-				sel.setCaret(offset1);
-				sel.extend(offset2);
-				this._setSelection(sel, true, true);
-			}
-			e.preventDefault();
-		},
-		_handleTouchEnd: function (e) {
-			var self = this;
-			if (!this._touchMoved) {
-				if (e.touches.length === 0 && e.changedTouches.length === 1) {
-					var touch = e.changedTouches[0];
-					var pt = this._touchConvert(touch);
-					var textArea = this._textArea;
-					textArea.value = "";
-					textArea.style.left = "-1000px";
-					textArea.style.top = "-1000px";
-					textArea.style.width = "3000px";
-					textArea.style.height = "3000px";
-					setTimeout(function() {
-						self._clickCount = 1;
-						self._ignoreDOMSelection = false;
-						self._setSelectionTo(pt.left, pt.top, false);
-					}, 300);
-				}
-			}
-			if (e.touches.length === 0) {
-				setTimeout(function() {
-					var selection = self._getSelection();
-					var text = self._model.getText(selection.start, selection.end);
-					var textArea = self._textArea;
-					textArea.value = text;
-					textArea.selectionStart = 0;
-					textArea.selectionEnd = text.length;
-					if (!selection.isEmpty()) {
-						var touchRect = self._touchDiv.getBoundingClientRect();
-						var bounds = self._getOffsetBounds(selection.start);
-						textArea.style.left = (touchRect.width / 2) + "px";
-						textArea.style.top = ((bounds.top > 40 ? bounds.top - 30 : bounds.top + 30)) + "px";
-					}
-				}, 0);
-			}
-//				e.preventDefault();
-		},
-
-		/************************************ Actions ******************************************/
-		_doAction: function (e) {
-			var keyBindings = this._keyBindings;
-			for (var i = 0; i < keyBindings.length; i++) {
-				var kb = keyBindings[i];
-				if (kb.keyBinding.match(e)) {
-					if (kb.name) {
-						var actions = this._actions;
-						for (var j = 0; j < actions.length; j++) {
-							var a = actions[j];
-							if (a.name === kb.name) {
-								if (a.userHandler) {
-									if (!a.userHandler()) {
-										if (a.defaultHandler) {
-											a.defaultHandler();
-										} else {
-											return false;
-										}
-									}
-								} else if (a.defaultHandler) {
-									a.defaultHandler();
-								}
-								break;
-							}
-						}
-					}
-					return true;
-				}
-			}
-			return false;
-		},
-		_doBackspace: function (args) {
-			var selection = this._getSelection();
-			if (selection.isEmpty()) {
-				var model = this._model;
-				var caret = selection.getCaret();
-				var lineIndex = model.getLineAtOffset(caret);
-				var lineStart = model.getLineStart(lineIndex);
-				if (caret === lineStart) {
-					if (lineIndex > 0) {
-						selection.extend(model.getLineEnd(lineIndex - 1));
-					}
-				} else {
-					var removeTab = false;
-					if (this._expandTab && args.unit === "character" && (caret - lineStart) % this._tabSize === 0) {
-						var lineText = model.getText(lineStart, caret);
-						removeTab = !/[^ ]/.test(lineText); // Only spaces between line start and caret.
-					}
-					if (removeTab) {
-						selection.extend(caret - this._tabSize);
-					} else {
-						selection.extend(this._getOffset(caret, args.unit, -1));
-					}
-				}
-			}
-			this._modifyContent({text: "", start: selection.start, end: selection.end}, true);
-			return true;
-		},
-		_doContent: function (text) {
-			var selection = this._getSelection();
-			this._modifyContent({text: text, start: selection.start, end: selection.end, _ignoreDOMSelection: true}, true);
-		},
-		_doCopy: function (e) {
-			var selection = this._getSelection();
-			if (!selection.isEmpty()) {
-				var text = this._getBaseText(selection.start, selection.end);
-				return this._setClipboardText(text, e);
-			}
-			return true;
-		},
-		_doCursorNext: function (args) {
-			if (!args.select) {
-				if (this._clearSelection("next")) { return true; }
-			}
-			var model = this._model;
-			var selection = this._getSelection();
-			var caret = selection.getCaret();
-			var lineIndex = model.getLineAtOffset(caret);
-			if (caret === model.getLineEnd(lineIndex)) {
-				if (lineIndex + 1 < model.getLineCount()) {
-					selection.extend(model.getLineStart(lineIndex + 1));
-				}
-			} else {
-				selection.extend(this._getOffset(caret, args.unit, 1));
-			}
-			if (!args.select) { selection.collapse(); }
-			this._setSelection(selection, true);
-			return true;
-		},
-		_doCursorPrevious: function (args) {
-			if (!args.select) {
-				if (this._clearSelection("previous")) { return true; }
-			}
-			var model = this._model;
-			var selection = this._getSelection();
-			var caret = selection.getCaret();
-			var lineIndex = model.getLineAtOffset(caret);
-			if (caret === model.getLineStart(lineIndex)) {
-				if (lineIndex > 0) {
-					selection.extend(model.getLineEnd(lineIndex - 1));
-				}
-			} else {
-				selection.extend(this._getOffset(caret, args.unit, -1));
-			}
-			if (!args.select) { selection.collapse(); }
-			this._setSelection(selection, true);
-			return true;
-		},
-		_doCut: function (e) {
-			var selection = this._getSelection();
-			if (!selection.isEmpty()) {
-				var text = this._getBaseText(selection.start, selection.end);
-				this._doContent("");
-				return this._setClipboardText(text, e);
-			}
-			return true;
-		},
-		_doDelete: function (args) {
-			var selection = this._getSelection();
-			if (selection.isEmpty()) {
-				var model = this._model;
-				var caret = selection.getCaret();
-				var lineIndex = model.getLineAtOffset(caret);
-				if (caret === model.getLineEnd (lineIndex)) {
-					if (lineIndex + 1 < model.getLineCount()) {
-						selection.extend(model.getLineStart(lineIndex + 1));
-					}
-				} else {
-					selection.extend(this._getOffset(caret, args.unit, 1));
-				}
-			}
-			this._modifyContent({text: "", start: selection.start, end: selection.end}, true);
-			return true;
-		},
-		_doEnd: function (args) {
-			var selection = this._getSelection();
-			var model = this._model;
-			if (args.ctrl) {
-				selection.extend(model.getCharCount());
-			} else {
-				var lineIndex = model.getLineAtOffset(selection.getCaret());
-				selection.extend(model.getLineEnd(lineIndex)); 
-			}
-			if (!args.select) { selection.collapse(); }
-			this._setSelection(selection, true);
-			return true;
-		},
-		_doEnter: function (args) {
-			var model = this._model;
-			var selection = this._getSelection();
-			this._doContent(model.getLineDelimiter()); 
-			if (args && args.noCursor) {
-				selection.end = selection.start;
-				this._setSelection(selection);
-			}
-			return true;
-		},
-		_doHome: function (args) {
-			var selection = this._getSelection();
-			var model = this._model;
-			if (args.ctrl) {
-				selection.extend(0);
-			} else {
-				var lineIndex = model.getLineAtOffset(selection.getCaret());
-				selection.extend(model.getLineStart(lineIndex)); 
-			}
-			if (!args.select) { selection.collapse(); }
-			this._setSelection(selection, true);
-			return true;
-		},
-		_doLineDown: function (args) {
-			var model = this._model;
-			var selection = this._getSelection();
-			var caret = selection.getCaret();
-			var lineIndex = model.getLineAtOffset(caret);
-			if (lineIndex + 1 < model.getLineCount()) {
-				var scrollX = this._getScroll().x;
-				var x = this._columnX;
-				if (x === -1 || args.wholeLine || (args.select && isIE)) {
-					var offset = args.wholeLine ? model.getLineEnd(lineIndex + 1) : caret;
-					x = this._getOffsetToX(offset) + scrollX;
-				}
-				selection.extend(this._getXToOffset(lineIndex + 1, x - scrollX));
-				if (!args.select) { selection.collapse(); }
-				this._setSelection(selection, true, true);
-				this._columnX = x;
-			}
-			return true;
-		},
-		_doLineUp: function (args) {
-			var model = this._model;
-			var selection = this._getSelection();
-			var caret = selection.getCaret();
-			var lineIndex = model.getLineAtOffset(caret);
-			if (lineIndex > 0) {
-				var scrollX = this._getScroll().x;
-				var x = this._columnX;
-				if (x === -1 || args.wholeLine || (args.select && isIE)) {
-					var offset = args.wholeLine ? model.getLineStart(lineIndex - 1) : caret;
-					x = this._getOffsetToX(offset) + scrollX;
-				}
-				selection.extend(this._getXToOffset(lineIndex - 1, x - scrollX));
-				if (!args.select) { selection.collapse(); }
-				this._setSelection(selection, true, true);
-				this._columnX = x;
-			}
-			return true;
-		},
-		_doPageDown: function (args) {
-			var model = this._model;
-			var selection = this._getSelection();
-			var caret = selection.getCaret();
-			var caretLine = model.getLineAtOffset(caret);
-			var lineCount = model.getLineCount();
-			if (caretLine < lineCount - 1) {
-				var scroll = this._getScroll();
-				var clientHeight = this._getClientHeight();
-				var lineHeight = this._getLineHeight();
-				var lines = Math.floor(clientHeight / lineHeight);
-				var scrollLines = Math.min(lineCount - caretLine - 1, lines);
-				scrollLines = Math.max(1, scrollLines);
-				var x = this._columnX;
-				if (x === -1 || (args.select && isIE)) {
-					x = this._getOffsetToX(caret) + scroll.x;
-				}
-				selection.extend(this._getXToOffset(caretLine + scrollLines, x - scroll.x));
-				if (!args.select) { selection.collapse(); }
-				var verticalMaximum = lineCount * lineHeight;
-				var scrollOffset = scroll.y + scrollLines * lineHeight;
-				if (scrollOffset + clientHeight > verticalMaximum) {
-					scrollOffset = verticalMaximum - clientHeight;
-				}
-				this._setSelection(selection, true, true, scrollOffset - scroll.y);
-				this._columnX = x;
-			}
-			return true;
-		},
-		_doPageUp: function (args) {
-			var model = this._model;
-			var selection = this._getSelection();
-			var caret = selection.getCaret();
-			var caretLine = model.getLineAtOffset(caret);
-			if (caretLine > 0) {
-				var scroll = this._getScroll();
-				var clientHeight = this._getClientHeight();
-				var lineHeight = this._getLineHeight();
-				var lines = Math.floor(clientHeight / lineHeight);
-				var scrollLines = Math.max(1, Math.min(caretLine, lines));
-				var x = this._columnX;
-				if (x === -1 || (args.select && isIE)) {
-					x = this._getOffsetToX(caret) + scroll.x;
-				}
-				selection.extend(this._getXToOffset(caretLine - scrollLines, x - scroll.x));
-				if (!args.select) { selection.collapse(); }
-				var scrollOffset = Math.max(0, scroll.y - scrollLines * lineHeight);
-				this._setSelection(selection, true, true, scrollOffset - scroll.y);
-				this._columnX = x;
-			}
-			return true;
-		},
-		_doPaste: function(e) {
-			var self = this;
-			var result = this._getClipboardText(e, function(text) {
-				if (text) {
-					if (isLinux && self._lastMouseButton === 2) {
-						var timeDiff = new Date().getTime() - self._lastMouseTime;
-						if (timeDiff <= self._clickTime) {
-							self._setSelectionTo(self._lastMouseX, self._lastMouseY);
-						}
-					}
-					self._doContent(text);
-				}
-			});
-			return result !== null;
-		},
-		_doScroll: function (args) {
-			var type = args.type;
-			var model = this._model;
-			var lineCount = model.getLineCount();
-			var clientHeight = this._getClientHeight();
-			var lineHeight = this._getLineHeight();
-			var verticalMaximum = lineCount * lineHeight;
-			var verticalScrollOffset = this._getScroll().y;
-			var pixel;
-			switch (type) {
-				case "textStart": pixel = 0; break;
-				case "textEnd": pixel = verticalMaximum - clientHeight; break;
-				case "pageDown": pixel = verticalScrollOffset + clientHeight; break;
-				case "pageUp": pixel = verticalScrollOffset - clientHeight; break;
-				case "centerLine":
-					var selection = this._getSelection();
-					var lineStart = model.getLineAtOffset(selection.start);
-					var lineEnd = model.getLineAtOffset(selection.end);
-					var selectionHeight = (lineEnd - lineStart + 1) * lineHeight;
-					pixel = (lineStart * lineHeight) - (clientHeight / 2) + (selectionHeight / 2);
-					break;
-			}
-			if (pixel !== undefined) {
-				pixel = Math.min(Math.max(0, pixel), verticalMaximum - clientHeight);
-				this._scrollView(0, pixel - verticalScrollOffset);
-			}
-		},
-		_doSelectAll: function (args) {
-			var model = this._model;
-			var selection = this._getSelection();
-			selection.setCaret(0);
-			selection.extend(model.getCharCount());
-			this._setSelection(selection, false);
-			return true;
-		},
-		_doTab: function (args) {
-			var text = "\t";
-			if (this._expandTab) {
-				var model = this._model;
-				var caret = this._getSelection().getCaret();
-				var lineIndex = model.getLineAtOffset(caret);
-				var lineStart = model.getLineStart(lineIndex);
-				var spaces = this._tabSize - ((caret - lineStart) % this._tabSize);
-				text = (new Array(spaces + 1)).join(" ");
-			}
-			this._doContent(text);
-			return true;
-		},
-		
-		/************************************ Internals ******************************************/
-		_applyStyle: function(style, node, reset) {
-			if (reset) {
-				var attrs = node.attributes;
-				for (var i= attrs.length; i-->0;) {
-					if (attrs[i].specified) {
-						node.removeAttributeNode(attrs[i]); 
-					}
-				}
-			}
-			if (!style) {
-				return;
-			}
-			if (style.styleClass) {
-				node.className = style.styleClass;
-			}
-			var properties = style.style;
-			if (properties) {
-				for (var s in properties) {
-					if (properties.hasOwnProperty(s)) {
-						node.style[s] = properties[s];
-					}
-				}
-			}
-			var attributes = style.attributes;
-			if (attributes) {
-				for (var a in attributes) {
-					if (attributes.hasOwnProperty(a)) {
-						node.setAttribute(a, attributes[a]);
-					}
-				}
-			}
-		},
-		_autoScroll: function () {
-			var selection = this._getSelection();
-			var line;
-			var x = this._autoScrollX;
-			if (this._autoScrollDir === "up" || this._autoScrollDir === "down") {
-				var scroll = this._autoScrollY / this._getLineHeight();
-				scroll = scroll < 0 ? Math.floor(scroll) : Math.ceil(scroll);
-				line = this._model.getLineAtOffset(selection.getCaret());
-				line = Math.max(0, Math.min(this._model.getLineCount() - 1, line + scroll));
-			} else if (this._autoScrollDir === "left" || this._autoScrollDir === "right") {
-				line = this._getYToLine(this._autoScrollY);
-				x += this._getOffsetToX(selection.getCaret());
-			}
-			selection.extend(this._getXToOffset(line, x));
-			this._setSelection(selection, true);
-		},
-		_autoScrollTimer: function () {
-			this._autoScroll();
-			var self = this;
-			this._autoScrollTimerID = setTimeout(function () {self._autoScrollTimer();}, this._AUTO_SCROLL_RATE);
-		},
-		_calculateLineHeight: function() {
-			var parent = this._clientDiv;
-			var document = this._frameDocument;
-			var c = " ";
-			var line = document.createElement("DIV");
-			line.style.position = "fixed";
-			line.style.left = "-1000px";
-			var span1 = document.createElement("SPAN");
-			span1.appendChild(document.createTextNode(c));
-			line.appendChild(span1);
-			var span2 = document.createElement("SPAN");
-			span2.style.fontStyle = "italic";
-			span2.appendChild(document.createTextNode(c));
-			line.appendChild(span2);
-			var span3 = document.createElement("SPAN");
-			span3.style.fontWeight = "bold";
-			span3.appendChild(document.createTextNode(c));
-			line.appendChild(span3);
-			var span4 = document.createElement("SPAN");
-			span4.style.fontWeight = "bold";
-			span4.style.fontStyle = "italic";
-			span4.appendChild(document.createTextNode(c));
-			line.appendChild(span4);
-			parent.appendChild(line);
-			var lineRect = line.getBoundingClientRect();
-			var spanRect1 = span1.getBoundingClientRect();
-			var spanRect2 = span2.getBoundingClientRect();
-			var spanRect3 = span3.getBoundingClientRect();
-			var spanRect4 = span4.getBoundingClientRect();
-			var h1 = spanRect1.bottom - spanRect1.top;
-			var h2 = spanRect2.bottom - spanRect2.top;
-			var h3 = spanRect3.bottom - spanRect3.top;
-			var h4 = spanRect4.bottom - spanRect4.top;
-			var fontStyle = 0;
-			var lineHeight = lineRect.bottom - lineRect.top;
-			if (h2 > h1) {
-				fontStyle = 1;
-			}
-			if (h3 > h2) {
-				fontStyle = 2;
-			}
-			if (h4 > h3) {
-				fontStyle = 3;
-			}
-			var style;
-			if (fontStyle !== 0) {
-				style = {style: {}};
-				if ((fontStyle & 1) !== 0) {
-					style.style.fontStyle = "italic";
-				}
-				if ((fontStyle & 2) !== 0) {
-					style.style.fontWeight = "bold";
-				}
-			}
-			this._largestFontStyle = style;
-			parent.removeChild(line);
-			return lineHeight;
-		},
-		_calculatePadding: function() {
-			var document = this._frameDocument;
-			var parent = this._clientDiv;
-			var pad = this._getPadding(this._viewDiv);
-			var div1 = document.createElement("DIV");
-			div1.style.position = "fixed";
-			div1.style.left = "-1000px";
-			div1.style.paddingLeft = pad.left + "px";
-			div1.style.paddingTop = pad.top + "px";
-			div1.style.paddingRight = pad.right + "px";
-			div1.style.paddingBottom = pad.bottom + "px";
-			div1.style.width = "100px";
-			div1.style.height = "100px";
-			var div2 = document.createElement("DIV");
-			div2.style.width = "100%";
-			div2.style.height = "100%";
-			div1.appendChild(div2);
-			parent.appendChild(div1);
-			var rect1 = div1.getBoundingClientRect();
-			var rect2 = div2.getBoundingClientRect();
-			parent.removeChild(div1);
-			pad = {
-				left: rect2.left - rect1.left,
-				top: rect2.top - rect1.top,
-				right: rect1.right - rect2.right,
-				bottom: rect1.bottom - rect2.bottom
-			};
-			return pad;
-		},
-		_clearSelection: function (direction) {
-			var selection = this._getSelection();
-			if (selection.isEmpty()) { return false; }
-			if (direction === "next") {
-				selection.start = selection.end;
-			} else {
-				selection.end = selection.start;
-			}
-			this._setSelection(selection, true);
-			return true;
-		},
-		_clone: function (obj) {
-			/*Note that this code only works because of the limited types used in TextViewOptions */
-			if (obj instanceof Array) {
-				return obj.slice(0);
-			}
-			return obj;
-		},
-		_compare: function (s1, s2) {
-			if (s1 === s2) { return true; }
-			if (s1 && !s2 || !s1 && s2) { return false; }
-			if ((s1 && s1.constructor === String) || (s2 && s2.constructor === String)) { return false; }
-			if (s1 instanceof Array || s2 instanceof Array) {
-				if (!(s1 instanceof Array && s2 instanceof Array)) { return false; }
-				if (s1.length !== s2.length) { return false; }
-				for (var i = 0; i < s1.length; i++) {
-					if (!this._compare(s1[i], s2[i])) {
-						return false;
-					}
-				}
-				return true;
-			}
-			if (!(s1 instanceof Object) || !(s2 instanceof Object)) { return false; }
-			var p;
-			for (p in s1) {
-				if (s1.hasOwnProperty(p)) {
-					if (!s2.hasOwnProperty(p)) { return false; }
-					if (!this._compare(s1[p], s2[p])) {return false; }
-				}
-			}
-			for (p in s2) {
-				if (!s1.hasOwnProperty(p)) { return false; }
-			}
-			return true;
-		},
-		_commitIME: function () {
-			if (this._imeOffset === -1) { return; }
-			// make the state of the IME match the state the view expects it be in
-			// when the view commits the text and IME also need to be committed
-			// this can be accomplished by changing the focus around
-			this._scrollDiv.focus();
-			this._clientDiv.focus();
-			
-			var model = this._model;
-			var lineIndex = model.getLineAtOffset(this._imeOffset);
-			var lineStart = model.getLineStart(lineIndex);
-			var newText = this._getDOMText(lineIndex);
-			var oldText = model.getLine(lineIndex);
-			var start = this._imeOffset - lineStart;
-			var end = start + newText.length - oldText.length;
-			if (start !== end) {
-				var insertText = newText.substring(start, end);
-				this._doContent(insertText);
-			}
-			this._imeOffset = -1;
-		},
-		_convertDelimiter: function (text, addTextFunc, addDelimiterFunc) {
-				var cr = 0, lf = 0, index = 0, length = text.length;
-				while (index < length) {
-					if (cr !== -1 && cr <= index) { cr = text.indexOf("\r", index); }
-					if (lf !== -1 && lf <= index) { lf = text.indexOf("\n", index); }
-					var start = index, end;
-					if (lf === -1 && cr === -1) {
-						addTextFunc(text.substring(index));
-						break;
-					}
-					if (cr !== -1 && lf !== -1) {
-						if (cr + 1 === lf) {
-							end = cr;
-							index = lf + 1;
-						} else {
-							end = cr < lf ? cr : lf;
-							index = (cr < lf ? cr : lf) + 1;
-						}
-					} else if (cr !== -1) {
-						end = cr;
-						index = cr + 1;
-					} else {
-						end = lf;
-						index = lf + 1;
-					}
-					addTextFunc(text.substring(start, end));
-					addDelimiterFunc();
-				}
-		},
-		_createActions: function () {
-			var KeyBinding = mKeyBinding.KeyBinding;
-			//no duplicate keybindings
-			var bindings = this._keyBindings = [];
-
-			// Cursor Navigation
-			bindings.push({name: "lineUp",		keyBinding: new KeyBinding(38), predefined: true});
-			bindings.push({name: "lineDown",	keyBinding: new KeyBinding(40), predefined: true});
-			bindings.push({name: "charPrevious",	keyBinding: new KeyBinding(37), predefined: true});
-			bindings.push({name: "charNext",	keyBinding: new KeyBinding(39), predefined: true});
-			if (isMac) {
-				bindings.push({name: "scrollPageUp",		keyBinding: new KeyBinding(33), predefined: true});
-				bindings.push({name: "scrollPageDown",	keyBinding: new KeyBinding(34), predefined: true});
-				bindings.push({name: "pageUp",		keyBinding: new KeyBinding(33, null, null, true), predefined: true});
-				bindings.push({name: "pageDown",	keyBinding: new KeyBinding(34, null, null, true), predefined: true});
-				bindings.push({name: "lineStart",	keyBinding: new KeyBinding(37, true), predefined: true});
-				bindings.push({name: "lineEnd",		keyBinding: new KeyBinding(39, true), predefined: true});
-				bindings.push({name: "wordPrevious",	keyBinding: new KeyBinding(37, null, null, true), predefined: true});
-				bindings.push({name: "wordNext",	keyBinding: new KeyBinding(39, null, null, true), predefined: true});
-				bindings.push({name: "scrollTextStart",	keyBinding: new KeyBinding(36), predefined: true});
-				bindings.push({name: "scrollTextEnd",		keyBinding: new KeyBinding(35), predefined: true});
-				bindings.push({name: "textStart",	keyBinding: new KeyBinding(38, true), predefined: true});
-				bindings.push({name: "textEnd",		keyBinding: new KeyBinding(40, true), predefined: true});
-				bindings.push({name: "scrollPageUp",	keyBinding: new KeyBinding(38, null, null, null, true), predefined: true});
-				bindings.push({name: "scrollPageDown",		keyBinding: new KeyBinding(40, null, null, null, true), predefined: true});
-				bindings.push({name: "lineStart",	keyBinding: new KeyBinding(37, null, null, null, true), predefined: true});
-				bindings.push({name: "lineEnd",		keyBinding: new KeyBinding(39, null, null, null, true), predefined: true});
-				//TODO These two actions should be changed to paragraph start and paragraph end  when word wrap is implemented
-				bindings.push({name: "lineStart",	keyBinding: new KeyBinding(38, null, null, true), predefined: true});
-				bindings.push({name: "lineEnd",		keyBinding: new KeyBinding(40, null, null, true), predefined: true});
-			} else {
-				bindings.push({name: "pageUp",		keyBinding: new KeyBinding(33), predefined: true});
-				bindings.push({name: "pageDown",	keyBinding: new KeyBinding(34), predefined: true});
-				bindings.push({name: "lineStart",	keyBinding: new KeyBinding(36), predefined: true});
-				bindings.push({name: "lineEnd",		keyBinding: new KeyBinding(35), predefined: true});
-				bindings.push({name: "wordPrevious",	keyBinding: new KeyBinding(37, true), predefined: true});
-				bindings.push({name: "wordNext",	keyBinding: new KeyBinding(39, true), predefined: true});
-				bindings.push({name: "textStart",	keyBinding: new KeyBinding(36, true), predefined: true});
-				bindings.push({name: "textEnd",		keyBinding: new KeyBinding(35, true), predefined: true});
-			}
-			if (isFirefox && isLinux) {
-				bindings.push({name: "lineUp",		keyBinding: new KeyBinding(38, true), predefined: true});
-				bindings.push({name: "lineDown",	keyBinding: new KeyBinding(40, true), predefined: true});
-			}
-
-			// Select Cursor Navigation
-			bindings.push({name: "selectLineUp",		keyBinding: new KeyBinding(38, null, true), predefined: true});
-			bindings.push({name: "selectLineDown",		keyBinding: new KeyBinding(40, null, true), predefined: true});
-			bindings.push({name: "selectCharPrevious",	keyBinding: new KeyBinding(37, null, true), predefined: true});
-			bindings.push({name: "selectCharNext",		keyBinding: new KeyBinding(39, null, true), predefined: true});
-			bindings.push({name: "selectPageUp",		keyBinding: new KeyBinding(33, null, true), predefined: true});
-			bindings.push({name: "selectPageDown",		keyBinding: new KeyBinding(34, null, true), predefined: true});
-			if (isMac) {
-				bindings.push({name: "selectLineStart",	keyBinding: new KeyBinding(37, true, true), predefined: true});
-				bindings.push({name: "selectLineEnd",		keyBinding: new KeyBinding(39, true, true), predefined: true});
-				bindings.push({name: "selectWordPrevious",	keyBinding: new KeyBinding(37, null, true, true), predefined: true});
-				bindings.push({name: "selectWordNext",	keyBinding: new KeyBinding(39, null, true, true), predefined: true});
-				bindings.push({name: "selectTextStart",	keyBinding: new KeyBinding(36, null, true), predefined: true});
-				bindings.push({name: "selectTextEnd",		keyBinding: new KeyBinding(35, null, true), predefined: true});
-				bindings.push({name: "selectTextStart",	keyBinding: new KeyBinding(38, true, true), predefined: true});
-				bindings.push({name: "selectTextEnd",		keyBinding: new KeyBinding(40, true, true), predefined: true});
-				bindings.push({name: "selectLineStart",	keyBinding: new KeyBinding(37, null, true, null, true), predefined: true});
-				bindings.push({name: "selectLineEnd",		keyBinding: new KeyBinding(39, null, true, null, true), predefined: true});
-				//TODO These two actions should be changed to select paragraph start and select paragraph end  when word wrap is implemented
-				bindings.push({name: "selectLineStart",	keyBinding: new KeyBinding(38, null, true, true), predefined: true});
-				bindings.push({name: "selectLineEnd",		keyBinding: new KeyBinding(40, null, true, true), predefined: true});
-			} else {
-				if (isLinux) {
-					bindings.push({name: "selectWholeLineUp",		keyBinding: new KeyBinding(38, true, true), predefined: true});
-					bindings.push({name: "selectWholeLineDown",		keyBinding: new KeyBinding(40, true, true), predefined: true});
-				}
-				bindings.push({name: "selectLineStart",		keyBinding: new KeyBinding(36, null, true), predefined: true});
-				bindings.push({name: "selectLineEnd",		keyBinding: new KeyBinding(35, null, true), predefined: true});
-				bindings.push({name: "selectWordPrevious",	keyBinding: new KeyBinding(37, true, true), predefined: true});
-				bindings.push({name: "selectWordNext",		keyBinding: new KeyBinding(39, true, true), predefined: true});
-				bindings.push({name: "selectTextStart",		keyBinding: new KeyBinding(36, true, true), predefined: true});
-				bindings.push({name: "selectTextEnd",		keyBinding: new KeyBinding(35, true, true), predefined: true});
-			}
-
-			//Misc
-			bindings.push({name: "deletePrevious",		keyBinding: new KeyBinding(8), predefined: true});
-			bindings.push({name: "deletePrevious",		keyBinding: new KeyBinding(8, null, true), predefined: true});
-			bindings.push({name: "deleteNext",		keyBinding: new KeyBinding(46), predefined: true});
-			bindings.push({name: "deleteWordPrevious",	keyBinding: new KeyBinding(8, true), predefined: true});
-			bindings.push({name: "deleteWordPrevious",	keyBinding: new KeyBinding(8, true, true), predefined: true});
-			bindings.push({name: "deleteWordNext",		keyBinding: new KeyBinding(46, true), predefined: true});
-			bindings.push({name: "tab",			keyBinding: new KeyBinding(9), predefined: true});
-			bindings.push({name: "enter",			keyBinding: new KeyBinding(13), predefined: true});
-			bindings.push({name: "enter",			keyBinding: new KeyBinding(13, null, true), predefined: true});
-			bindings.push({name: "selectAll",		keyBinding: new KeyBinding('a', true), predefined: true});
-			if (isMac) {
-				bindings.push({name: "deleteNext",		keyBinding: new KeyBinding(46, null, true), predefined: true});
-				bindings.push({name: "deleteWordPrevious",	keyBinding: new KeyBinding(8, null, null, true), predefined: true});
-				bindings.push({name: "deleteWordNext",		keyBinding: new KeyBinding(46, null, null, true), predefined: true});
-			}
-				
-			/*
-			* Feature in IE/Chrome: prevent ctrl+'u', ctrl+'i', and ctrl+'b' from applying styles to the text.
-			*
-			* Note that Chrome applies the styles on the Mac with Ctrl instead of Cmd.
-			*/
-			if (!isFirefox) {
-				var isMacChrome = isMac && isChrome;
-				bindings.push({name: null, keyBinding: new KeyBinding('u', !isMacChrome, false, false, isMacChrome), predefined: true});
-				bindings.push({name: null, keyBinding: new KeyBinding('i', !isMacChrome, false, false, isMacChrome), predefined: true});
-				bindings.push({name: null, keyBinding: new KeyBinding('b', !isMacChrome, false, false, isMacChrome), predefined: true});
-			}
-
-			if (isFirefox) {
-				bindings.push({name: "copy", keyBinding: new KeyBinding(45, true), predefined: true});
-				bindings.push({name: "paste", keyBinding: new KeyBinding(45, null, true), predefined: true});
-				bindings.push({name: "cut", keyBinding: new KeyBinding(46, null, true), predefined: true});
-			}
-
-			// Add the emacs Control+ ... key bindings.
-			if (isMac) {
-				bindings.push({name: "lineStart", keyBinding: new KeyBinding("a", false, false, false, true), predefined: true});
-				bindings.push({name: "lineEnd", keyBinding: new KeyBinding("e", false, false, false, true), predefined: true});
-				bindings.push({name: "lineUp", keyBinding: new KeyBinding("p", false, false, false, true), predefined: true});
-				bindings.push({name: "lineDown", keyBinding: new KeyBinding("n", false, false, false, true), predefined: true});
-				bindings.push({name: "charPrevious", keyBinding: new KeyBinding("b", false, false, false, true), predefined: true});
-				bindings.push({name: "charNext", keyBinding: new KeyBinding("f", false, false, false, true), predefined: true});
-				bindings.push({name: "deletePrevious", keyBinding: new KeyBinding("h", false, false, false, true), predefined: true});
-				bindings.push({name: "deleteNext", keyBinding: new KeyBinding("d", false, false, false, true), predefined: true});
-				bindings.push({name: "deleteLineEnd", keyBinding: new KeyBinding("k", false, false, false, true), predefined: true});
-				if (isFirefox) {
-					bindings.push({name: "scrollPageDown", keyBinding: new KeyBinding("v", false, false, false, true), predefined: true});
-					bindings.push({name: "deleteLineStart", keyBinding: new KeyBinding("u", false, false, false, true), predefined: true});
-					bindings.push({name: "deleteWordPrevious", keyBinding: new KeyBinding("w", false, false, false, true), predefined: true});
-				} else {
-					bindings.push({name: "pageDown", keyBinding: new KeyBinding("v", false, false, false, true), predefined: true});
-					bindings.push({name: "centerLine", keyBinding: new KeyBinding("l", false, false, false, true), predefined: true});
-					bindings.push({name: "enterNoCursor", keyBinding: new KeyBinding("o", false, false, false, true), predefined: true});
-					//TODO implement: y (yank), t (transpose)
-				}
-			}
-
-			//1 to 1, no duplicates
-			var self = this;
-			this._actions = [
-				{name: "lineUp",		defaultHandler: function() {return self._doLineUp({select: false});}},
-				{name: "lineDown",		defaultHandler: function() {return self._doLineDown({select: false});}},
-				{name: "lineStart",		defaultHandler: function() {return self._doHome({select: false, ctrl:false});}},
-				{name: "lineEnd",		defaultHandler: function() {return self._doEnd({select: false, ctrl:false});}},
-				{name: "charPrevious",		defaultHandler: function() {return self._doCursorPrevious({select: false, unit:"character"});}},
-				{name: "charNext",		defaultHandler: function() {return self._doCursorNext({select: false, unit:"character"});}},
-				{name: "pageUp",		defaultHandler: function() {return self._doPageUp({select: false});}},
-				{name: "pageDown",		defaultHandler: function() {return self._doPageDown({select: false});}},
-				{name: "scrollPageUp",		defaultHandler: function() {return self._doScroll({type: "pageUp"});}},
-				{name: "scrollPageDown",		defaultHandler: function() {return self._doScroll({type: "pageDown"});}},
-				{name: "wordPrevious",		defaultHandler: function() {return self._doCursorPrevious({select: false, unit:"word"});}},
-				{name: "wordNext",		defaultHandler: function() {return self._doCursorNext({select: false, unit:"word"});}},
-				{name: "textStart",		defaultHandler: function() {return self._doHome({select: false, ctrl:true});}},
-				{name: "textEnd",		defaultHandler: function() {return self._doEnd({select: false, ctrl:true});}},
-				{name: "scrollTextStart",	defaultHandler: function() {return self._doScroll({type: "textStart"});}},
-				{name: "scrollTextEnd",		defaultHandler: function() {return self._doScroll({type: "textEnd"});}},
-				{name: "centerLine",		defaultHandler: function() {return self._doScroll({type: "centerLine"});}},
-				
-				{name: "selectLineUp",		defaultHandler: function() {return self._doLineUp({select: true});}},
-				{name: "selectLineDown",	defaultHandler: function() {return self._doLineDown({select: true});}},
-				{name: "selectWholeLineUp",		defaultHandler: function() {return self._doLineUp({select: true, wholeLine: true});}},
-				{name: "selectWholeLineDown",	defaultHandler: function() {return self._doLineDown({select: true, wholeLine: true});}},
-				{name: "selectLineStart",	defaultHandler: function() {return self._doHome({select: true, ctrl:false});}},
-				{name: "selectLineEnd",		defaultHandler: function() {return self._doEnd({select: true, ctrl:false});}},
-				{name: "selectCharPrevious",	defaultHandler: function() {return self._doCursorPrevious({select: true, unit:"character"});}},
-				{name: "selectCharNext",	defaultHandler: function() {return self._doCursorNext({select: true, unit:"character"});}},
-				{name: "selectPageUp",		defaultHandler: function() {return self._doPageUp({select: true});}},
-				{name: "selectPageDown",	defaultHandler: function() {return self._doPageDown({select: true});}},
-				{name: "selectWordPrevious",	defaultHandler: function() {return self._doCursorPrevious({select: true, unit:"word"});}},
-				{name: "selectWordNext",	defaultHandler: function() {return self._doCursorNext({select: true, unit:"word"});}},
-				{name: "selectTextStart",	defaultHandler: function() {return self._doHome({select: true, ctrl:true});}},
-				{name: "selectTextEnd",		defaultHandler: function() {return self._doEnd({select: true, ctrl:true});}},
-
-				{name: "deletePrevious",	defaultHandler: function() {return self._doBackspace({unit:"character"});}},
-				{name: "deleteNext",		defaultHandler: function() {return self._doDelete({unit:"character"});}},
-				{name: "deleteWordPrevious",	defaultHandler: function() {return self._doBackspace({unit:"word"});}},
-				{name: "deleteWordNext",	defaultHandler: function() {return self._doDelete({unit:"word"});}},
-				{name: "deleteLineStart",	defaultHandler: function() {return self._doBackspace({unit: "line"});}},
-				{name: "deleteLineEnd",	defaultHandler: function() {return self._doDelete({unit: "line"});}},
-				{name: "tab",			defaultHandler: function() {return self._doTab();}},
-				{name: "enter",			defaultHandler: function() {return self._doEnter();}},
-				{name: "enterNoCursor",	defaultHandler: function() {return self._doEnter({noCursor:true});}},
-				{name: "selectAll",		defaultHandler: function() {return self._doSelectAll();}},
-				{name: "copy",			defaultHandler: function() {return self._doCopy();}},
-				{name: "cut",			defaultHandler: function() {return self._doCut();}},
-				{name: "paste",			defaultHandler: function() {return self._doPaste();}}
-			];
-		},
-		_createLine: function(parent, div, document, lineIndex, model) {
-			var lineText = model.getLine(lineIndex);
-			var lineStart = model.getLineStart(lineIndex);
-			var e = {type:"LineStyle", textView: this, lineIndex: lineIndex, lineText: lineText, lineStart: lineStart};
-			this.onLineStyle(e);
-			var lineDiv = div || document.createElement("DIV");
-			if (!div || !this._compare(div.viewStyle, e.style)) {
-				this._applyStyle(e.style, lineDiv, div);
-				lineDiv.viewStyle = e.style;
-			}
-			lineDiv.lineIndex = lineIndex;
-			var ranges = [];
-			var data = {tabOffset: 0, ranges: ranges};
-			this._createRanges(e.ranges, lineText, 0, lineText.length, lineStart, data);
-			
-			/*
-			* A trailing span with a whitespace is added for three different reasons:
-			* 1. Make sure the height of each line is the largest of the default font
-			* in normal, italic, bold, and italic-bold.
-			* 2. When full selection is off, Firefox, Opera and IE9 do not extend the 
-			* selection at the end of the line when the line is fully selected. 
-			* 3. The height of a div with only an empty span is zero.
-			*/
-			var c = " ";
-			if (!this._fullSelection && isIE < 9) {
-				/* 
-				* IE8 already selects extra space at end of a line fully selected,
-				* adding another space at the end of the line causes the selection 
-				* to look too big. The fix is to use a zero-width space (\uFEFF) instead. 
-				*/
-				c = "\uFEFF";
-			}
-			if (isWebkit) {
-				/*
-				* Feature in WekKit. Adding a regular white space to the line will
-				* cause the longest line in the view to wrap even though "pre" is set.
-				* The fix is to use the zero-width non-joiner character (\u200C) instead.
-				* Note: To not use \uFEFF because in old version of Chrome this character 
-				* shows a glyph;
-				*/
-				c = "\u200C";
-			}
-			ranges.push({text: c, style: this._largestFontStyle, ignoreChars: 1});
-			
-			var range, span, style, oldSpan, oldStyle, text, oldText, end = 0, oldEnd = 0, next;
-			var changeCount, changeStart;
-			if (div) {
-				var modelChangedEvent = div.modelChangedEvent;
-				if (modelChangedEvent) {
-					if (modelChangedEvent.removedLineCount === 0 && modelChangedEvent.addedLineCount === 0) {
-						changeStart = modelChangedEvent.start - lineStart;
-						changeCount = modelChangedEvent.addedCharCount - modelChangedEvent.removedCharCount;
-					} else {
-						changeStart = -1;
-					}
-					div.modelChangedEvent = undefined;
-				}
-				oldSpan = div.firstChild;
-			}
-			for (var i = 0; i < ranges.length; i++) {
-				range = ranges[i];
-				text = range.text;
-				end += text.length;
-				style = range.style;
-				if (oldSpan) {
-					oldText = oldSpan.firstChild.data;
-					oldStyle = oldSpan.viewStyle;
-					if (oldText === text && this._compare(style, oldStyle)) {
-						oldEnd += oldText.length;
-						oldSpan._rectsCache = undefined;
-						span = oldSpan = oldSpan.nextSibling;
-						continue;
-					} else {
-						while (oldSpan) {
-							if (changeStart !== -1) {
-								var spanEnd = end;
-								if (spanEnd >= changeStart) {
-									spanEnd -= changeCount;
-								}
-								var length = oldSpan.firstChild.data.length;
-								if (oldEnd + length > spanEnd) { break; }
-								oldEnd += length;
-							}
-							next = oldSpan.nextSibling;
-							lineDiv.removeChild(oldSpan);
-							oldSpan = next;
-						}
-					}
-				}
-				span = this._createSpan(lineDiv, document, text, style, range.ignoreChars);
-				if (oldSpan) {
-					lineDiv.insertBefore(span, oldSpan);
-				} else {
-					lineDiv.appendChild(span);
-				}
-				if (div) {
-					div.lineWidth = undefined;
-				}
-			}
-			if (div) {
-				var tmp = span ? span.nextSibling : null;
-				while (tmp) {
-					next = tmp.nextSibling;
-					div.removeChild(tmp);
-					tmp = next;
-				}
-			} else {
-				parent.appendChild(lineDiv);
-			}
-			return lineDiv;
-		},
-		_createRanges: function(ranges, text, start, end, lineStart, data) {
-			if (start >= end) { return; }
-			if (ranges) {
-				for (var i = 0; i < ranges.length; i++) {
-					var range = ranges[i];
-					if (range.end <= lineStart + start) { continue; }
-					var styleStart = Math.max(lineStart + start, range.start) - lineStart;
-					if (styleStart >= end) { break; }
-					var styleEnd = Math.min(lineStart + end, range.end) - lineStart;
-					if (styleStart < styleEnd) {
-						styleStart = Math.max(start, styleStart);
-						styleEnd = Math.min(end, styleEnd);
-						if (start < styleStart) {
-							this._createRange(text, start, styleStart, null, data);
-						}
-						while (i + 1 < ranges.length && ranges[i + 1].start - lineStart === styleEnd && this._compare(range.style, ranges[i + 1].style)) {
-							range = ranges[i + 1];
-							styleEnd = Math.min(lineStart + end, range.end) - lineStart;
-							i++;
-						}
-						this._createRange(text, styleStart, styleEnd, range.style, data);
-						start = styleEnd;
-					}
-				}
-			}
-			if (start < end) {
-				this._createRange(text, start, end, null, data);
-			}
-		},
-		_createRange: function(text, start, end, style, data) {
-			if (start >= end) { return; }
-			var tabSize = this._customTabSize, range;
-			if (tabSize && tabSize !== 8) {
-				var tabIndex = text.indexOf("\t", start);
-				while (tabIndex !== -1 && tabIndex < end) {
-					if (start < tabIndex) {
-						range = {text: text.substring(start, tabIndex), style: style};
-						data.ranges.push(range);
-						data.tabOffset += range.text.length;
-					}
-					var spacesCount = tabSize - (data.tabOffset % tabSize);
-					if (spacesCount > 0) {
-						//TODO hack to preserve text length in getDOMText()
-						var spaces = "\u00A0";
-						for (var i = 1; i < spacesCount; i++) {
-							spaces += " ";
-						}
-						range = {text: spaces, style: style, ignoreChars: spacesCount - 1};
-						data.ranges.push(range);
-						data.tabOffset += range.text.length;
-					}
-					start = tabIndex + 1;
-					tabIndex = text.indexOf("\t", start);
-				}
-			}
-			if (start < end) {
-				range = {text: text.substring(start, end), style: style};
-				data.ranges.push(range);
-				data.tabOffset += range.text.length;
-			}
-		},
-		_createSpan: function(parent, document, text, style, ignoreChars) {
-			var isLink = style && style.tagName === "A";
-			if (isLink) { parent.hasLink = true; }
-			var tagName = isLink && this._linksVisible ? "A" : "SPAN";
-			var child = document.createElement(tagName);
-			child.appendChild(document.createTextNode(text));
-			this._applyStyle(style, child);
-			if (tagName === "A") {
-				var self = this;
-				addHandler(child, "click", function(e) { return self._handleLinkClick(e); }, false);
-			}
-			child.viewStyle = style;
-			if (ignoreChars) {
-				child.ignoreChars = ignoreChars;
-			}
-			return child;
-		},
-		_createRuler: function(ruler) {
-			if (!this._clientDiv) { return; }
-			var document = this._frameDocument;
-			var body = document.body;
-			var side = ruler.getLocation();
-			var rulerParent = side === "left" ? this._leftDiv : this._rightDiv;
-			if (!rulerParent) {
-				rulerParent = document.createElement("DIV");
-				rulerParent.style.overflow = "hidden";
-				rulerParent.style.MozUserSelect = "none";
-				rulerParent.style.WebkitUserSelect = "none";
-				if (isIE) {
-					rulerParent.attachEvent("onselectstart", function() {return false;});
-				}
-				rulerParent.style.position = "absolute";
-				rulerParent.style.top = "0px";
-				rulerParent.style.cursor = "default";
-				body.appendChild(rulerParent);
-				if (side === "left") {
-					this._leftDiv = rulerParent;
-					rulerParent.className = "viewLeftRuler";
-				} else {
-					this._rightDiv = rulerParent;
-					rulerParent.className = "viewRightRuler";
-				}
-				var table = document.createElement("TABLE");
-				rulerParent.appendChild(table);
-				table.cellPadding = "0px";
-				table.cellSpacing = "0px";
-				table.border = "0px";
-				table.insertRow(0);
-				var self = this;
-				addHandler(rulerParent, "click", function(e) { self._handleRulerEvent(e); });
-				addHandler(rulerParent, "dblclick", function(e) { self._handleRulerEvent(e); });
-				addHandler(rulerParent, "mousemove", function(e) { self._handleRulerEvent(e); });
-				addHandler(rulerParent, "mouseover", function(e) { self._handleRulerEvent(e); });
-				addHandler(rulerParent, "mouseout", function(e) { self._handleRulerEvent(e); });
-			}
-			var div = document.createElement("DIV");
-			div._ruler = ruler;
-			div.rulerChanged = true;
-			div.style.position = "relative";
-			var row = rulerParent.firstChild.rows[0];
-			var index = row.cells.length;
-			var cell = row.insertCell(index);
-			cell.vAlign = "top";
-			cell.appendChild(div);
-		},
-		_createFrame: function() {
-			if (this.frame) { return; }
-			var parent = this._parent;
-			while (parent.hasChildNodes()) { parent.removeChild(parent.lastChild); }
-			var parentDocument = parent.ownerDocument;
-			this._parentDocument = parentDocument;
-			var frame = parentDocument.createElement("IFRAME");
-			this._frame = frame;
-			frame.frameBorder = "0px";//for IE, needs to be set before the frame is added to the parent
-			frame.style.border = "0px";
-			frame.style.width = "100%";
-			frame.style.height = "100%";
-			frame.scrolling = "no";
-			var self = this;
-			/*
-			* Note that it is not possible to create the contents of the frame if the
-			* parent is not connected to the document.  Only create it when the load
-			* event is trigged.
-			*/
-			this._loadHandler = function(e) {
-				self._handleLoad(e);
-			};
-			addHandler(frame, "load", this._loadHandler, !!isFirefox);
-			if (!isWebkit) {
-				/*
-				* Feature in IE and Firefox.  It is not possible to get the style of an
-				* element if it is not layed out because one of the ancestor has
-				* style.display = none.  This means that the view cannot be created in this
-				* situations, since no measuring can be performed.  The fix is to listen
-				* for DOMAttrModified and create or destroy the view when the style.display
-				* attribute changes.
-				*/
-				addHandler(parentDocument, "DOMAttrModified", this._attrModifiedHandler = function(e) {
-					self._handleDOMAttrModified(e);
-				});
-			}
-			parent.appendChild(frame);
-			/* create synchronously if possible */
-			if (this._sync) {
-				this._handleLoad();
-			}
-		},
-		_getFrameHTML: function() {
-			var html = [];
-			html.push("<!DOCTYPE html>");
-			html.push("<html>");
-			html.push("<head>");
-			if (isIE < 9) {
-				html.push("<meta http-equiv='X-UA-Compatible' content='IE=EmulateIE7'/>");
-			}
-			html.push("<style>");
-			html.push(".viewContainer {font-family: monospace; font-size: 10pt;}");
-			html.push(".view {padding: 1px 2px;}");
-			html.push(".viewContent {}");
-			html.push("</style>");
-			if (this._stylesheet) {
-				var stylesheet = typeof(this._stylesheet) === "string" ? [this._stylesheet] : this._stylesheet;
-				for (var i = 0; i < stylesheet.length; i++) {
-					var sheet = stylesheet[i];
-					var isLink = this._isLinkURL(sheet);
-					if (isLink && this._sync) {
-						try {
-							var objXml = new XMLHttpRequest();
-							if (objXml.overrideMimeType) {
-								objXml.overrideMimeType("text/css");
-							}
-							objXml.open("GET", sheet, false);
-							objXml.send(null);
-							sheet = objXml.responseText;
-							isLink = false;
-						} catch (e) {}
-					}
-					if (isLink) {
-						html.push("<link rel='stylesheet' type='text/css' ");
-						/*
-						* Bug in IE7. The window load event is not sent unless a load handler is added to the link node.
-						*/
-						if (isIE < 9) {
-							html.push("onload='window' ");
-						}
-						html.push("href='");
-						html.push(sheet);
-						html.push("'></link>");
-					} else {
-						html.push("<style>");
-						html.push(sheet);
-						html.push("</style>");
-					}
-				}
-			}
-			/*
-			* Feature in WebKit.  In WebKit, window load will not wait for the style sheets
-			* to be loaded unless there is script element after the style sheet link elements.
-			*/
-			html.push("<script>");
-			html.push("var waitForStyleSheets = true;");
-			html.push("</script>");
-			html.push("</head>");
-			html.push("<body spellcheck='false'></body>");
-			html.push("</html>");
-			return html.join("");
-		},
-		_createView: function() {
-			if (this._frameDocument) { return; }
-			var frameWindow = this._frameWindow = this._frame.contentWindow;
-			var frameDocument = this._frameDocument = frameWindow.document;
-			var self = this;
-			function write() {
-				frameDocument.open("text/html", "replace");
-				frameDocument.write(self._getFrameHTML());
-				frameDocument.close();
-				self._windowLoadHandler = function(e) {
-					/*
-					* Bug in Safari.  Safari sends the window load event before the
-					* style sheets are loaded. The fix is to defer creation of the
-					* contents until the document readyState changes to complete.
-					*/
-					if (self._isDocumentReady()) {
-						self._createContent();
-					}
-				};
-				addHandler(frameWindow, "load", self._windowLoadHandler);
-			}
-			write();
-			if (this._sync) {
-				this._createContent();
-			} else {
-				/*
-				* Bug in Webkit. Webkit does not send the load event for the iframe window when the main page
-				* loads as a result of backward or forward navigation.
-				* The fix is to use a timer to create the content only when the document is ready.
-				*/
-				this._createViewTimer = function() {
-					if (self._clientDiv) { return; }
-					if (self._isDocumentReady()) {
-						self._createContent();
-					} else {
-						setTimeout(self._createViewTimer, 10);
-					}
-				};
-				setTimeout(this._createViewTimer, 10);
-			}
-		},
-		_isDocumentReady: function() {
-			var frameDocument = this._frameDocument;
-			if (!frameDocument) { return false; }
-			if (frameDocument.readyState === "complete") {
-				return true;
-			} else if (frameDocument.readyState === "interactive" && isFirefox) {
-				/*
-				* Bug in Firefox. Firefox does not change the document ready state to complete 
-				* all the time. The fix is to wait for the ready state to be "interactive" and check that 
-				* all css rules are initialized.
-				*/
-				var styleSheets = frameDocument.styleSheets;
-				var styleSheetCount = 1;
-				if (this._stylesheet) {
-					styleSheetCount += typeof(this._stylesheet) === "string" ? 1 : this._stylesheet.length;
-				}
-				if (styleSheetCount === styleSheets.length) {
-					var index = 0;
-					while (index < styleSheets.length) {
-						var count = 0;
-						try {
-							count = styleSheets.item(index).cssRules.length;
-						} catch (ex) {
-							/*
-							* Feature in Firefox. To determine if a stylesheet is loaded the number of css rules is used, if the 
-							* stylesheet is not loaded this operation will throw an invalid access error. When a stylesheet from
-							* a different domain is loaded, accessing the css rules will result in a security exception. In this
-							* case count is set to 1 to indicate the stylesheet is loaded.
-							*/
-							if (ex.code !== DOMException.INVALID_ACCESS_ERR) {
-								count = 1;
-							}
-						}
-						if (count === 0) { break; }
-						index++;
-					}
-					return index === styleSheets.length;
-				}	
-			}
-			return false;
-		},
-		_createContent: function() {
-			if (this._clientDiv) { return; }
-			var parent = this._parent;
-			var parentDocument = this._parentDocument;
-			var frameDocument = this._frameDocument;
-			var body = frameDocument.body;
-			this._setThemeClass(this._themeClass, true);
-			body.style.margin = "0px";
-			body.style.borderWidth = "0px";
-			body.style.padding = "0px";
-			
-			var textArea;
-			if (isPad) {
-				var touchDiv = parentDocument.createElement("DIV");
-				this._touchDiv = touchDiv;
-				touchDiv.style.position = "absolute";
-				touchDiv.style.border = "0px";
-				touchDiv.style.padding = "0px";
-				touchDiv.style.margin = "0px";
-				touchDiv.style.zIndex = "2";
-				touchDiv.style.overflow = "hidden";
-				touchDiv.style.background="transparent";
-				touchDiv.style.WebkitUserSelect = "none";
-				parent.appendChild(touchDiv);
-
-				textArea = parentDocument.createElement("TEXTAREA");
-				this._textArea = textArea;
-				textArea.style.position = "absolute";
-				textArea.style.whiteSpace = "pre";
-				textArea.style.left = "-1000px";
-				textArea.tabIndex = 1;
-				textArea.autocapitalize = "off";
-				textArea.autocorrect = "off";
-				textArea.className = "viewContainer";
-				textArea.style.background = "transparent";
-				textArea.style.color = "transparent";
-				textArea.style.border = "0px";
-				textArea.style.padding = "0px";
-				textArea.style.margin = "0px";
-				textArea.style.borderRadius = "0px";
-				textArea.style.WebkitAppearance = "none";
-				textArea.style.WebkitTapHighlightColor = "transparent";
-				touchDiv.appendChild(textArea);
-			}
-			if (isFirefox) {
-				var clipboardDiv = frameDocument.createElement("DIV");
-				this._clipboardDiv = clipboardDiv;
-				clipboardDiv.style.position = "fixed";
-				clipboardDiv.style.whiteSpace = "pre";
-				clipboardDiv.style.left = "-1000px";
-				body.appendChild(clipboardDiv);
-			}
-
-			var viewDiv = frameDocument.createElement("DIV");
-			viewDiv.className = "view";
-			this._viewDiv = viewDiv;
-			viewDiv.id = "viewDiv";
-			viewDiv.tabIndex = -1;
-			viewDiv.style.overflow = "auto";
-			viewDiv.style.position = "absolute";
-			viewDiv.style.top = "0px";
-			viewDiv.style.borderWidth = "0px";
-			viewDiv.style.margin = "0px";
-			viewDiv.style.outline = "none";
-			body.appendChild(viewDiv);
-				
-			var scrollDiv = frameDocument.createElement("DIV");
-			this._scrollDiv = scrollDiv;
-			scrollDiv.id = "scrollDiv";
-			scrollDiv.style.margin = "0px";
-			scrollDiv.style.borderWidth = "0px";
-			scrollDiv.style.padding = "0px";
-			viewDiv.appendChild(scrollDiv);
-			
-			if (isFirefox) {
-				var clipDiv = frameDocument.createElement("DIV");
-				this._clipDiv = clipDiv;
-				clipDiv.id = "clipDiv";
-				clipDiv.style.position = "fixed";
-				clipDiv.style.overflow = "hidden";
-				clipDiv.style.margin = "0px";
-				clipDiv.style.borderWidth = "0px";
-				clipDiv.style.padding = "0px";
-				scrollDiv.appendChild(clipDiv);
-				
-				var clipScrollDiv = frameDocument.createElement("DIV");
-				this._clipScrollDiv = clipScrollDiv;
-				clipScrollDiv.id = "clipScrollDiv";
-				clipScrollDiv.style.position = "absolute";
-				clipScrollDiv.style.height = "1px";
-				clipScrollDiv.style.top = "-1000px";
-				clipDiv.appendChild(clipScrollDiv);
-			}
-			
-			this._setFullSelection(this._fullSelection, true);
-
-			var clientDiv = frameDocument.createElement("DIV");
-			clientDiv.className = "viewContent";
-			this._clientDiv = clientDiv;
-			clientDiv.id = "clientDiv";
-			clientDiv.style.whiteSpace = "pre";
-			clientDiv.style.position = this._clipDiv ? "absolute" : "fixed";
-			clientDiv.style.borderWidth = "0px";
-			clientDiv.style.margin = "0px";
-			clientDiv.style.padding = "0px";
-			clientDiv.style.outline = "none";
-			clientDiv.style.zIndex = "1";
-			if (isPad) {
-				clientDiv.style.WebkitTapHighlightColor = "transparent";
-			}
-			(this._clipDiv || scrollDiv).appendChild(clientDiv);
-
-			if (isFirefox && !clientDiv.setCapture) {
-				var overlayDiv = frameDocument.createElement("DIV");
-				this._overlayDiv = overlayDiv;
-				overlayDiv.id = "overlayDiv";
-				overlayDiv.style.position = clientDiv.style.position;
-				overlayDiv.style.borderWidth = clientDiv.style.borderWidth;
-				overlayDiv.style.margin = clientDiv.style.margin;
-				overlayDiv.style.padding = clientDiv.style.padding;
-				overlayDiv.style.cursor = "text";
-				overlayDiv.style.zIndex = "2";
-				(this._clipDiv || scrollDiv).appendChild(overlayDiv);
-			}
-			if (!isPad) {
-				clientDiv.contentEditable = "true";
-			}
-			this._lineHeight = this._calculateLineHeight();
-			this._viewPadding = this._calculatePadding();
-			if (isIE) {
-				body.style.lineHeight = this._lineHeight + "px";
-			}
-			this._setTabSize(this._tabSize, true);
-			this._hookEvents();
-			var rulers = this._rulers;
-			for (var i=0; i<rulers.length; i++) {
-				this._createRuler(rulers[i]);
-			}
-			this._updatePage();
-			var h = this._hScroll, v = this._vScroll;
-			this._vScroll = this._hScroll = 0;
-			if (h > 0 || v > 0) {
-				viewDiv.scrollLeft = h;
-				viewDiv.scrollTop = v;
-			}
-			this.onLoad({type: "Load"});
-		},
-		_defaultOptions: function() {
-			return {
-				parent: {value: undefined, recreate: true, update: null},
-				model: {value: undefined, recreate: false, update: this.setModel},
-				readonly: {value: false, recreate: false, update: null},
-				fullSelection: {value: true, recreate: false, update: this._setFullSelection},
-				tabSize: {value: 8, recreate: false, update: this._setTabSize},
-				expandTab: {value: false, recreate: false, update: null},
-				stylesheet: {value: [], recreate: false, update: this._setStyleSheet},
-				themeClass: {value: undefined, recreate: false, update: this._setThemeClass},
-				sync: {value: false, recreate: false, update: null}
-			};
-		},
-		_destroyFrame: function() {
-			var frame = this._frame;
-			if (!frame) { return; }
-			if (this._loadHandler) {
-				removeHandler(frame, "load", this._loadHandler, !!isFirefox);
-				this._loadHandler = null;
-			}
-			if (this._attrModifiedHandler) {
-				removeHandler(this._parentDocument, "DOMAttrModified", this._attrModifiedHandler);
-				this._attrModifiedHandler = null;
-			}
-			frame.parentNode.removeChild(frame);
-			this._frame = null;
-		},
-		_destroyRuler: function(ruler) {
-			var side = ruler.getLocation();
-			var rulerParent = side === "left" ? this._leftDiv : this._rightDiv;
-			if (rulerParent) {
-				var row = rulerParent.firstChild.rows[0];
-				var cells = row.cells;
-				for (var index = 0; index < cells.length; index++) {
-					var cell = cells[index];
-					if (cell.firstChild._ruler === ruler) { break; }
-				}
-				if (index === cells.length) { return; }
-				row.cells[index]._ruler = undefined;
-				row.deleteCell(index);
-			}
-		},
-		_destroyView: function() {
-			var clientDiv = this._clientDiv;
-			if (!clientDiv) { return; }
-			this._setGrab(null);
-			this._unhookEvents();
-			if (this._windowLoadHandler) {
-				removeHandler(this._frameWindow, "load", this._windowLoadHandler);
-				this._windowLoadHandler = null;
-			}
-
-			/* Destroy timers */
-			if (this._autoScrollTimerID) {
-				clearTimeout(this._autoScrollTimerID);
-				this._autoScrollTimerID = null;
-			}
-			if (this._updateTimer) {
-				clearTimeout(this._updateTimer);
-				this._updateTimer = null;
-			}
-
-			/* Destroy DOM */
-			var parent = this._frameDocument.body;
-			while (parent.hasChildNodes()) { parent.removeChild(parent.lastChild); }
-			if (this._touchDiv) {
-				this._parent.removeChild(this._touchDiv);
-				this._touchDiv = null;
-			}
-			this._selDiv1 = null;
-			this._selDiv2 = null;
-			this._selDiv3 = null;
-			this._insertedSelRule = false;
-			this._textArea = null;
-			this._clipboardDiv = null;
-			this._scrollDiv = null;
-			this._viewDiv = null;
-			this._clipDiv = null;
-			this._clipScrollDiv = null;
-			this._clientDiv = null;
-			this._overlayDiv = null;
-			this._leftDiv = null;
-			this._rightDiv = null;
-			this._frameDocument = null;
-			this._frameWindow = null;
-			this.onUnload({type: "Unload"});
-		},
-		_doAutoScroll: function (direction, x, y) {
-			this._autoScrollDir = direction;
-			this._autoScrollX = x;
-			this._autoScrollY = y;
-			if (!this._autoScrollTimerID) {
-				this._autoScrollTimer();
-			}
-		},
-		_endAutoScroll: function () {
-			if (this._autoScrollTimerID) { clearTimeout(this._autoScrollTimerID); }
-			this._autoScrollDir = undefined;
-			this._autoScrollTimerID = undefined;
-		},
-		_fixCaret: function() {
-			var clientDiv = this._clientDiv;
-			if (clientDiv) {
-				var hasFocus = this._hasFocus;
-				this._ignoreFocus = true;
-				if (hasFocus) { clientDiv.blur(); }
-				clientDiv.contentEditable = false;
-				clientDiv.contentEditable = true;
-				if (hasFocus) { clientDiv.focus(); }
-				this._ignoreFocus = false;
-			}
-		},
-		_getBaseText: function(start, end) {
-			var model = this._model;
-			/* This is the only case the view access the base model, alternatively the view could use a event to application to customize the text */
-			if (model.getBaseModel) {
-				start = model.mapOffset(start);
-				end = model.mapOffset(end);
-				model = model.getBaseModel();
-			}
-			return model.getText(start, end);
-		},
-		_getBoundsAtOffset: function (offset) {
-			var model = this._model;
-			var document = this._frameDocument;
-			var clientDiv = this._clientDiv;
-			var lineIndex = model.getLineAtOffset(offset);
-			var dummy;
-			var child = this._getLineNode(lineIndex);
-			if (!child) {
-				child = dummy = this._createLine(clientDiv, null, document, lineIndex, model);
-			}
-			var result = null;
-			if (offset < model.getLineEnd(lineIndex)) {
-				var lineOffset = model.getLineStart(lineIndex);
-				var lineChild = child.firstChild;
-				while (lineChild) {
-					var textNode = lineChild.firstChild;
-					var nodeLength = textNode.length; 
-					if (lineChild.ignoreChars) {
-						nodeLength -= lineChild.ignoreChars;
-					}
-					if (lineOffset + nodeLength > offset) {
-						var index = offset - lineOffset;
-						var range;
-						if (isRangeRects) {
-							range = document.createRange();
-							range.setStart(textNode, index);
-							range.setEnd(textNode, index + 1);
-							result = range.getBoundingClientRect();
-						} else if (isIE) {
-							range = document.body.createTextRange();
-							range.moveToElementText(lineChild);
-							range.collapse();
</