Bug 929766 - Remove Orion from the SourceEditor component. r=msucan
authorAnton Kovalyov <anton@mozilla.com>
Tue, 19 Nov 2013 15:53:13 -0800
changeset 165787 464f36a51d3e7fe8721a12d39a6e90fbf597376d
parent 165786 371a2267b7a829f1e5922e8829a3fbccdbe6b661
child 165788 39c711e4570a8970d0c722b9e3222f536d0b5292
push idunknown
push userunknown
push dateunknown
reviewersmsucan
bugs929766
milestone28.0a1
Bug 929766 - Remove Orion from the SourceEditor component. r=msucan
browser/app/profile/firefox.js
browser/devtools/jar.mn
browser/devtools/markupview/html-editor.js
browser/devtools/scratchpad/scratchpad.js
browser/devtools/scratchpad/test/browser_scratchpad_edit_ui_updates.js
browser/devtools/sourceeditor/codemirror/mozilla.css
browser/devtools/sourceeditor/editor.js
browser/devtools/sourceeditor/moz.build
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.ini
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_editor_basic.js
browser/devtools/sourceeditor/test/browser_editor_cursor.js
browser/devtools/sourceeditor/test/browser_editor_history.js
browser/devtools/sourceeditor/test/browser_editor_markers.js
browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js
browser/devtools/sourceeditor/test/head.js
browser/devtools/styleeditor/StyleSheetEditor.jsm
browser/devtools/styleeditor/styleeditor.xul
browser/devtools/styleeditor/test/browser_styleeditor_sv_resize.js
browser/themes/linux/devtools/editor-breakpoint.png
browser/themes/linux/devtools/editor-debug-location.png
browser/themes/linux/devtools/editor-error.png
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/linux/jar.mn
browser/themes/osx/devtools/editor-breakpoint.png
browser/themes/osx/devtools/editor-debug-location.png
browser/themes/osx/devtools/editor-error.png
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/osx/jar.mn
browser/themes/windows/devtools/editor-breakpoint.png
browser/themes/windows/devtools/editor-debug-location.png
browser/themes/windows/devtools/editor-error.png
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
browser/themes/windows/jar.mn
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1222,24 +1222,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/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
@@ -1677,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/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);
--- 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
--- a/browser/devtools/sourceeditor/editor.js
+++ b/browser/devtools/sourceeditor/editor.js
@@ -79,17 +79,17 @@ const CM_MAPPING = [
   "openDialog",
   "cursorCoords",
   "markText",
   "refresh"
 ];
 
 const CM_JUMP_DIALOG = [
   L10N.GetStringFromName("gotoLineCmd.promptTitle")
-    + " <input type=text style='width: 10em'/>"
+    + " <input class=jumptoline type=text style='width: 10em'/>"
 ];
 
 const { cssProperties, cssValues, cssColors } = getCSSKeywords();
 
 const editors = new WeakMap();
 
 Editor.modes = {
   text: { name: "text" },
@@ -181,25 +181,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.
@@ -498,20 +502,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);
--- 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();
-							range.moveEnd("character", index + 1);
-							range.moveStart("character", index);
-							result = range.getBoundingClientRect();
-						} else {
-							var text = textNode.data;
-							lineChild.removeChild(textNode);
-							lineChild.appendChild(document.createTextNode(text.substring(0, index)));
-							var span = document.createElement("SPAN");
-							span.appendChild(document.createTextNode(text.substring(index, index + 1)));
-							lineChild.appendChild(span);
-							lineChild.appendChild(document.createTextNode(text.substring(index + 1)));
-							result = span.getBoundingClientRect();
-							lineChild.innerHTML = "";
-							lineChild.appendChild(textNode);
-							if (!dummy) {
-								/*
-								 * Removing the element node that holds the selection start or end
-								 * causes the selection to be lost. The fix is to detect this case
-								 * and restore the selection. 
-								 */
-								var s = this._getSelection();
-								if ((lineOffset <= s.start && s.start < lineOffset + nodeLength) ||  (lineOffset <= s.end && s.end < lineOffset + nodeLength)) {
-									this._updateDOMSelection();
-								}
-							}
-						}
-						if (isIE) {
-							var logicalXDPI = window.screen.logicalXDPI;
-							var deviceXDPI = window.screen.deviceXDPI;
-							result.left = result.left * logicalXDPI / deviceXDPI;
-							result.right = result.right * logicalXDPI / deviceXDPI;
-						}
-						break;
-					}
-					lineOffset += nodeLength;
-					lineChild = lineChild.nextSibling;
-				}
-			}
-			if (!result) {
-				var rect = this._getLineBoundingClientRect(child);
-				result = {left: rect.right, right: rect.right};
-			}
-			if (dummy) { clientDiv.removeChild(dummy); }
-			return result;
-		},
-		_getBottomIndex: function (fullyVisible) {
-			var child = this._bottomChild;
-			if (fullyVisible && this._getClientHeight() > this._getLineHeight()) {
-				var rect = child.getBoundingClientRect();
-				var clientRect = this._clientDiv.getBoundingClientRect();
-				if (rect.bottom > clientRect.bottom) {
-					child = this._getLinePrevious(child) || child;
-				}
-			}
-			return child.lineIndex;
-		},
-		_getFrameHeight: function() {
-			return this._frameDocument.documentElement.clientHeight;
-		},
-		_getFrameWidth: function() {
-			return this._frameDocument.documentElement.clientWidth;
-		},
-		_getClientHeight: function() {
-			var viewPad = this._getViewPadding();
-			return Math.max(0, this._viewDiv.clientHeight - viewPad.top - viewPad.bottom);
-		},
-		_getClientWidth: function() {
-			var viewPad = this._getViewPadding();
-			return Math.max(0, this._viewDiv.clientWidth - viewPad.left - viewPad.right);
-		},
-		_getClipboardText: function (event, handler) {
-			var delimiter = this._model.getLineDelimiter();
-			var clipboadText, text;
-			if (this._frameWindow.clipboardData) {
-				//IE
-				clipboadText = [];
-				text = this._frameWindow.clipboardData.getData("Text");
-				this._convertDelimiter(text, function(t) {clipboadText.push(t);}, function() {clipboadText.push(delimiter);});
-				text = clipboadText.join("");
-				if (handler) { handler(text); }
-				return text;
-			}
-			if (isFirefox) {
-				this._ignoreFocus = true;
-				var document = this._frameDocument;
-				var clipboardDiv = this._clipboardDiv;
-				clipboardDiv.innerHTML = "<pre contenteditable=''></pre>";
-				clipboardDiv.firstChild.focus();
-				var self = this;
-				var _getText = function() {
-					var noteText = self._getTextFromElement(clipboardDiv);
-					clipboardDiv.innerHTML = "";
-					clipboadText = [];
-					self._convertDelimiter(noteText, function(t) {clipboadText.push(t);}, function() {clipboadText.push(delimiter);});
-					return clipboadText.join("");
-				};
-				
-				/* Try execCommand first. Works on firefox with clipboard permission. */
-				var result = false;
-				this._ignorePaste = true;
-
-				/* Do not try execCommand if middle-click is used, because if we do, we get the clipboard text, not the primary selection text. */
-				if (!isLinux || this._lastMouseButton !== 2) {
-					try {
-						result = document.execCommand("paste", false, null);
-					} catch (ex) {
-						/* Firefox can throw even when execCommand() works, see bug 362835. */
-						result = clipboardDiv.childNodes.length > 1 || clipboardDiv.firstChild && clipboardDiv.firstChild.childNodes.length > 0;
-					}
-				}
-				this._ignorePaste = false;
-				if (!result) {
-					/* Try native paste in DOM, works for firefox during the paste event. */
-					if (event) {
-						setTimeout(function() {
-							self.focus();
-							text = _getText();
-							if (text && handler) {
-								handler(text);
-							}
-							self._ignoreFocus = false;
-						}, 0);
-						return null;
-					} else {
-						/* no event and no clipboard permission, paste can't be performed */
-						this.focus();
-						this._ignoreFocus = false;
-						return "";
-					}
-				}
-				this.focus();
-				this._ignoreFocus = false;
-				text = _getText();
-				if (text && handler) {
-					handler(text);
-				}
-				return text;
-			}
-			//webkit
-			if (event && event.clipboardData) {
-				/*
-				* Webkit (Chrome/Safari) allows getData during the paste event
-				* Note: setData is not allowed, not even during copy/cut event
-				*/
-				clipboadText = [];
-				text = event.clipboardData.getData("text/plain");
-				this._convertDelimiter(text, function(t) {clipboadText.push(t);}, function() {clipboadText.push(delimiter);});
-				text = clipboadText.join("");
-				if (text && handler) {
-					handler(text);
-				}
-				return text;
-			} else {
-				//TODO try paste using extension (Chrome only)
-			}
-			return "";
-		},
-		_getDOMText: function(lineIndex) {
-			var child = this._getLineNode(lineIndex);
-			var lineChild = child.firstChild;
-			var text = "";
-			while (lineChild) {
-				var textNode = lineChild.firstChild;
-				while (textNode) {
-					if (lineChild.ignoreChars) {
-						for (var i = 0; i < textNode.length; i++) {
-							var ch = textNode.data.substring(i, i + 1);
-							if (ch !== " ") {
-								text += ch;
-							}
-						}
-					} else {
-						text += textNode.data;
-					}
-					textNode = textNode.nextSibling;
-				}
-				lineChild = lineChild.nextSibling;
-			}
-			return text;
-		},
-		_getTextFromElement: function(element) {
-			var document = element.ownerDocument;
-			var window = document.defaultView;
-			if (!window.getSelection) {
-				return element.innerText || element.textContent;
-			}
-
-			var newRange = document.createRange();
-			newRange.selectNode(element);
-
-			var selection = window.getSelection();
-			var oldRanges = [], i;
-			for (i = 0; i < selection.rangeCount; i++) {
-				oldRanges.push(selection.getRangeAt(i));
-			}
-
-			this._ignoreSelect = true;
-			selection.removeAllRanges();
-			selection.addRange(newRange);
-
-			var text = selection.toString();
-
-			selection.removeAllRanges();
-			for (i = 0; i < oldRanges.length; i++) {
-				selection.addRange(oldRanges[i]);
-			}
-
-			this._ignoreSelect = false;
-			return text;
-		},
-		_getViewPadding: function() {
-			return this._viewPadding;
-		},
-		_getLineBoundingClientRect: function (child) {
-			var rect = child.getBoundingClientRect();
-			var lastChild = child.lastChild;
-			//Remove any artificial trailing whitespace in the line
-			while (lastChild && lastChild.ignoreChars === lastChild.firstChild.length) {
-				lastChild = lastChild.previousSibling;
-			}
-			if (!lastChild) {
-				return {left: rect.left, top: rect.top, right: rect.left, bottom: rect.bottom};
-			}
-			var lastRect = lastChild.getBoundingClientRect();
-			return {left: rect.left, top: rect.top, right: lastRect.right, bottom: rect.bottom};
-		},
-		_getLineHeight: function() {
-			return this._lineHeight;
-		},
-		_getLineNode: function (lineIndex) {
-			var clientDiv = this._clientDiv;
-			var child = clientDiv.firstChild;
-			while (child) {
-				if (lineIndex === child.lineIndex) {
-					return child;
-				}
-				child = child.nextSibling;
-			}
-			return undefined;
-		},
-		_getLineNext: function (lineNode) {
-			var node = lineNode ? lineNode.nextSibling : this._clientDiv.firstChild;
-			while (node && node.lineIndex === -1) {
-				node = node.nextSibling;
-			}
-			return node;
-		},
-		_getLinePrevious: function (lineNode) {
-			var node = lineNode ? lineNode.previousSibling : this._clientDiv.lastChild;
-			while (node && node.lineIndex === -1) {
-				node = node.previousSibling;
-			}
-			return node;
-		},
-		_getOffset: function (offset, unit, direction) {
-			if (unit === "line") {
-				var model = this._model;
-				var lineIndex = model.getLineAtOffset(offset);
-				if (direction > 0) {
-					return model.getLineEnd(lineIndex);
-				}
-				return model.getLineStart(lineIndex);
-			}
-			if (unit === "wordend") {
-				return this._getOffset_W3C(offset, unit, direction);
-			}
-			return isIE ? this._getOffset_IE(offset, unit, direction) : this._getOffset_W3C(offset, unit, direction);
-		},
-		_getOffset_W3C: function (offset, unit, direction) {
-			function _isPunctuation(c) {
-				return (33 <= c && c <= 47) || (58 <= c && c <= 64) || (91 <= c && c <= 94) || c === 96 || (123 <= c && c <= 126);
-			}
-			function _isWhitespace(c) {
-				return c === 32 || c === 9;
-			}
-			if (unit === "word" || unit === "wordend") {
-				var model = this._model;
-				var lineIndex = model.getLineAtOffset(offset);
-				var lineText = model.getLine(lineIndex);
-				var lineStart = model.getLineStart(lineIndex);
-				var lineEnd = model.getLineEnd(lineIndex);
-				var lineLength = lineText.length;
-				var offsetInLine = offset - lineStart;
-				
-				
-				var c, previousPunctuation, previousLetterOrDigit, punctuation, letterOrDigit;
-				if (direction > 0) {
-					if (offsetInLine === lineLength) { return lineEnd; }
-					c = lineText.charCodeAt(offsetInLine);
-					previousPunctuation = _isPunctuation(c); 
-					previousLetterOrDigit = !previousPunctuation && !_isWhitespace(c);
-					offsetInLine++;
-					while (offsetInLine < lineLength) {
-						c = lineText.charCodeAt(offsetInLine);
-						punctuation = _isPunctuation(c);
-						if (unit === "wordend") {
-							if (!punctuation && previousPunctuation) { break; }
-						} else {
-							if (punctuation && !previousPunctuation) { break; }
-						}
-						letterOrDigit  = !punctuation && !_isWhitespace(c);
-						if (unit === "wordend") {
-							if (!letterOrDigit && previousLetterOrDigit) { break; }
-						} else {
-							if (letterOrDigit && !previousLetterOrDigit) { break; }
-						}
-						previousLetterOrDigit = letterOrDigit;
-						previousPunctuation = punctuation;
-						offsetInLine++;
-					}
-				} else {
-					if (offsetInLine === 0) { return lineStart; }
-					offsetInLine--;
-					c = lineText.charCodeAt(offsetInLine);
-					previousPunctuation = _isPunctuation(c); 
-					previousLetterOrDigit = !previousPunctuation && !_isWhitespace(c);
-					while (0 < offsetInLine) {
-						c = lineText.charCodeAt(offsetInLine - 1);
-						punctuation = _isPunctuation(c);
-						if (unit === "wordend") {
-							if (punctuation && !previousPunctuation) { break; }
-						} else {
-							if (!punctuation && previousPunctuation) { break; }
-						}
-						letterOrDigit  = !punctuation && !_isWhitespace(c);
-						if (unit === "wordend") {
-							if (letterOrDigit && !previousLetterOrDigit) { break; }
-						} else {
-							if (!letterOrDigit && previousLetterOrDigit) { break; }
-						}
-						previousLetterOrDigit = letterOrDigit;
-						previousPunctuation = punctuation;
-						offsetInLine--;
-					}
-				}
-				return lineStart + offsetInLine;
-			}
-			return offset + direction;
-		},
-		_getOffset_IE: function (offset, unit, direction) {
-			var document = this._frameDocument;
-			var model = this._model;
-			var lineIndex = model.getLineAtOffset(offset);
-			var clientDiv = this._clientDiv;
-			var dummy;
-			var child = this._getLineNode(lineIndex);
-			if (!child) {
-				child = dummy = this._createLine(clientDiv, null, document, lineIndex, model);
-			}
-			var result = 0, range, length;
-			var lineOffset = model.getLineStart(lineIndex);
-			if (offset === model.getLineEnd(lineIndex)) {
-				range = document.body.createTextRange();
-				range.moveToElementText(child.lastChild);
-				length = range.text.length;
-				range.moveEnd(unit, direction);
-				result = offset + range.text.length - length;
-			} else if (offset === lineOffset && direction < 0) {
-				result = lineOffset;
-			} else {
-				var lineChild = child.firstChild;
-				while (lineChild) {
-					var textNode = lineChild.firstChild;
-					var nodeLength = textNode.length;
-					if (lineChild.ignoreChars) {
-						nodeLength -= lineChild.ignoreChars;
-					}
-					if (lineOffset + nodeLength > offset) {
-						range = document.body.createTextRange();
-						if (offset === lineOffset && direction < 0) {
-							range.moveToElementText(lineChild.previousSibling);
-						} else {
-							range.moveToElementText(lineChild);
-							range.collapse();
-							range.moveEnd("character", offset - lineOffset);
-						}
-						length = range.text.length;
-						range.moveEnd(unit, direction);
-						result = offset + range.text.length - length;
-						break;
-					}
-					lineOffset = nodeLength + lineOffset;
-					lineChild = lineChild.nextSibling;
-				}
-			}
-			if (dummy) { clientDiv.removeChild(dummy); }
-			return result;
-		},
-		_getOffsetToX: function (offset) {
-			return this._getBoundsAtOffset(offset).left;
-		},
-		_getPadding: function (node) {
-			var left,top,right,bottom;
-			if (node.currentStyle) {
-				left = node.currentStyle.paddingLeft;
-				top = node.currentStyle.paddingTop;
-				right = node.currentStyle.paddingRight;
-				bottom = node.currentStyle.paddingBottom;
-			} else if (this._frameWindow.getComputedStyle) {
-				var style = this._frameWindow.getComputedStyle(node, null);
-				left = style.getPropertyValue("padding-left");
-				top = style.getPropertyValue("padding-top");
-				right = style.getPropertyValue("padding-right");
-				bottom = style.getPropertyValue("padding-bottom");
-			}
-			return {
-					left: parseInt(left, 10), 
-					top: parseInt(top, 10),
-					right: parseInt(right, 10),
-					bottom: parseInt(bottom, 10)
-			};
-		},
-		_getScroll: function() {
-			var viewDiv = this._viewDiv;
-			return {x: viewDiv.scrollLeft, y: viewDiv.scrollTop};
-		},
-		_getSelection: function () {
-			return this._selection.clone();
-		},
-		_getTopIndex: function (fullyVisible) {
-			var child = this._topChild;
-			if (fullyVisible && this._getClientHeight() > this._getLineHeight()) {
-				var rect = child.getBoundingClientRect();
-				var viewPad = this._getViewPadding();
-				var viewRect = this._viewDiv.getBoundingClientRect();
-				if (rect.top < viewRect.top + viewPad.top) {
-					child = this._getLineNext(child) || child;
-				}
-			}
-			return child.lineIndex;
-		},
-		_getXToOffset: function (lineIndex, x) {
-			var model = this._model;
-			var lineStart = model.getLineStart(lineIndex);
-			var lineEnd = model.getLineEnd(lineIndex);
-			if (lineStart === lineEnd) {
-				return lineStart;
-			}
-			var document = this._frameDocument;
-			var clientDiv = this._clientDiv;
-			var dummy;
-			var child = this._getLineNode(lineIndex);
-			if (!child) {
-				child = dummy = this._createLine(clientDiv, null, document, lineIndex, model);
-			}
-			var lineRect = this._getLineBoundingClientRect(child);
-			if (x < lineRect.left) { x = lineRect.left; }
-			if (x > lineRect.right) { x = lineRect.right; }
-			/*
-			* Bug in IE 8 and earlier. The coordinates of getClientRects() are relative to
-			* the browser window.  The fix is to convert to the frame window before using it. 
-			*/
-			var deltaX = 0, rects;
-			if (isIE < 9) {
-				rects = child.getClientRects();
-				var minLeft = rects[0].left;
-				for (var i=1; i<rects.length; i++) {
-					minLeft = Math.min(rects[i].left, minLeft);
-				}
-				deltaX = minLeft - lineRect.left;
-			}
-			var scrollX = this._getScroll().x;
-			function _getClientRects(element) {
-				var rects, newRects, i, r;
-				if (!element._rectsCache) {
-					rects = element.getClientRects();
-					newRects = [rects.length];
-					for (i = 0; i<rects.length; i++) {
-						r = rects[i];
-						newRects[i] = {left: r.left - deltaX + scrollX, top: r.top, right: r.right - deltaX + scrollX, bottom: r.bottom};
-					}
-					element._rectsCache = newRects; 
-				}
-				rects = element._rectsCache;
-				newRects = [rects.length];
-				for (i = 0; i<rects.length; i++) {
-					r = rects[i];
-					newRects[i] = {left: r.left - scrollX, top: r.top, right: r.right - scrollX, bottom: r.bottom};
-				}
-				return newRects;
-			}
-			var logicalXDPI = isIE ? window.screen.logicalXDPI : 1;
-			var deviceXDPI = isIE ? window.screen.deviceXDPI : 1;
-			var offset = lineStart;
-			var lineChild = child.firstChild;
-			done:
-			while (lineChild) {
-				var textNode = lineChild.firstChild;
-				var nodeLength = textNode.length;
-				if (lineChild.ignoreChars) {
-					nodeLength -= lineChild.ignoreChars;
-				}
-				rects = _getClientRects(lineChild);
-				for (var j = 0; j < rects.length; j++) {
-					var rect = rects[j];
-					if (rect.left <= x && x < rect.right) {
-						var range, start, end;
-						if (isIE || isRangeRects) {
-							range = isRangeRects ? document.createRange() : document.body.createTextRange();
-							var high = nodeLength;
-							var low = -1;
-							while ((high - low) > 1) {
-								var mid = Math.floor((high + low) / 2);
-								start = low + 1;
-								end = mid === nodeLength - 1 && lineChild.ignoreChars ? textNode.length : mid + 1;
-								if (isRangeRects) {
-									range.setStart(textNode, start);
-									range.setEnd(textNode, end);
-								} else {
-									range.moveToElementText(lineChild);
-									range.move("character", start);
-									range.moveEnd("character", end - start);
-								}
-								rects = range.getClientRects();
-								var found = false;
-								for (var k = 0; k < rects.length; k++) {
-									rect = rects[k];
-									var rangeLeft = rect.left * logicalXDPI / deviceXDPI - deltaX;
-									var rangeRight = rect.right * logicalXDPI / deviceXDPI - deltaX;
-									if (rangeLeft <= x && x < rangeRight) {
-										found = true;
-										break;
-									}
-								}
-								if (found) {
-									high = mid;
-								} else {
-									low = mid;
-								}
-							}
-							offset += high;
-							start = high;
-							end = high === nodeLength - 1 && lineChild.ignoreChars ? textNode.length : Math.min(high + 1, textNode.length);
-							if (isRangeRects) {
-								range.setStart(textNode, start);
-								range.setEnd(textNode, end);
-							} else {
-								range.moveToElementText(lineChild);
-								range.move("character", start);
-								range.moveEnd("character", end - start);
-							}
-							rect = range.getClientRects()[0];
-							//TODO test for character trailing (wrong for bidi)
-							if (x > ((rect.left * logicalXDPI / deviceXDPI - deltaX) + ((rect.right - rect.left) * logicalXDPI / deviceXDPI / 2))) {
-								offset++;
-							}
-						} else {
-							var newText = [];
-							for (var q = 0; q < nodeLength; q++) {
-								newText.push("<span>");
-								if (q === nodeLength - 1) {
-									newText.push(textNode.data.substring(q));
-								} else {
-									newText.push(textNode.data.substring(q, q + 1));
-								}
-								newText.push("</span>");
-							}
-							lineChild.innerHTML = newText.join("");
-							var rangeChild = lineChild.firstChild;
-							while (rangeChild) {
-								rect = rangeChild.getBoundingClientRect();
-								if (rect.left <= x && x < rect.right) {
-									//TODO test for character trailing (wrong for bidi)
-									if (x > rect.left + (rect.right - rect.left) / 2) {
-										offset++;
-									}
-									break;
-								}
-								offset++;
-								rangeChild = rangeChild.nextSibling;
-							}
-							if (!dummy) {
-								lineChild.innerHTML = "";
-								lineChild.appendChild(textNode);
-								/*
-								 * Removing the element node that holds the selection start or end
-								 * causes the selection to be lost. The fix is to detect this case
-								 * and restore the selection. 
-								 */
-								var s = this._getSelection();
-								if ((offset <= s.start && s.start < offset + nodeLength) || (offset <= s.end && s.end < offset + nodeLength)) {
-									this._updateDOMSelection();
-								}
-							}
-						}
-						break done;
-					}
-				}
-				offset += nodeLength;
-				lineChild = lineChild.nextSibling;
-			}
-			if (dummy) { clientDiv.removeChild(dummy); }
-			return Math.min(lineEnd, Math.max(lineStart, offset));
-		},
-		_getYToLine: function (y) {
-			var viewPad = this._getViewPadding();
-			var viewRect = this._viewDiv.getBoundingClientRect();
-			y -= viewRect.top + viewPad.top;
-			var lineHeight = this._getLineHeight();
-			var lineIndex = Math.floor((y + this._getScroll().y) / lineHeight);
-			var lineCount = this._model.getLineCount();
-			return Math.max(0, Math.min(lineCount - 1, lineIndex));
-		},
-		_getOffsetBounds: function(offset) {
-			var model = this._model;
-			var lineIndex = model.getLineAtOffset(offset);
-			var lineHeight = this._getLineHeight();
-			var scroll = this._getScroll();
-			var viewPad = this._getViewPadding();
-			var viewRect = this._viewDiv.getBoundingClientRect();
-			var bounds = this._getBoundsAtOffset(offset);
-			var left = bounds.left;
-			var right = bounds.right;
-			var top = (lineIndex * lineHeight) - scroll.y + viewRect.top + viewPad.top;
-			var bottom = top + lineHeight;
-			return {left: left, top: top, right: right, bottom: bottom};
-		},
-		_getVisible: function() {
-			var temp = this._parent;
-			var parentDocument = temp.ownerDocument;
-			while (temp !== parentDocument) {
-				var hidden;
-				if (isIE < 9) {
-					hidden = temp.currentStyle && temp.currentStyle.display === "none";
-				} else {
-					var tempStyle = parentDocument.defaultView.getComputedStyle(temp, null);
-					hidden = tempStyle && tempStyle.getPropertyValue("display") === "none";
-				}
-				if (hidden) { return "hidden"; }
-				temp =  temp.parentNode;
-				if (!temp) { return "disconnected"; }
-			}
-			return "visible";
-		},
-		_hitOffset: function (offset, x, y) {
-			var bounds = this._getOffsetBounds(offset);
-			var left = bounds.left;
-			var right = bounds.right;
-			var top = bounds.top;
-			var bottom = bounds.bottom;
-			var area = 20;
-			left -= area;
-			top -= area;
-			right += area;
-			bottom += area;
-			return (left <= x && x <= right && top <= y && y <= bottom);
-		},
-		_hookEvents: function() {
-			var self = this;
-			this._modelListener = {
-				/** @private */
-				onChanging: function(modelChangingEvent) {
-					self._onModelChanging(modelChangingEvent);
-				},
-				/** @private */
-				onChanged: function(modelChangedEvent) {
-					self._onModelChanged(modelChangedEvent);
-				}
-			};
-			this._model.addEventListener("Changing", this._modelListener.onChanging);
-			this._model.addEventListener("Changed", this._modelListener.onChanged);
-			
-			var clientDiv = this._clientDiv;
-			var viewDiv = this._viewDiv;
-			var body = this._frameDocument.body; 
-			var handlers = this._handlers = [];