15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// CodeMirror is the only global var we claim
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)window.CodeMirror = (function() {
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  "use strict";
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // BROWSER SNIFFING
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Crude, but necessary to handle a number of hard-to-feature-detect
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // bugs and behavior differences.
9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var gecko = /gecko\/\d/i.test(navigator.userAgent);
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var ie = /MSIE \d/.test(navigator.userAgent);
11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var webkit = /WebKit\//.test(navigator.userAgent);
14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var chrome = /Chrome\//.test(navigator.userAgent);
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var opera = /Opera\//.test(navigator.userAgent);
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var safari = /Apple Computer/.test(navigator.vendor);
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var khtml = /KHTML\//.test(navigator.userAgent);
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var phantom = /PhantomJS/.test(navigator.userAgent);
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // This is woefully incomplete. Suggestions for alternative methods welcome.
25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var mac = ios || /Mac/.test(navigator.platform);
27926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var windows = /windows/i.test(navigator.platform);
28926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
29926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
30926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  if (opera_version) opera_version = Number(opera_version[1]);
31f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
32926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
33926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
34926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var captureMiddleClick = gecko || (ie && !ie_lt9);
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Optimize some code when these features are not used
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var sawReadOnlySpans = false, sawCollapsedSpans = false;
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // CONSTRUCTOR
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function CodeMirror(place, options) {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.options = options = options || {};
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Determine effective options based on given values and defaults.
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      options[opt] = defaults[opt];
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setGuttersForLineNumbers(options);
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var docStart = typeof options.value == "string" ? 0 : options.value.first;
51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var display = this.display = makeDisplay(place, docStart);
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.wrapper.CodeMirror = this;
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateGutters(this);
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (options.autofocus && !mobile) focusInput(this);
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.state = {keyMaps: [],
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  overlays: [],
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  modeGen: 0,
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  overwrite: false, focused: false,
60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  suppressEdits: false, pasteIncoming: false,
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  draggingText: false,
62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  highlight: new Delayed()};
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    themeChanged(this);
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (options.lineWrapping)
66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.display.wrapper.className += " CodeMirror-wrap";
67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = options.value;
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof doc == "string") doc = new Doc(options.value, options.mode);
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    operation(this, attachDoc)(this, doc);
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Override magic textarea content restore that IE sometimes does
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // on our hidden textarea on reload
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ie) setTimeout(bind(resetInput, this, true), 20);
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    registerEventHandlers(this);
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // IE throws unspecified error in certain cases, when
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // trying to access activeElement before onload
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else onBlur(this);
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    operation(this, function() {
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var opt in optionHandlers)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (optionHandlers.propertyIsEnumerable(opt))
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          optionHandlers[opt](this, options[opt], Init);
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    })();
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // DISPLAY CONSTRUCTOR
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function makeDisplay(place, docStart) {
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var d = {};
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
9653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (webkit) input.style.width = "1000px";
98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else input.setAttribute("wrap", "off");
99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // if border: 0; -- iOS fails to open keyboard (issue #1287)
100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (ios) input.style.border = "1px solid black";
10193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Wraps and hides input textarea
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The actual fake scrollbars.
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
10993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // DIVs containing the selection and the actual code
11193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    d.lineDiv = elt("div", null, "CodeMirror-code");
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Blinky cursor, and element used to ensure cursor fits at the end of a line
114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Secondary cursor, shown when on a 'jump' in bi-directional text
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Used to measure text size
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.measure = elt("div", null, "CodeMirror-measure");
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Wraps everything that needs to exist inside the vertically-padded coordinate system
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         null, "position: relative; outline: none");
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Moved around its parent to cover visible view
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Set to the height of the text, causes scrolling
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Will contain the gutters, if any
129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.gutters = elt("div", null, "CodeMirror-gutters");
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.lineGutter = null;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Provides scrolling
13293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.scroller.setAttribute("tabIndex", "-1");
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The element in which the editor lives.
135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
13693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                            d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Work around IE7 z-index bug
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Needed to hide big blue blinking cursor on Mobile Safari
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ios) input.style.width = "0px";
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!webkit) d.scroller.draggable = true;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Needed to handle Tab key in KHTML
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Current visible range (may be bigger than the view window).
150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.viewOffset = d.lastSizeC = 0;
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.showingFrom = d.showingTo = docStart;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Used to only resize the line number gutter when necessary (when
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the amount of lines crosses a boundary that makes its width change)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // See readInput and resetInput
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.prevInput = "";
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Set to true when a non-horizontal-scrolling widget is added. As
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // an optimization, widget aligning is skipped when d is false.
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.alignWidgets = false;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Flag that indicates whether we currently expect input to appear
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // (after some event like 'keypress' or 'input') and are polling
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // intensively.
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.pollingFast = false;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Self-resetting timeout for the poller
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.poll = new Delayed();
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.cachedCharWidth = d.cachedTextHeight = null;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.measureLineCache = [];
170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.measureLineCachePos = 0;
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Tracks when resetInput has punted to just putting a short
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // string instead of the (large) selection.
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    d.inaccurateSelection = false;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Tracks the maximum line length so that the horizontal scrollbar
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // can be kept static when scrolling.
178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.maxLine = null;
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.maxLineLength = 0;
180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.maxLineChanged = false;
181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Used for measuring wheel scrolling granularity
183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return d;
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // STATE UPDATES
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Used to get the editor into a consistent state again when options change.
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function loadMode(cm) {
193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.iter(function(line) {
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (line.stateAfter) line.stateAfter = null;
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (line.styles) line.styles = null;
197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.frontier = cm.doc.first;
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startWorker(cm, 100);
200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.state.modeGen++;
201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.curOp) regChange(cm);
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function wrappingChanged(cm) {
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.options.lineWrapping) {
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      cm.display.wrapper.className += " CodeMirror-wrap";
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      cm.display.sizer.style.minWidth = "";
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      computeMaxLength(cm);
211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    estimateLineHeights(cm);
213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    regChange(cm);
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clearCaches(cm);
21593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    setTimeout(function(){updateScrollbars(cm);}, 100);
216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function estimateHeight(cm) {
219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return function(line) {
222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (lineIsHidden(cm.doc, line))
223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else if (wrapping)
225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return (Math.ceil(line.text.length / perLine) || 1) * th;
226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else
227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return th;
228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function estimateLineHeights(cm) {
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc, est = estimateHeight(cm);
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.iter(function(line) {
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var estHeight = est(line);
235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (estHeight != line.height) updateLineHeight(line, estHeight);
236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function keyMapChanged(cm) {
2405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var map = keyMap[cm.options.keyMap], style = map.style;
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      (style ? " cm-keymap-" + style : "");
2435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    cm.state.disableInput = map.disableInput;
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function themeChanged(cm) {
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clearCaches(cm);
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function guttersChanged(cm) {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateGutters(cm);
254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    regChange(cm);
25593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    setTimeout(function(){alignHorizontally(cm);}, 20);
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function updateGutters(cm) {
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var gutters = cm.display.gutters, specs = cm.options.gutters;
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeChildren(gutters);
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < specs.length; ++i) {
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var gutterClass = specs[i];
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (gutterClass == "CodeMirror-linenumbers") {
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cm.display.lineGutter = gElt;
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    gutters.style.display = i ? "" : "none";
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function lineLength(doc, line) {
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (line.height == 0) return 0;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var len = line.text.length, merged, cur = line;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (merged = collapsedSpanAtStart(cur)) {
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var found = merged.find();
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      cur = getLine(doc, found.from.line);
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      len += found.from.ch - found.to.ch;
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cur = line;
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (merged = collapsedSpanAtEnd(cur)) {
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var found = merged.find();
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      len -= cur.text.length - found.from.ch;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      cur = getLine(doc, found.to.line);
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      len += cur.text.length - found.to.ch;
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return len;
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function computeMaxLength(cm) {
291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var d = cm.display, doc = cm.doc;
292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.maxLine = getLine(doc, doc.first);
293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.maxLineLength = lineLength(doc, d.maxLine);
294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.maxLineChanged = true;
295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.iter(function(line) {
296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var len = lineLength(doc, line);
297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (len > d.maxLineLength) {
298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        d.maxLineLength = len;
299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        d.maxLine = line;
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Make sure the gutters options contains the element
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // "CodeMirror-linenumbers" when the lineNumbers option is true.
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function setGuttersForLineNumbers(options) {
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var found = false;
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < options.gutters.length; ++i) {
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (options.gutters[i] == "CodeMirror-linenumbers") {
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (options.lineNumbers) found = true;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else options.gutters.splice(i--, 1);
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!found && options.lineNumbers)
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      options.gutters.push("CodeMirror-linenumbers");
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // SCROLLBARS
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Re-synchronize the fake scrollbars with the actual size of the
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // content. Optionally force a scrollTop.
32293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  function updateScrollbars(cm) {
32393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var d = cm.display, docHeight = cm.doc.height;
324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var totalHeight = docHeight + paddingVert(d);
325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
32693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
3285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
3295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var needsV = scrollHeight > (d.scroller.clientHeight + 1);
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (needsV) {
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarV.style.display = "block";
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      d.scrollbarV.firstChild.style.height =
334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else d.scrollbarV.style.display = "";
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (needsH) {
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarH.style.display = "block";
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarH.firstChild.style.width =
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else d.scrollbarH.style.display = "";
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (needsH && needsV) {
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarFiller.style.display = "block";
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else d.scrollbarFiller.style.display = "";
34693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
34793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      d.gutterFiller.style.display = "block";
34893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
34993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
35093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    } else d.gutterFiller.style.display = "";
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mac_geLion && scrollbarWidth(d.measure) === 0)
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function visibleLines(display, doc, viewPort) {
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof viewPort == "number") top = viewPort;
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    top = Math.floor(top - paddingTop(display));
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var bottom = Math.ceil(top + height);
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // LINE NUMBERS
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function alignHorizontally(cm) {
368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var display = cm.display;
369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var gutterW = display.gutters.offsetWidth, l = comp + "px";
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.options.fixedGutter)
376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.gutters.style.left = (comp + gutterW) + "px";
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function maybeUpdateLineNumberWidth(cm) {
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!cm.options.lineNumbers) return false;
381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (last.length != display.lineNumChars) {
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var test = display.measure.appendChild(elt("div", [elt("div", last)],
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                 "CodeMirror-linenumber CodeMirror-gutter-elt"));
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.lineGutter.style.width = "";
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.lineNumWidth = display.lineNumInnerWidth + padding;
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.lineGutter.style.width = display.lineNumWidth + "px";
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return true;
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function lineNumberFor(options, i) {
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return String(options.lineNumberFormatter(i + options.firstLineNumber));
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function compensateForHScroll(display) {
400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return getRect(display.scroller).left - getRect(display.sizer).left;
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // DISPLAY DRAWING
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
405f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  function updateDisplay(cm, changes, viewPort, forced) {
40653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
40753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    var visible = visibleLines(cm.display, cm.doc, viewPort);
40853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    for (;;) {
409f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      if (!updateDisplayInner(cm, changes, visible, forced)) break;
410f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      forced = false;
41193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      updated = true;
41253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      updateSelection(cm);
41393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      updateScrollbars(cm);
41453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
41553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      // Clip forced viewport to actual scrollable area
41653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (viewPort)
41753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
41853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                            typeof viewPort == "number" ? viewPort : viewPort.top);
41953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      visible = visibleLines(cm.display, cm.doc, viewPort);
42053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
42153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
42253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      changes = [];
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
42593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (updated) {
42693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      signalLater(cm, "update", cm);
42793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
42893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
42993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return updated;
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Uses a set of changes plus the current scroll position to
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // determine which DOM updates have to be made, and makes the
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // updates.
436f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  function updateDisplayInner(cm, changes, visible, forced) {
437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var display = cm.display, doc = cm.doc;
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!display.wrapper.clientWidth) {
439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.showingFrom = display.showingTo = doc.first;
440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.viewOffset = 0;
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Bail out if the visible area is already rendered and nothing changed.
445f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (!forced && changes.length == 0 &&
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visible.from > display.showingFrom && visible.to < display.showingTo)
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (maybeUpdateLineNumberWidth(cm))
450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      changes = [{from: doc.first, to: doc.first + doc.size}];
451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Used to determine which lines need their line numbers updated
455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var positionsChangedFrom = Infinity;
456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.options.lineNumbers)
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < changes.length; ++i)
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var end = doc.first + doc.size;
461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var to = Math.min(end, visible.to + cm.options.viewportMargin);
463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (sawCollapsedSpans) {
466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      from = lineNo(visualLine(doc, getLine(doc, from)));
467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Create a range of theoretically intact lines, and punch holes
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // in that using the change info.
472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var intact = [{from: Math.max(display.showingFrom, doc.first),
473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                   to: Math.min(display.showingTo, end)}];
474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (intact[0].from >= intact[0].to) intact = [];
475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else intact = computeIntact(intact, changes);
476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // When merged lines are present, we might have to reduce the
477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // intact ranges because changes in continued fragments of the
478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // intact lines do require the lines to be redrawn.
479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (sawCollapsedSpans)
480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0; i < intact.length; ++i) {
481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var range = intact[i], merged;
482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var newTo = merged.find().from.line;
484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (newTo > range.from) range.to = newTo;
485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          else { intact.splice(i--, 1); break; }
486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Clip off the parts that won't be visible
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var intactLines = 0;
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < intact.length; ++i) {
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var range = intact[i];
493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (range.from < from) range.from = from;
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (range.to > to) range.to = to;
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (range.from >= range.to) intact.splice(i--, 1);
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else intactLines += range.to - range.from;
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
498f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateViewOffset(cm);
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    intact.sort(function(a, b) {return a.from - b.from;});
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // Avoid crashing on IE's "unspecified error" when in iframes
50553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    try {
50653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var focused = document.activeElement;
50753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    } catch(e) {}
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    patchDisplay(cm, from, to, intact, positionsChangedFrom);
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.lineDiv.style.display = "";
51153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var different = from != display.showingFrom || to != display.showingTo ||
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.lastSizeC != display.wrapper.clientHeight;
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is just a bogus formula that detects when the editor is
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // resized or the font size changes.
5175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (different) {
5185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      display.lastSizeC = display.wrapper.clientHeight;
5195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      startWorker(cm, 400);
5205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.showingFrom = from; display.showingTo = to;
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
523f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    updateHeightsInViewport(cm);
524f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    updateViewOffset(cm);
525f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
526f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return true;
527f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  }
528f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
529f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  function updateHeightsInViewport(cm) {
530f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    var display = cm.display;
531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var prevBottom = display.lineDiv.offsetTop;
532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (ie_lt8) {
534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var bot = node.offsetTop + node.offsetHeight;
535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        height = bot - prevBottom;
536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        prevBottom = bot;
537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else {
538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var box = getRect(node);
539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        height = box.bottom - box.top;
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var diff = node.lineObj.height - height;
542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (height < 2) height = textHeight(display);
543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (diff > .001 || diff < -.001) {
544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        updateLineHeight(node.lineObj, height);
545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var widgets = node.lineObj.widgets;
546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (widgets) for (var i = 0; i < widgets.length; ++i)
547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          widgets[i].height = widgets[i].node.offsetHeight;
548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function updateViewOffset(cm) {
553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Position the mover div to align with the current virtual scroll position
555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.display.mover.style.top = off + "px";
556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function computeIntact(intact, changes) {
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0, l = changes.length || 0; i < l; ++i) {
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var change = changes[i], intact2 = [], diff = change.diff || 0;
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var j = 0, l2 = intact.length; j < l2; ++j) {
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var range = intact[j];
563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (change.to <= range.from && change.diff) {
564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          intact2.push({from: range.from + diff, to: range.to + diff});
565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else if (change.to <= range.from || change.from >= range.to) {
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          intact2.push(range);
567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else {
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (change.from > range.from)
569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            intact2.push({from: range.from, to: change.from});
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (change.to < range.to)
571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            intact2.push({from: change.to + diff, to: range.to + diff});
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      intact = intact2;
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return intact;
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function getDimensions(cm) {
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var d = cm.display, left = {}, width = {};
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      left[cm.options.gutters[i]] = n.offsetLeft;
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      width[cm.options.gutters[i]] = n.offsetWidth;
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return {fixedPos: compensateForHScroll(d),
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gutterTotalWidth: d.gutters.offsetWidth,
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gutterLeft: left,
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gutterWidth: width,
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            wrapperWidth: d.wrapper.clientWidth};
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var dims = getDimensions(cm);
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var display = cm.display, lineNumbers = cm.options.lineNumbers;
595926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      removeChildren(display.lineDiv);
597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var container = display.lineDiv, cur = container.firstChild;
598926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function rm(node) {
600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var next = node.nextSibling;
601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (webkit && mac && cm.display.currentWheelTarget == node) {
602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        node.style.display = "none";
603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        node.lineObj = null;
604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else {
605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        node.parentNode.removeChild(node);
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return next;
608926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
609926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var nextIntact = intact.shift(), lineN = from;
611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.iter(from, to, function(line) {
612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (lineIsHidden(cm.doc, line)) {
614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (line.height != 0) updateLineHeight(line, 0);
6155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
6165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)          var w = line.widgets[i];
6175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)          if (w.showIfHidden) {
618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var prev = cur.previousSibling;
619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (/pre/i.test(prev.nodeName)) {
620926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              var wrap = elt("div", null, null, "position: relative");
621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              prev.parentNode.replaceChild(wrap, prev);
622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              wrap.appendChild(prev);
623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              prev = wrap;
624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
6255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
6265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            if (!w.handleMouseEvents) wnode.ignoreEvents = true;
6275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            positionLineWidget(w, wnode, prev, dims);
628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          }
6295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        }
630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
631926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // This line is intact. Skip to the actual node. Update its
632926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // line number if needed.
633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        while (cur.lineObj != line) cur = rm(cur);
634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
635926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
636926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cur = cur.nextSibling;
637926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else {
638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // For lines with widgets, make an attempt to find and reuse
639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // the existing element, so that widgets aren't needlessly
640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // removed and re-inserted into the dom
641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // This line needs to be generated.
644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (lineNode != reuse) {
646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          container.insertBefore(lineNode, cur);
647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else {
648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          while (cur != reuse) cur = rm(cur);
649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          cur = cur.nextSibling;
650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
652926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lineNode.lineObj = line;
653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      ++lineN;
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (cur) cur = rm(cur);
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function buildLineElement(cm, line, lineNo, dims, reuse) {
660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lineElement = lineContent(cm, line);
661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var markers = line.gutterMarkers, display = cm.display, wrap;
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return lineElement;
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Lines with gutter elements, widgets or a background class need
667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // to be wrapped again, and have the extra elements added to the
668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // wrapper div
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (reuse) {
671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      reuse.alignable = null;
6725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      var isOk = true, widgetsSeen = 0, insertBefore = null;
673926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var n = reuse.firstChild, next; n; n = next) {
674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        next = n.nextSibling;
675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
676926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          reuse.removeChild(n);
677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else {
678e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          for (var i = 0; i < line.widgets.length; ++i) {
6795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            var widget = line.widgets[i];
680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (widget.node == n.firstChild) {
681e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch              if (!widget.above && !insertBefore) insertBefore = n;
682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              positionLineWidget(widget, n, reuse, dims);
683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              ++widgetsSeen;
684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              break;
685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          }
687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (i == line.widgets.length) { isOk = false; break; }
688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
6905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      reuse.insertBefore(lineElement, insertBefore);
691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (isOk && widgetsSeen == line.widgets.length) {
692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        wrap = reuse;
693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        reuse.className = line.wrapClass || "";
694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!wrap) {
697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      wrap = elt("div", null, line.wrapClass, "position: relative");
698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      wrap.appendChild(lineElement);
699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Kludge to make sure the styled element lies behind the selection (by z-index)
701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (line.bgClass)
702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.options.lineNumbers || markers) {
704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                         wrap.firstChild);
707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
709926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        wrap.lineNumber = gutterWrap.appendChild(
710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          elt("div", lineNumberFor(cm.options, lineNo),
711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              "CodeMirror-linenumber CodeMirror-gutter-elt",
712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              + display.lineNumInnerWidth + "px"));
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (markers)
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var k = 0; k < cm.options.gutters.length; ++k) {
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (found)
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                       dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ie_lt8) wrap.style.zIndex = 2;
723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
7255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (!widget.handleMouseEvents) node.ignoreEvents = true;
726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      positionLineWidget(widget, node, wrap, dims);
727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (widget.above)
728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else
730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        wrap.appendChild(node);
731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      signalLater(widget, "redraw");
732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return wrap;
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function positionLineWidget(widget, node, wrap, dims) {
737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (widget.noHScroll) {
738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      (wrap.alignable || (wrap.alignable = [])).push(node);
739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var width = dims.wrapperWidth;
740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      node.style.left = dims.fixedPos + "px";
741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!widget.coverGutter) {
742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        width -= dims.gutterTotalWidth;
743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        node.style.paddingLeft = dims.gutterTotalWidth + "px";
744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      node.style.width = width + "px";
746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (widget.coverGutter) {
748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      node.style.zIndex = 5;
749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      node.style.position = "relative";
750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // SELECTION / CURSOR
755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function updateSelection(cm) {
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var display = cm.display;
758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (collapsed || cm.options.showCursorWhenSelecting)
760926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateSelectionCursor(cm);
761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.cursor.style.display = display.otherCursor.style.display = "none";
763926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!collapsed)
764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateSelectionRange(cm);
765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.selectionDiv.style.display = "none";
767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Move the hidden textarea near the cursor to prevent scrolling artifacts
76953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (cm.options.moveInputWithCursor) {
77053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
77153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
77253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
77353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                                                        headPos.top + lineOff.top - wrapOff.top)) + "px";
77453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
77553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                                                         headPos.left + lineOff.left - wrapOff.left)) + "px";
77653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // No selection, plain cursor
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function updateSelectionCursor(cm) {
781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.cursor.style.left = pos.left + "px";
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.cursor.style.top = pos.top + "px";
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.cursor.style.display = "";
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pos.other) {
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.otherCursor.style.display = "";
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.otherCursor.style.left = pos.other.left + "px";
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.otherCursor.style.top = pos.other.top + "px";
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else { display.otherCursor.style.display = "none"; }
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Highlight selection
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function updateSelectionRange(cm) {
797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var fragment = document.createDocumentFragment();
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function add(left, top, width, bottom) {
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (top < 0) top = 0;
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                               "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                               "px; height: " + (bottom - top) + "px"));
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
808591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    function drawForLine(line, fromArg, toArg) {
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var lineObj = getLine(doc, line);
810591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var lineLen = lineObj.text.length;
811591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var start, end;
8125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      function coords(ch, bias) {
8135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
8175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var leftPos = coords(from, "left"), rightPos, left, right;
81853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (from == to) {
81953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)          rightPos = leftPos;
82053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)          left = right = leftPos.left;
82153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        } else {
8225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)          rightPos = coords(to - 1, "right");
82353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)          if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
82453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)          left = leftPos.left;
82553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)          right = rightPos.right;
82653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        }
827591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (fromArg == null && from == 0) left = pl;
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          add(left, leftPos.top, null, leftPos.bottom);
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          left = pl;
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (toArg == null && to == lineLen) right = clientWidth;
834591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
835591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          start = leftPos;
836591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
837591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          end = rightPos;
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (left < pl + 1) left = pl;
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        add(left, rightPos.top, right - left, rightPos.bottom);
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
841591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      return {start: start, end: end};
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (sel.from.line == sel.to.line) {
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
847591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
848591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
849591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
850591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
851591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (singleVLine) {
852591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (leftEnd.top < rightStart.top - 2) {
853591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
854591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          add(pl, rightStart.top, rightStart.left, rightStart.bottom);
855591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        } else {
856591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
859591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (leftEnd.bottom < rightStart.top)
860591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        add(pl, leftEnd.bottom, null, rightStart.top);
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeChildrenAndAdd(display.selectionDiv, fragment);
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.selectionDiv.style.display = "";
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Cursor-blinking
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function restartBlink(cm) {
86953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!cm.state.focused) return;
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var display = cm.display;
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearInterval(display.blinker);
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var on = true;
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.cursor.style.visibility = display.otherCursor.style.visibility = "";
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.blinker = setInterval(function() {
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }, cm.options.cursorBlinkRate);
8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // HIGHLIGHT WORKER
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function startWorker(cm, time) {
882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.state.highlight.set(time, bind(highlightWorker, cm));
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function highlightWorker(cm) {
887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc;
888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.frontier < doc.first) doc.frontier = doc.first;
889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.frontier >= cm.display.showingTo) return;
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var end = +new Date + cm.options.workTime;
891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var changed = [], prevChange;
893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (doc.frontier >= cm.display.showingFrom) { // Visible
895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var oldStyles = line.styles;
896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        line.styles = highlightLine(cm, line, state);
897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var ischange = !oldStyles || oldStyles.length != line.styles.length;
898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (ischange) {
900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        line.stateAfter = copyState(doc.mode, state);
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        processLine(cm, line, state);
906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      ++doc.frontier;
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (+new Date > end) {
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startWorker(cm, cm.options.workDelay);
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (changed.length)
9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      operation(cm, function() {
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < changed.length; ++i)
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          regChange(this, changed[i].start, changed[i].end);
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      })();
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Finds the line to start with when starting a parse. Tries to
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // find a line with a stateAfter, so that it can start with a
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // valid state. If that fails, it returns the line with the
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // smallest indentation, which tends to need the least context to
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // parse correctly.
926591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  function findStartLine(cm, n, precise) {
927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var minindent, minline, doc = cm.doc;
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var search = n, lim = n - 100; search > lim; --search) {
929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (search <= doc.first) return doc.first;
930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var line = getLine(doc, search - 1);
931591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var indented = countColumn(line.text, null, cm.options.tabSize);
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (minline == null || minindent > indented) {
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        minline = search - 1;
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        minindent = indented;
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return minline;
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
941591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  function getStateBefore(cm, n, precise) {
942926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc, display = cm.display;
943926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!doc.mode.startState) return true;
944591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
945926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!state) state = startState(doc.mode);
946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else state = copyState(doc.mode, state);
947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.iter(pos, n, function(line) {
9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      processLine(cm, line, state);
949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      line.stateAfter = save ? copyState(doc.mode, state) : null;
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      ++pos;
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return state;
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // POSITION MEASUREMENT
957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function paddingTop(display) {return display.lineSpace.offsetTop;}
959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function paddingLeft(display) {
961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return e.offsetLeft;
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  function measureChar(cm, line, ch, data, bias) {
966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dir = -1;
967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    data = data || measureLine(cm, line);
968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
9695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var pos = ch;; pos += dir) {
970591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var r = data.get(pos);
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (r) break;
9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (dir < 0 && pos == 0) dir = 1;
9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
974e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    bias = pos > ch ? "left" : pos < ch ? "right" : bias;
975e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (bias == "left" && r.leftSide) r = r.leftSide;
976e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    else if (bias == "right" && r.rightSide) r = r.rightSide;
9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return {left: pos < ch ? r.right : r.left,
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            right: pos > ch ? r.left : r.right,
979e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            top: r.top,
980e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            bottom: r.bottom};
9815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function findCachedMeasurement(cm, line) {
984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cache = cm.display.measureLineCache;
9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < cache.length; ++i) {
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var memo = cache[i];
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          cm.display.scroller.clientWidth == memo.width &&
989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
99093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        return memo;
9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
99493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  function clearCachedMeasurement(cm, line) {
99593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var exists = findCachedMeasurement(cm, line);
99693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (exists) exists.text = exists.measure = exists.markedSpans = null;
99793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  }
99893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function measureLine(cm, line) {
1000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // First look in the cache
100193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var cached = findCachedMeasurement(cm, line);
100293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (cached) return cached.measure;
100393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
100493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    // Failing that, recompute and store result in cache
1005591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    var measure = measureLineInner(cm, line, 0, 10);
1006591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    measure.get = function(num) {
1007591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (this[num]) return this[num];
1008591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (num < 0 || num >= line.text.length) return null;
1009591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      measureLineInner(cm, line, Math.max(num - 50, 0), Math.min(num + 50, line.text.length), this);
1010591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      return this[num];
1011591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    };
101293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var cache = cm.display.measureLineCache;
101393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var memo = {text: line.text, width: cm.display.scroller.clientWidth,
101493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                markedSpans: line.markedSpans, measure: measure,
101593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
101693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
101793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    else cache.push(memo);
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return measure;
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1021591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  function measureLineInner(cm, line, from, to, oldMeasure) {
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var display = cm.display, measure = emptyArray(line.text.length);
1023f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    var pre = lineContent(cm, line, measure, true, from, to);
1024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1025926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // IE does not cache element positions of inline elements between
1026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // calls to getBoundingClientRect. This makes the loop below,
1027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // which gathers the positions of all the characters on the line,
1028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // do an amount of layout work quadratic to the number of
1029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // characters. When line wrapping is off, we try to improve things
1030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // by first subdividing the line into a bunch of inline blocks, so
1031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // that IE can reuse most of the layout information from caches
1032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // for those blocks. This does interfere with line wrapping, so it
1033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // doesn't work when wrapping is on, but in that case the
1034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // situation is slightly better, since IE does cache line-wrapping
1035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // information and only recomputes per-line.
1036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var fragment = document.createDocumentFragment();
1038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var chunk = 10, n = pre.childNodes.length;
1039926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
1040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var wrap = elt("div", null, null, "display: inline-block");
1041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var j = 0; j < chunk && n; ++j) {
1042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          wrap.appendChild(pre.firstChild);
1043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          --n;
1044926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
1045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        fragment.appendChild(wrap);
1046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
1047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      pre.appendChild(fragment);
1048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeChildrenAndAdd(display.measure, pre);
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var outer = getRect(display.lineDiv);
1053591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    var vranges = [], data = oldMeasure || emptyArray(line.text.length), maxBot = pre.offsetHeight;
1054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Work around an IE7/8 bug where it will sometimes have randomly
1055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // replaced our pre with a clone at this point.
1056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (ie_lt9 && display.measure.first != pre)
1057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      removeChildrenAndAdd(display.measure, pre);
1058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1059e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    function measureRect(rect) {
1060e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      var top = rect.top - outer.top, bot = rect.bottom - outer.top;
10615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (bot > maxBot) bot = maxBot;
10625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (top < 0) top = 0;
1063e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      for (var i = vranges.length - 2; i >= 0; i -= 2) {
1064e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var rtop = vranges[i], rbot = vranges[i+1];
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rtop > bot || rbot < top) continue;
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rtop <= top && rbot >= bot ||
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            top <= rtop && bot >= rbot ||
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1069e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          vranges[i] = Math.min(top, rtop);
1070e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          vranges[i+1] = Math.max(bot, rbot);
1071e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          break;
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
1074e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (i < 0) { i = vranges.length; vranges.push(top, bot); }
1075e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return {left: rect.left - outer.left,
1076e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch              right: rect.right - outer.left,
1077e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch              top: i, bottom: null};
1078e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
1079e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    function finishRect(rect) {
1080e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      rect.bottom = vranges[rect.top+1];
1081e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      rect.top = vranges[rect.top];
10825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
10835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
10845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1085e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      var node = cur, rect = null;
10865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      // A widget might wrap, needs special care
10875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1088591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1089e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var rects = node.getClientRects();
1090591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (rects.length > 1) {
1091e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          rect = data[i] = measureRect(rects[0]);
1092e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          rect.rightSide = measureRect(rects[rects.length - 1]);
10935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        }
1094591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      }
1095e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (!rect) rect = data[i] = measureRect(getRect(node));
1096e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1097e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1099591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (var i = 0, cur; i < data.length; ++i) if (measure[i] && (cur = data[i])) {
1100e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      finishRect(cur);
1101e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (cur.leftSide) finishRect(cur.leftSide);
1102e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (cur.rightSide) finishRect(cur.rightSide);
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return data;
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function measureLineWidth(cm, line) {
1108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var hasBadSpan = false;
1109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
1110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sp = line.markedSpans[i];
1111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cached = !hasBadSpan && findCachedMeasurement(cm, line);
11145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
1115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1116f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    var pre = lineContent(cm, line, null, true);
1117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeChildrenAndAdd(cm.display.measure, pre);
1119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return getRect(end).right - getRect(cm.display.lineDiv).left;
1120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
1121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function clearCaches(cm) {
1123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
1124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
112553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
1126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.display.lineNumChars = null;
1127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
1128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
11295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
11305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
11315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function intoCoordSystem(cm, lineObj, rect, context) {
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
1135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var size = widgetHeight(lineObj.widgets[i]);
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      rect.top += size; rect.bottom += size;
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (context == "line") return rect;
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!context) context = "local";
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var yOff = heightAtLine(cm, lineObj);
11415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (context == "local") yOff += paddingTop(cm.display);
11425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    else yOff -= cm.display.viewOffset;
11435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (context == "page" || context == "window") {
1144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var lOff = getRect(cm.display.lineSpace);
11455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
11465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      rect.left += xOff; rect.right += xOff;
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rect.top += yOff; rect.bottom += yOff;
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return rect;
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Context may be "window", "page", "div", or "local"/null
115453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // Result is in "div" coords
1155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function fromCoordSystem(cm, coords, context) {
1156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (context == "div") return coords;
1157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var left = coords.left, top = coords.top;
11585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    // First move into "page" coordinate system
1159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (context == "page") {
11605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      left -= pageScrollX();
11615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      top -= pageScrollY();
11625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    } else if (context == "local" || !context) {
11635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      var localBox = getRect(cm.display.sizer);
11645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      left += localBox.left;
11655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      top += localBox.top;
1166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
11675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lineSpaceBox = getRect(cm.display.lineSpace);
11695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
1171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
11725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  function charCoords(cm, pos, context, lineObj, bias) {
1173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!lineObj) lineObj = getLine(cm.doc, pos.line);
11745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function cursorCoords(cm, pos, context, lineObj, measurement) {
1178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    lineObj = lineObj || getLine(cm.doc, pos.line);
11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!measurement) measurement = measureLine(cm, lineObj);
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function get(ch, right) {
11815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (right) m.left = m.right; else m.right = m.left;
1183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return intoCoordSystem(cm, lineObj, m, context);
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
118593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    function getBidi(ch, partPos) {
118693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      var part = order[partPos], right = part.level % 2;
118793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
118893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        part = order[--partPos];
118993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
119093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        right = true;
119193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
119293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        part = order[++partPos];
119393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        ch = bidiLeft(part) - part.level % 2;
119493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        right = false;
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
119693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (right && ch == part.to && ch > part.from) return get(ch - 1);
119793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      return get(ch, right);
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
119993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var order = getOrder(lineObj), ch = pos.ch;
120093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (!order) return get(ch);
120193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var partPos = getBidiPartAt(order, ch);
120293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var val = getBidi(ch, partPos);
120393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (bidiOther != null) val.other = getBidi(ch, bidiOther);
120493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return val;
12055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1207591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  function PosWithInfo(line, ch, outside, xRel) {
1208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var pos = new Pos(line, ch);
1209591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    pos.xRel = xRel;
1210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (outside) pos.outside = true;
1211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return pos;
1212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
1213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Coords must be lineSpace-local
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function coordsChar(cm, x, y) {
1216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc;
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    y += cm.display.viewOffset;
1218591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
1219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (lineNo > last)
1221591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (x < 0) x = 0;
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (;;) {
12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var lineObj = getLine(doc, lineNo);
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var found = coordsCharInner(cm, lineObj, lineNo, x, y);
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var merged = collapsedSpanAtEnd(lineObj);
1228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var mergedPos = merged && merged.find();
1229591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
1230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lineNo = mergedPos.to.line;
12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else
12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return found;
12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function coordsCharInner(cm, lineObj, lineNo, x, y) {
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var innerOff = y - heightAtLine(cm, lineObj);
1238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var measurement = measureLine(cm, lineObj);
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function getX(ch) {
1242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            lineObj, measurement);
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      wrongLine = true;
1245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (innerOff > sp.bottom) return sp.left - adjust;
1246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else if (innerOff < sp.top) return sp.left + adjust;
12475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else wrongLine = false;
12485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return sp.left;
12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var bidi = getOrder(lineObj), dist = lineObj.text.length;
1252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var from = lineLeft(lineObj), to = lineRight(lineObj);
1253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1255591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
12565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do a binary search between these bounds.
12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (;;) {
12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1259591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var ch = x < fromX || x - fromX <= toX - x ? from : to;
1260591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var xDiff = x - (ch == from ? fromX : toX);
12615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1262591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1263591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                              xDiff < 0 ? -1 : xDiff ? 1 : 0);
1264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return pos;
12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var step = Math.ceil(dist / 2), middle = from + step;
12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (bidi) {
12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        middle = from;
12695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
12705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var middleX = getX(middle);
127253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
127353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
12745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var measureText;
12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function textHeight(display) {
12795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (display.cachedTextHeight != null) return display.cachedTextHeight;
12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (measureText == null) {
12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      measureText = elt("pre");
12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Measure a bunch of lines, for browsers that compute
12835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // fractional heights.
12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < 49; ++i) {
12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        measureText.appendChild(document.createTextNode("x"));
12865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        measureText.appendChild(elt("br"));
12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      measureText.appendChild(document.createTextNode("x"));
12895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeChildrenAndAdd(display.measure, measureText);
12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var height = measureText.offsetHeight / 50;
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (height > 3) display.cachedTextHeight = height;
12935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeChildren(display.measure);
12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return height || 1;
12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function charWidth(display) {
12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (display.cachedCharWidth != null) return display.cachedCharWidth;
12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var anchor = elt("span", "x");
13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var pre = elt("pre", [anchor]);
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeChildrenAndAdd(display.measure, pre);
13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var width = anchor.offsetWidth;
13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (width > 2) display.cachedCharWidth = width;
13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return width || 10;
13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // OPERATIONS
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Operations are used to wrap changes in such a way that each
13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // change won't have to update the cursor and display (which would
13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // be awkward, slow, and error-prone), but instead updates are
13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // batched and then all combined and executed at once.
13135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var nextOpId = 0;
13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function startOperation(cm) {
1316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.curOp = {
13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // An array of ranges of lines that have to be updated. See
13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // updateDisplay.
13195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      changes: [],
1320f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      forceUpdate: false,
13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      updateInput: null,
13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      userSelChange: null,
13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      textChanged: null,
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      selectionChanged: false,
132553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      cursorActivity: false,
1326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateMaxLine: false,
1327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateScrollPos: false,
1328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      id: ++nextOpId
13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
1330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!delayedCallbackDepth++) delayedCallbacks = [];
13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
13325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function endOperation(cm) {
1334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var op = cm.curOp, doc = cm.doc, display = cm.display;
13355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.curOp = null;
1336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (op.updateMaxLine) computeMaxLength(cm);
133853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
1339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var width = measureLineWidth(cm, display.maxLine);
1340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
1341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.maxLineChanged = false;
1342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
1343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
1344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
13455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var newScrollPos, updated;
1347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (op.updateScrollPos) {
1348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      newScrollPos = op.updateScrollPos;
1349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
1350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var coords = cursorCoords(cm, doc.sel.head);
1351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
13525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1353f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
1354f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
1355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
1356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
13575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!updated && op.selectionChanged) updateSelection(cm);
1358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (op.updateScrollPos) {
1359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
1360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
1361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      alignHorizontally(cm);
136253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (op.scrollToPos)
136353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
1364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (newScrollPos) {
1365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      scrollCursorIntoView(cm);
1366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (op.selectionChanged) restartBlink(cm);
13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.state.focused && op.updateInput)
13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      resetInput(cm, op.userSelChange);
13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
1373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hidden) for (var i = 0; i < hidden.length; ++i)
1374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!hidden[i].lines.length) signal(hidden[i], "hide");
1375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (unhidden) for (var i = 0; i < unhidden.length; ++i)
1376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
1377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var delayed;
1379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!--delayedCallbackDepth) {
1380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      delayed = delayedCallbacks;
1381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      delayedCallbacks = null;
1382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (op.textChanged)
13845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      signal(cm, "change", cm, op.textChanged);
138553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (op.cursorActivity) signal(cm, "cursorActivity", cm);
1386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
13875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
13885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Wraps a function in an operation. Returns the wrapped function.
13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function operation(cm1, f) {
13915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return function() {
1392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var cm = cm1 || this, withOp = !cm.curOp;
1393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (withOp) startOperation(cm);
1394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      try { var result = f.apply(cm, arguments); }
1395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      finally { if (withOp) endOperation(cm); }
1396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return result;
1397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
1398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
1399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function docOperation(f) {
1400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return function() {
1401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var withOp = this.cm && !this.cm.curOp, result;
1402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (withOp) startOperation(this.cm);
1403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      try { result = f.apply(this, arguments); }
1404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      finally { if (withOp) endOperation(this.cm); }
14055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return result;
14065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
1408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function runInOp(cm, f) {
1409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var withOp = !cm.curOp, result;
1410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (withOp) startOperation(cm);
1411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    try { result = f(); }
1412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    finally { if (withOp) endOperation(cm); }
1413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return result;
1414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
14155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function regChange(cm, from, to, lendiff) {
1417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (from == null) from = cm.doc.first;
1418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (to == null) to = cm.doc.first + cm.doc.size;
14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.curOp.changes.push({from: from, to: to, diff: lendiff});
14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // INPUT HANDLING
14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function slowPoll(cm) {
1425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.display.pollingFast) return;
14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.display.poll.set(cm.options.pollInterval, function() {
14275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      readInput(cm);
1428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm.state.focused) slowPoll(cm);
14295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function fastPoll(cm) {
14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var missed = false;
14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.display.pollingFast = true;
14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function p() {
14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var changed = readInput(cm);
14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else {cm.display.pollingFast = false; slowPoll(cm);}
14395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.display.poll.set(20, p);
14415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // prevInput is a hack to work with IME. If we reset the textarea
14445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // on every change, that breaks IME. So we look for changes
14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // compared to the previous content instead. (Modern browsers have
14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // events that indicate IME taking place, but these are not widely
14475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // supported or compatible enough yet to rely on.)
14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function readInput(cm) {
1449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
14505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1451f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
1452f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      input.value = input.value.substring(0, input.value.length - 1);
1453f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      cm.state.fakedLastChar = false;
1454f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    }
14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var text = input.value;
14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (text == prevInput && posEq(sel.from, sel.to)) return false;
145753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
1458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      resetInput(cm, true);
1459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return false;
1460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
146153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
1462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var withOp = !cm.curOp;
1463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (withOp) startOperation(cm);
1464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    sel.shift = false;
14655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var same = 0, l = Math.min(prevInput.length, text.length);
146653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var from = sel.from, to = sel.to;
14685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (same < prevInput.length)
1469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      from = Pos(from.line, from.ch - (prevInput.length - same));
1470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1471926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
14735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var updateInput = cm.curOp.updateInput;
14745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
14755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                       origin: cm.state.pasteIncoming ? "paste" : "+input"};
14765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    makeChange(cm.doc, changeEvent, "end");
14775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.curOp.updateInput = updateInput;
14785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    signalLater(cm, "inputRead", cm, changeEvent);
14795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
148053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
14815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else cm.display.prevInput = text;
1482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (withOp) endOperation(cm);
1483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.state.pasteIncoming = false;
14845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
14855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
14865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function resetInput(cm, user) {
1488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var minimal, selected, doc = cm.doc;
1489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!posEq(doc.sel.from, doc.sel.to)) {
14905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      cm.display.prevInput = "";
14915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      minimal = hasCopyEvent &&
1492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
149353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var content = minimal ? "-" : selected || cm.getSelection();
149453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      cm.display.input.value = content;
1495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm.state.focused) selectInput(cm.display.input);
149653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (ie && !ie_lt9) cm.display.inputHasSelection = content;
149753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    } else if (user) {
149853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      cm.display.prevInput = cm.display.input.value = "";
149953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (ie && !ie_lt9) cm.display.inputHasSelection = null;
150053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
15015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.display.inaccurateSelection = minimal;
15025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
15035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function focusInput(cm) {
1505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
1506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.display.input.focus();
15075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
15085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function isReadOnly(cm) {
1510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return cm.options.readOnly || cm.doc.cantEdit;
15115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
15125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // EVENT HANDLERS
15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function registerEventHandlers(cm) {
15165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var d = cm.display;
15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scroller, "mousedown", operation(cm, onMouseDown));
151853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (ie)
151953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      on(d.scroller, "dblclick", operation(cm, function(e) {
1520591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (signalDOMEvent(cm, e)) return;
152153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var pos = posFromMouse(cm, e);
152253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
152353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        e_preventDefault(e);
152453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
152553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        extendSelection(cm.doc, word.from, word.to);
152653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      }));
152753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    else
1528591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.lineSpace, "selectstart", function(e) {
1530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!eventInWidget(d, e)) e_preventDefault(e);
15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
15325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Gecko browsers fire contextmenu *after* opening the menu, at
15335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // which point we can't mess with it anymore. Context menu is
15345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // handled in onMouseDown for Gecko.
1535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
15365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scroller, "scroll", function() {
1538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (d.scroller.clientHeight) {
1539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setScrollTop(cm, d.scroller.scrollTop);
1540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setScrollLeft(cm, d.scroller.scrollLeft, true);
1541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        signal(cm, "scroll", cm);
1542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
15435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
15445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scrollbarV, "scroll", function() {
1545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
15465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
15475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scrollbarH, "scroll", function() {
1548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
15495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
15505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
15525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
15535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
15555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scrollbarH, "mousedown", reFocus);
15565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.scrollbarV, "mousedown", reFocus);
15575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Prevent wrapper from ever scrolling
15585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
15605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var resizeTimer;
1561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function onResize() {
15625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (resizeTimer == null) resizeTimer = setTimeout(function() {
15635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        resizeTimer = null;
156493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        // Might be a text scaling operation, clear size caches.
15655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
156693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        clearCaches(cm);
156793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        runInOp(cm, bind(regChange, cm));
15685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      }, 100);
1569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    on(window, "resize", onResize);
1571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Above handler holds on to the editor and its data structures.
1572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Here we poll to unregister it when the editor is no longer in
1573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // the document, so that it can be garbage-collected.
1574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function unregister() {
1575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
1576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (p) setTimeout(unregister, 5000);
1577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else off(window, "resize", onResize);
1578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setTimeout(unregister, 5000);
15805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "keyup", operation(cm, function(e) {
1582591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (e.keyCode == 16) cm.doc.sel.shift = false;
15845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }));
15855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "input", bind(fastPoll, cm));
15865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "keydown", operation(cm, onKeyDown));
15875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "keypress", operation(cm, onKeyPress));
15885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "focus", bind(onFocus, cm));
15895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "blur", bind(onBlur, cm));
15905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function drag_(e) {
1592591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
15935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_stop(e);
15945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.options.dragDrop) {
15965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
15975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      on(d.scroller, "dragenter", drag_);
15985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      on(d.scroller, "dragover", drag_);
15995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      on(d.scroller, "drop", operation(cm, onDrop));
16005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    on(d.scroller, "paste", function(e){
1602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (eventInWidget(d, e)) return;
1603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      focusInput(cm);
1604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      fastPoll(cm);
1605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
16065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "paste", function() {
1607f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
1608f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      // Add a char to the end of textarea before paste occur so that
1609f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      // selection doesn't span to the end of textarea.
1610f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      if (webkit && !cm.state.fakedLastChar) {
1611f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        var start = d.input.selectionStart, end = d.input.selectionEnd;
1612f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        d.input.value += "$";
1613f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        d.input.selectionStart = start;
1614f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        d.input.selectionEnd = end;
1615f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        cm.state.fakedLastChar = true;
1616f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      }
1617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.state.pasteIncoming = true;
16185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      fastPoll(cm);
16195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
16205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function prepareCopy() {
16225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (d.inaccurateSelection) {
16235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        d.prevInput = "";
16245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        d.inaccurateSelection = false;
16255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        d.input.value = cm.getSelection();
16265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        selectInput(d.input);
16275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
16285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "cut", prepareCopy);
16305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(d.input, "copy", prepareCopy);
16315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Needed to handle Tab key in KHTML
16335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (khtml) on(d.sizer, "mouseup", function() {
16345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (document.activeElement == d.input) d.input.blur();
16355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        focusInput(cm);
16365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
16375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
16385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function eventInWidget(display, e) {
1640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
16415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
16435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
16445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function posFromMouse(cm, e, liberal) {
16465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var display = cm.display;
16475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!liberal) {
16485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var target = e_target(e);
16495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
16505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          target == display.scrollbarV || target == display.scrollbarV.firstChild ||
165193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          target == display.scrollbarFiller || target == display.gutterFiller) return null;
16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var x, y, space = getRect(display.lineSpace);
16545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Fails unpredictably on IE[67] when mouse is dragged around quickly.
16555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
16565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return coordsChar(cm, x - space.left, y - space.top);
16575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
16585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var lastClick, lastDoubleClick;
16605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onMouseDown(e) {
1661591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (signalDOMEvent(this, e)) return;
1662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    sel.shift = e.shiftKey;
16645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (eventInWidget(display, e)) {
16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!webkit) {
16675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        display.scroller.draggable = false;
16685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setTimeout(function(){display.scroller.draggable = true;}, 100);
16695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
16705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
16715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1672926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (clickInGutter(cm, e)) return;
16735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var start = posFromMouse(cm, e);
16745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (e_button(e)) {
16765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 3:
1677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (captureMiddleClick) onContextMenu.call(cm, cm, e);
16785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
16795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 2:
1680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (start) extendSelection(cm.doc, start);
16815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      setTimeout(bind(focusInput, cm), 20);
16825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_preventDefault(e);
16835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
16845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // For button 1, if it was clicked inside the editor
16865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // (posFromMouse returning non-null), we have to adjust the
16875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // selection.
16885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
16895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cm.state.focused) onFocus(cm);
16915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var now = +new Date, type = "single";
16935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
16945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      type = "triple";
16955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_preventDefault(e);
16965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      setTimeout(bind(focusInput, cm), 20);
16975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      selectLine(cm, start.line);
16985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
16995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      type = "double";
17005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      lastDoubleClick = {time: now, pos: start};
17015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_preventDefault(e);
17025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var word = findWordAt(getLine(doc, start.line).text, start);
1703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      extendSelection(cm.doc, word.from, word.to);
17045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else { lastClick = {time: now, pos: start}; }
17055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var last = start;
17075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
17085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var dragEnd = operation(cm, function(e2) {
17105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (webkit) display.scroller.draggable = false;
1711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.state.draggingText = false;
17125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        off(document, "mouseup", dragEnd);
17135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        off(display.scroller, "drop", dragEnd);
17145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
17155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          e_preventDefault(e2);
1716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          extendSelection(cm.doc, start);
17175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          focusInput(cm);
17185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Let the drag handler handle this.
17215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (webkit) display.scroller.draggable = true;
1722926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.state.draggingText = dragEnd;
17235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // IE's approach to draggable
17245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (display.scroller.dragDrop) display.scroller.dragDrop();
17255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      on(document, "mouseup", dragEnd);
17265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      on(display.scroller, "drop", dragEnd);
17275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
17285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    e_preventDefault(e);
1730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
17315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
173253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    var startstart = sel.from, startend = sel.to, lastPos = start;
17335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function doSelect(cur) {
173553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (posEq(lastPos, cur)) return;
173653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      lastPos = cur;
173753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
17385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (type == "single") {
1739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        extendSelection(cm.doc, clipPos(doc, start), cur);
1740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
1742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      startstart = clipPos(doc, startstart);
1744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      startend = clipPos(doc, startend);
1745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (type == "double") {
17465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var word = findWordAt(getLine(doc, cur.line).text, cur);
1747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
1748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else extendSelection(cm.doc, startstart, word.to);
17495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else if (type == "triple") {
1750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
1751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
17525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
17535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var editorSize = getRect(display.wrapper);
17565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Used to ensure timeout re-tries don't fire when another extend
17575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // happened in the meantime (clearTimeout isn't reliable -- at
17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // least on Chrome, the timeouts still happen even when cleared,
17595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // if the clear happens after their scheduled firing time).
17605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var counter = 0;
17615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function extend(e) {
17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var curCount = ++counter;
17645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var cur = posFromMouse(cm, e, true);
17655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!cur) return;
17665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!posEq(cur, last)) {
1767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!cm.state.focused) onFocus(cm);
17685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        last = cur;
17695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doSelect(cur);
17705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var visible = visibleLines(display, doc);
17715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (cur.line >= visible.to || cur.line < visible.from)
17725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
17735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
17745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
17755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (outside) setTimeout(operation(cm, function() {
17765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (counter != curCount) return;
17775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          display.scroller.scrollTop += outside;
17785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          extend(e);
17795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }), 50);
17805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
17815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function done(e) {
17845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      counter = Infinity;
17855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_preventDefault(e);
17865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      focusInput(cm);
17875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      off(document, "mousemove", move);
17885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      off(document, "mouseup", up);
17895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var move = operation(cm, function(e) {
17925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!ie && !e_button(e)) done(e);
17935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else extend(e);
17945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
17955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var up = operation(cm, done);
17965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(document, "mousemove", move);
17975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    on(document, "mouseup", up);
17985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
17995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  function clickInGutter(cm, e) {
18015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var display = cm.display;
18025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    try { var mX = e.clientX, mY = e.clientY; }
18035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    catch(e) { return false; }
18045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
18055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (mX >= Math.floor(getRect(display.gutters).right)) return false;
18065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    e_preventDefault(e);
18075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (!hasHandler(cm, "gutterClick")) return true;
18085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
18095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var lineBox = getRect(display.lineDiv);
18105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (mY > lineBox.bottom) return true;
18115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    mY -= lineBox.top - display.viewOffset;
18125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
18135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    for (var i = 0; i < cm.options.gutters.length; ++i) {
18145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      var g = display.gutters.childNodes[i];
18155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (g && getRect(g).right >= mX) {
18165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var line = lineAtHeight(cm.doc, mY);
18175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var gutter = cm.options.gutters[i];
18185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        signalLater(cm, "gutterClick", cm, line, gutter, e);
18195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        break;
18205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      }
18215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
18225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return true;
18235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  }
18245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
18255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  // Kludge to work around strange IE behavior where it'll sometimes
18265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  // re-fire a series of drag-related events right after the drop (#1551)
18275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  var lastDrop = 0;
18285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
18295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onDrop(e) {
18305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var cm = this;
1831591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return;
18335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    e_preventDefault(e);
18345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (ie) lastDrop = +new Date;
18355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
18365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!pos || isReadOnly(cm)) return;
18375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (files && files.length && window.FileReader && window.File) {
18385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var n = files.length, text = Array(n), read = 0;
18395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var loadFile = function(file, i) {
18405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var reader = new FileReader;
18415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        reader.onload = function() {
18425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          text[i] = reader.result;
18435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (++read == n) {
1844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            pos = clipPos(cm.doc, pos);
1845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
18465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
18475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
18485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        reader.readAsText(file);
18495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      };
18505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < n; ++i) loadFile(files[i], i);
18515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
18525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Don't do a replace if the drop happened inside of the selected text.
1853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
1854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.state.draggingText(e);
1855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Ensure the editor is re-focused
1856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setTimeout(bind(focusInput, cm), 20);
18575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
18585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
18595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      try {
18605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var text = e.dataTransfer.getData("Text");
18615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (text) {
1862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
1863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          setSelection(cm.doc, pos, pos);
1864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
1865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          cm.replaceSelection(text, null, "paste");
1866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          focusInput(cm);
1867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          onFocus(cm);
18685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
18705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      catch(e){}
18715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
18735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onDragStart(cm, e) {
18755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1876591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
18785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var txt = cm.getSelection();
18795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    e.dataTransfer.setData("Text", txt);
18805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Use dummy image instead of default browsers image.
1882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
18835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (e.dataTransfer.setDragImage && !safari) {
1884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (opera) {
1886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        img.width = img.height = 1;
1887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.display.wrapper.appendChild(img);
1888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Force a relayout, or Opera won't use our image for some obscure reason
1889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        img._top = img.offsetTop;
1890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
1891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      e.dataTransfer.setDragImage(img, 0, 0);
1892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (opera) img.parentNode.removeChild(img);
1893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
18945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
18955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function setScrollTop(cm, val) {
1897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (Math.abs(cm.doc.scrollTop - val) < 2) return;
1898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.scrollTop = val;
18995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!gecko) updateDisplay(cm, [], val);
19005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
19015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
19025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (gecko) updateDisplay(cm, []);
19035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    startWorker(cm, 100);
19045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
1905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function setScrollLeft(cm, val, isScroller) {
1906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
1907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
1908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.scrollLeft = val;
1909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    alignHorizontally(cm);
19105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
19115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
19125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
19135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Since the delta values reported on mouse wheel events are
19155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // unstandardized between browsers and even browser versions, and
19165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // generally horribly unpredictable, this code starts by measuring
19175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // the scroll effect that the first few mouse wheel events have,
19185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // and, from that, detects the way it can convert deltas to pixel
19195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // offsets afterwards.
19205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  //
19215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // The reason we want to know the amount a wheel event will scroll
19225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // is that it gives us a chance to update the display before the
19235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // actual scrolling happens, reducing flickering.
19245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var wheelSamples = 0, wheelPixelsPerUnit = null;
19265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Fill in a browser-detected starting value on browsers where we
19275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // know one. These don't have to be accurate -- the result of them
19285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // being wrong would just be a slight flicker on the first wheel
19295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // scroll (if it is large enough).
19305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (ie) wheelPixelsPerUnit = -.53;
19315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  else if (gecko) wheelPixelsPerUnit = 15;
19325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  else if (chrome) wheelPixelsPerUnit = -.7;
19335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  else if (safari) wheelPixelsPerUnit = -1/3;
19345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onScrollWheel(cm, e) {
19365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
19375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
19385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
19395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (dy == null) dy = e.wheelDelta;
19405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
194153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    var display = cm.display, scroll = display.scroller;
194253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // Quit if there's nothing to scroll here
194353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
194453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)          dy && scroll.scrollHeight > scroll.clientHeight)) return;
194553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
1946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Webkit browsers on OS X abort momentum scrolls when the target
1947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // of the scroll event is removed from the scrollable element.
1948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // This hack (see related code in patchDisplay) makes sure the
1949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // element is kept around.
1950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (dy && mac && webkit) {
1951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
1952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cur.lineObj) {
1953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          cm.display.currentWheelTarget = cur;
1954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          break;
1955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
1956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
1957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1958926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // On some browsers, horizontal scrolling will cause redraws to
1960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // happen before the gutter has been realigned, causing it to
1961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // wriggle around in a most unseemly way. When we have an
1962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // estimated pixels/delta value, we just handle horizontal
1963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // scrolling entirely here. It'll be slightly off from native, but
1964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // better than glitching out.
1965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
1966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (dy)
1967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
1968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
1969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      e_preventDefault(e);
1970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      display.wheelStartX = null; // Abort measurement, if in progress
1971926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return;
1972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (dy && wheelPixelsPerUnit != null) {
19755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var pixels = dy * wheelPixelsPerUnit;
1976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
1977926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (pixels < 0) top = Math.max(0, top + pixels - 50);
1978926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else bot = Math.min(cm.doc.height, bot + pixels + 50);
19795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      updateDisplay(cm, [], {top: top, bottom: bot});
19805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1981926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
19825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (wheelSamples < 20) {
1983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (display.wheelStartX == null) {
1984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
1985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        display.wheelDX = dx; display.wheelDY = dy;
19865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setTimeout(function() {
1987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (display.wheelStartX == null) return;
1988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var movedX = scroll.scrollLeft - display.wheelStartX;
1989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var movedY = scroll.scrollTop - display.wheelStartY;
1990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
1991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            (movedX && display.wheelDX && movedX / display.wheelDX);
1992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          display.wheelStartX = display.wheelStartY = null;
19935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (!sample) return;
19945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
19955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          ++wheelSamples;
19965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }, 200);
19975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
1998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        display.wheelDX += dx; display.wheelDY += dy;
19995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
20005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
20025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function doHandleBinding(cm, bound, dropShift) {
20045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof bound == "string") {
20055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      bound = commands[bound];
20065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!bound) return false;
20075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Ensure previous input has been read, so that the handler sees a
2009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // consistent view of the document
2010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
2011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc, prevShift = doc.sel.shift, done = false;
20125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    try {
2013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (isReadOnly(cm)) cm.state.suppressEdits = true;
2014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (dropShift) doc.sel.shift = false;
2015926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      done = bound(cm) != Pass;
20165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } finally {
2017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      doc.sel.shift = prevShift;
2018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.state.suppressEdits = false;
20195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2020926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return done;
2021926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2022926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2023926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function allKeyMaps(cm) {
2024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var maps = cm.state.keyMaps.slice(0);
202553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
2026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    maps.push(cm.options.keyMap);
2027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return maps;
20285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
20295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var maybeTransition;
20315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function handleKeyBinding(cm, e) {
20325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Handle auto keymap transitions
20335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
20345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearTimeout(maybeTransition);
20355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
20365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (getKeyMap(cm.options.keyMap) == startMap) {
20375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cm.options.keyMap = (next.call ? next.call(null, cm) : next);
20385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        keyMapChanged(cm);
20395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      }
20405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }, 50);
20415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var name = keyName(e, true), handled = false;
2043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!name) return false;
2044926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var keymaps = allKeyMaps(cm);
2045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (e.shiftKey) {
2047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // First try to resolve full name (including 'Shift-'). Failing
2048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // that, see if there is a cursor-motion command (starting with
2049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // 'go') bound to the keyname without 'Shift-'.
2050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
2051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             || lookupKey(name, keymaps, function(b) {
20525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                  if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
20535267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                    return doHandleBinding(cm, b);
2054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                });
20555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
20575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
20595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (handled) {
20605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_preventDefault(e);
20615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      restartBlink(cm);
20625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
20635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      signalLater(cm, "keyHandled", cm, name, e);
20645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return handled;
20665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
20675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function handleCharBinding(cm, e, ch) {
2069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
20705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            function(b) { return doHandleBinding(cm, b, true); });
20715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (handled) {
20725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_preventDefault(e);
20735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      restartBlink(cm);
20745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
20755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return handled;
20775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
20785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var lastStoppedKey = null;
20805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onKeyDown(e) {
20815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var cm = this;
2082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cm.state.focused) onFocus(cm);
20835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ie && e.keyCode == 27) { e.returnValue = false; }
2084591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var code = e.keyCode;
20865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // IE does strange things with escape.
2087926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.sel.shift = code == 16 || e.shiftKey;
20885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // First give onKeyEvent option a chance to handle this.
20895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var handled = handleKeyBinding(cm, e);
20905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (opera) {
20915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      lastStoppedKey = handled ? code : null;
20925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Opera has no cut event... we try to at least catch the key combo
2093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
20945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cm.replaceSelection("");
20955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
20975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onKeyPress(e) {
20995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var cm = this;
2100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var keyCode = e.keyCode, charCode = e.charCode;
21025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
21035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
21045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
2105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.options.electricChars && this.doc.mode.electricChars &&
21065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.options.smartIndent && !isReadOnly(this) &&
2107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.doc.mode.electricChars.indexOf(ch) > -1)
2108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
21095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (handleCharBinding(cm, e, ch)) return;
211053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (ie && !ie_lt9) cm.display.inputHasSelection = null;
21115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fastPoll(cm);
21125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
21135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onFocus(cm) {
21155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.options.readOnly == "nocursor") return;
2116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cm.state.focused) {
21175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      signal(cm, "focus", cm);
2118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.state.focused = true;
2119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
2120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.display.wrapper.className += " CodeMirror-focused";
21215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      resetInput(cm, true);
21225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    slowPoll(cm);
21245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    restartBlink(cm);
21255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
21265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onBlur(cm) {
2127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm.state.focused) {
21285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      signal(cm, "blur", cm);
2129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.state.focused = false;
2130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
21315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearInterval(cm.display.blinker);
2133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
21345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
21355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var detectingSelectAll;
21375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function onContextMenu(cm, e) {
2138e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (signalDOMEvent(cm, e, "contextmenu")) return;
2139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var display = cm.display, sel = cm.doc.sel;
2140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (eventInWidget(display, e)) return;
2141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
21425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
21435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!pos || opera) return; // Opera is difficult.
21445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
2145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      operation(cm, setSelection)(cm.doc, pos, pos);
21465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var oldCSS = display.input.style.cssText;
21485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.inputDiv.style.position = "absolute";
21495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
21505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
2151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
21525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    focusInput(cm);
21535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resetInput(cm, true);
21545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Adds "Select all" to context menu in FF
21555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
21565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
215793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    function prepareSelectAllHack() {
215893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (display.input.selectionStart != null) {
215993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
216093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        display.prevInput = " ";
216193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
216293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      }
216393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
21645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function rehide() {
21655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.inputDiv.style.position = "relative";
21665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.input.style.cssText = oldCSS;
21675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
21685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      slowPoll(cm);
21695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // Try to detect the user choosing select-all
217193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (display.input.selectionStart != null) {
217293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (!ie || ie_lt9) prepareSelectAllHack();
21735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearTimeout(detectingSelectAll);
217493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var i = 0, poll = function(){
21755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (display.prevInput == " " && display.input.selectionStart == 0)
21765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            operation(cm, commands.selectAll)(cm);
21775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
21785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          else resetInput(cm);
2179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        };
2180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        detectingSelectAll = setTimeout(poll, 200);
21815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
21825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
218493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (ie && !ie_lt9) prepareSelectAllHack();
2185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (captureMiddleClick) {
21865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e_stop(e);
2187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var mouseup = function() {
21885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        off(window, "mouseup", mouseup);
21895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setTimeout(rehide, 20);
2190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      };
2191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      on(window, "mouseup", mouseup);
21925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
21935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      setTimeout(rehide, 50);
21945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
21965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // UPDATING
21985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  var changeEnd = CodeMirror.changeEnd = function(change) {
220053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!change.text) return change.to;
2201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Pos(change.from.line + change.text.length - 1,
2202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2203591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  };
2204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Make sure a position will be valid after the given change.
2206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function clipPostChange(doc, change, pos) {
2207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!posLess(change.from, pos)) return clipPos(doc, pos);
2208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var diff = (change.text.length - 1) - (change.to.line - change.from.line);
2209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (pos.line > change.to.line + diff) {
2210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
2211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
2212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return clipToLen(pos, getLine(doc, preLine).text.length);
2213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (pos.line == change.to.line + diff)
2215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
2216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                       getLine(doc, change.to.line).text.length - change.to.ch);
2217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var inside = pos.line - change.from.line;
2218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
2219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Hint can be null|"end"|"start"|"around"|{anchor,head}
2222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function computeSelAfterChange(doc, change, hint) {
2223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
2224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return {anchor: clipPostChange(doc, change, hint.anchor),
2225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              head: clipPostChange(doc, change, hint.head)};
2226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hint == "start") return {anchor: change.from, head: change.from};
2228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var end = changeEnd(change);
2230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hint == "around") return {anchor: change.from, head: end};
2231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hint == "end") return {anchor: end, head: end};
2232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // hint is null, leave the selection alone as much as possible
2234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var adjustPos = function(pos) {
2235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (posLess(pos, change.from)) return pos;
2236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!posLess(change.to, pos)) return end;
2237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
2239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (pos.line == change.to.line) ch += end.ch - change.to.ch;
2240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return Pos(line, ch);
2241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
2242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
224593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  function filterChange(doc, change, update) {
2246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var obj = {
2247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      canceled: false,
2248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      from: change.from,
2249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      to: change.to,
2250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      text: change.text,
2251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      origin: change.origin,
2252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cancel: function() { this.canceled = true; }
2253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
225493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (update) obj.update = function(from, to, text, origin) {
225593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (from) this.from = clipPos(doc, from);
225693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (to) this.to = clipPos(doc, to);
225793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (text) this.text = text;
225893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (origin !== undefined) this.origin = origin;
225993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    };
2260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    signal(doc, "beforeChange", doc, obj);
2261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (obj.canceled) return null;
2264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
2265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Replace the range from from to to by the strings in replacement.
2268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // change is a {from, to, text [, origin]} object
2269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function makeChange(doc, change, selUpdate, ignoreReadOnly) {
2270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm) {
2271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
2272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (doc.cm.state.suppressEdits) return;
2273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2275926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
227693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      change = filterChange(doc, change, true);
2277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!change) return;
2278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
22805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Possibly split or suppress the update based on the presence
22815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // of read-only spans in its range.
2282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
22835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (split) {
22845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = split.length - 1; i >= 1; --i)
2285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
22865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (split.length)
2287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
22885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      makeChangeNoReadonly(doc, change, selUpdate);
22905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
22915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
22925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function makeChangeNoReadonly(doc, change, selUpdate) {
2294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var selAfter = computeSelAfterChange(doc, change, selUpdate);
2295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
22965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
2298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var rebased = [];
2299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    linkedDocs(doc, function(doc, sharedHist) {
2301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        rebaseHist(doc.history, change);
2303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        rebased.push(doc.history);
2304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
2305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
23065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
2307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function makeChangeFromHistory(doc, type) {
231053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (doc.cm && doc.cm.state.suppressEdits) return;
231153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var hist = doc.history;
2313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var event = (type == "undo" ? hist.done : hist.undone).pop();
2314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!event) return;
2315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
23175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                anchorAfter: event.anchorBefore, headAfter: event.headBefore,
23185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                generation: hist.generation};
2319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    (type == "undo" ? hist.undone : hist.done).push(anti);
23205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    hist.generation = event.generation || ++hist.maxGeneration;
2321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
232293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
232393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = event.changes.length - 1; i >= 0; --i) {
2325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var change = event.changes[i];
2326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      change.origin = type;
232793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (filter && !filterChange(doc, change, false)) {
232893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        (type == "undo" ? hist.done : hist.undone).length = 0;
232993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        return;
233093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      }
233193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      anti.changes.push(historyChangeFromChange(doc, change));
2333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var after = i ? computeSelAfterChange(doc, change, null)
2335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    : {anchor: event.anchorBefore, head: event.headBefore};
2336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
2337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var rebased = [];
2338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      linkedDocs(doc, function(doc, sharedHist) {
2340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          rebaseHist(doc.history, change);
2342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          rebased.push(doc.history);
2343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
2345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      });
23465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
23475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
23485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function shiftDoc(doc, distance) {
2350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
2351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.first += distance;
2352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
2353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
2354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
2355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function makeChangeSingleDoc(doc, change, selAfter, spans) {
2358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm && !doc.cm.curOp)
2359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
2360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (change.to.line < doc.first) {
2362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
2363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return;
2364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (change.from.line > doc.lastLine()) return;
2366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Clip the change to the size of this doc
2368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (change.from.line < doc.first) {
2369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var shift = change.text.length - 1 - (doc.first - change.from.line);
2370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      shiftDoc(doc, shift);
2371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
2372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                text: [lst(change.text)], origin: change.origin};
2373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var last = doc.lastLine();
2375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (change.to.line > last) {
2376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
2377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                text: [change.text[0]], origin: change.origin};
23785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    change.removed = getBetween(doc, change.from, change.to);
2381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
2383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
2384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else updateDoc(doc, change, spans, selAfter);
23855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
23865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
2388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
23895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var recomputeMaxLength = false, checkWidthStart = from.line;
23915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!cm.options.lineWrapping) {
2392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
23935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      doc.iter(checkWidthStart, to.line + 1, function(line) {
2394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (line == display.maxLine) {
23955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          recomputeMaxLength = true;
23965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          return true;
23975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
23985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
23995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
24005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
240153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
240253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      cm.curOp.cursorActivity = true;
240353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
24055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cm.options.lineWrapping) {
2407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
24085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var len = lineLength(doc, line);
2409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (len > display.maxLineLength) {
2410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          display.maxLine = line;
2411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          display.maxLineLength = len;
2412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          display.maxLineChanged = true;
24135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          recomputeMaxLength = false;
24145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
24155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
24165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
24175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
24185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Adjust frontier, schedule worker
2420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.frontier = Math.min(doc.frontier, from.line);
24215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startWorker(cm, 400);
24225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lendiff = change.text.length - (to.line - from.line) - 1;
24245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Remember that these lines changed, for updating the display
24255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    regChange(cm, from.line, to.line + 1, lendiff);
2426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
24275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasHandler(cm, "change")) {
2428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var changeObj = {from: from, to: to,
2429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                       text: change.text,
2430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                       removed: change.removed,
2431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                       origin: change.origin};
24325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (cm.curOp.textChanged) {
24335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
24345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cur.next = changeObj;
24355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else cm.curOp.textChanged = changeObj;
24365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
24375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
24385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function replaceRange(doc, code, from, to, origin) {
24405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!to) to = from;
24415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
2442926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof code == "string") code = splitLines(code);
2443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
24445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
24455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // POSITION OBJECT
2447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function Pos(line, ch) {
2449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!(this instanceof Pos)) return new Pos(line, ch);
2450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.line = line; this.ch = ch;
2451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  CodeMirror.Pos = Pos;
24535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
24555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function copyPos(x) {return Pos(x.line, x.ch);}
24575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // SELECTION
2459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
24615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function clipPos(doc, pos) {
2462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (pos.line < doc.first) return Pos(doc.first, 0);
2463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var last = doc.first + doc.size - 1;
2464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return clipToLen(pos, getLine(doc, pos.line).text.length);
2466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function clipToLen(pos, linelen) {
2468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var ch = pos.ch;
2469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (ch < 0) return Pos(pos.line, 0);
24715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else return pos;
24725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
2473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // If shift is held, this will move the selection anchor. Otherwise,
2476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // it'll set the whole selection.
2477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function extendSelection(doc, pos, other, bias) {
2478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.sel.shift || doc.sel.extend) {
2479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var anchor = doc.sel.anchor;
2480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (other) {
2481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var posBefore = posLess(pos, anchor);
2482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (posBefore != posLess(other, anchor)) {
2483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          anchor = pos;
2484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          pos = other;
2485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else if (posBefore != posLess(pos, other)) {
2486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          pos = other;
2487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
2489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      setSelection(doc, anchor, pos, bias);
2490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
2491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      setSelection(doc, pos, other || pos, bias);
24925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm) doc.cm.curOp.userSelChange = true;
2494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function filterSelectionChange(doc, anchor, head) {
2497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var obj = {anchor: anchor, head: head};
2498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    signal(doc, "beforeSelectionChange", doc, obj);
2499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
2501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return obj;
25025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
25035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Update the selection. Last two args are only used by
25055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // updateDoc, since they have to be expressed in the line
25065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // numbers before the update.
2507926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function setSelection(doc, anchor, head, bias, checkAtomic) {
2508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
2509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var filtered = filterSelectionChange(doc, anchor, head);
2510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      head = filtered.head;
2511926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      anchor = filtered.anchor;
2512926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
25135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2514926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var sel = doc.sel;
2515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    sel.goalColumn = null;
25165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Skip over atomic spans.
2517926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (checkAtomic || !posEq(anchor, sel.anchor))
2518926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
2519926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (checkAtomic || !posEq(head, sel.head))
2520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      head = skipAtomic(doc, head, bias, checkAtomic != "push");
2521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
2523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    sel.anchor = anchor; sel.head = head;
2525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var inv = posLess(head, anchor);
2526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    sel.from = inv ? head : anchor;
2527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    sel.to = inv ? anchor : head;
2528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm)
253053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
253153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        doc.cm.curOp.cursorActivity = true;
25325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    signalLater(doc, "cursorActivity", doc);
25345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
25355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function reCheckSelection(cm) {
2537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
25385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
25395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function skipAtomic(doc, pos, bias, mayClear) {
2541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var flipped = false, curPos = pos;
25425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var dir = bias || 1;
2543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.cantEdit = false;
25445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    search: for (;;) {
254553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var line = getLine(doc, curPos.line);
25465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (line.markedSpans) {
25475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < line.markedSpans.length; ++i) {
25485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var sp = line.markedSpans[i], m = sp.marker;
25495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
25505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
255153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            if (mayClear) {
255253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)              signal(m, "beforeCursorEnter");
255353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)              if (m.explicitlyCleared) {
255453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                if (!line.markedSpans) break;
255553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                else {--i; continue;}
255653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)              }
255753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            }
255853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            if (!m.atomic) continue;
25595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var newPos = m.find()[dir < 0 ? "from" : "to"];
25605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (posEq(newPos, curPos)) {
25615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              newPos.ch += dir;
25625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              if (newPos.ch < 0) {
2563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
25645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else newPos = null;
25655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              } else if (newPos.ch > line.text.length) {
2566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
25675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else newPos = null;
25685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              }
25695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              if (!newPos) {
25705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (flipped) {
25715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  // Driven in a corner -- no valid cursor position found at all
25725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  // -- try again *with* clearing, if we didn't already
2573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  if (!mayClear) return skipAtomic(doc, pos, bias, true);
25745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  // Otherwise, turn off editing until further notice, and return the start of the doc
2575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  doc.cantEdit = true;
2576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                  return Pos(doc.first, 0);
25775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
25785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                flipped = true; newPos = pos; dir = -dir;
25795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              }
25805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
25815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            curPos = newPos;
25825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue search;
25835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
25845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
25855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
25865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return curPos;
25875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
25885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
25895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // SCROLLING
25915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function scrollCursorIntoView(cm) {
259393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
2594926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cm.state.focused) return;
25955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var display = cm.display, box = getRect(display.sizer), doScroll = null;
25965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (coords.top + box.top < 0) doScroll = true;
25975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
25985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (doScroll != null && !phantom) {
25995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var hidden = display.cursor.style.display == "none";
26005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (hidden) {
26015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        display.cursor.style.display = "";
26025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        display.cursor.style.left = coords.left + "px";
26035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        display.cursor.style.top = (coords.top - display.viewOffset) + "px";
26045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
26055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.cursor.scrollIntoView(doScroll);
26065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (hidden) display.cursor.style.display = "none";
26075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
26095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function scrollPosIntoView(cm, pos, margin) {
2611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (margin == null) margin = 0;
2612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (;;) {
2613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var changed = false, coords = cursorCoords(cm, pos);
2614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
2615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
2616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (scrollPos.scrollTop != null) {
2617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setScrollTop(cm, scrollPos.scrollTop);
2618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
2619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
2620926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (scrollPos.scrollLeft != null) {
2621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setScrollLeft(cm, scrollPos.scrollLeft);
2622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
2623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
2624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!changed) return coords;
2625926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function scrollIntoView(cm, x1, y1, x2, y2) {
2629926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
2630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
2631926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
26325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
26335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function calculateScrollPos(cm, x1, y1, x2, y2) {
26355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var display = cm.display, snapMargin = textHeight(cm.display);
263653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (y1 < 0) y1 = 0;
26375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var docBottom = cm.doc.height + paddingVert(display);
26395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
264053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (y1 < screentop) {
264153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      result.scrollTop = atTop ? 0 : y1;
264253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    } else if (y2 > screentop + screen) {
264353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
264453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (newTop != screentop) result.scrollTop = newTop;
264553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
26465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
26485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
26495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var gutterw = display.gutters.offsetWidth;
26505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var atLeft = x1 < gutterw + 10;
26515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (x1 < screenleft + gutterw || atLeft) {
26525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (atLeft) x1 = 0;
26535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
26545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (x2 > screenw + screenleft - 3) {
26555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      result.scrollLeft = x2 + 10 - screenw;
26565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
26585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
26595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function updateScrollPos(cm, left, top) {
266153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
266253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                                scrollTop: top == null ? cm.doc.scrollTop : top};
2663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function addToScrollPos(cm, left, top) {
2666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
2667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var scroll = cm.display.scroller;
2668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
2669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
2670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
26725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // API UTILITIES
26735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function indentLine(cm, n, how, aggressive) {
2675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc;
26765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (how == null) how = "add";
26775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (how == "smart") {
2678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!cm.doc.mode.indent) how = "prev";
26795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else var state = getStateBefore(cm, n);
26805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var tabSize = cm.options.tabSize;
26835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
26845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var curSpaceString = line.text.match(/^\s*/)[0], indentation;
26855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (how == "smart") {
2686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
2687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (indentation == Pass) {
2688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!aggressive) return;
2689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        how = "prev";
2690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
26915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (how == "prev") {
2693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
26945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else indentation = 0;
2695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (how == "add") {
2696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      indentation = curSpace + cm.options.indentUnit;
2697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (how == "subtract") {
2698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      indentation = curSpace - cm.options.indentUnit;
26995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    } else if (typeof how == "number") {
27005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      indentation = curSpace + how;
27015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    indentation = Math.max(0, indentation);
27035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var indentString = "", pos = 0;
27055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cm.options.indentWithTabs)
27065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
27075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pos < indentation) indentString += spaceStr(indentation - pos);
27085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (indentString != curSpaceString)
2710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
27115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    line.stateAfter = null;
27125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
27135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function changeLine(cm, handle, op) {
2715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var no = handle, line = handle, doc = cm.doc;
27165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
27175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else no = lineNo(handle);
27185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (no == null) return null;
27195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (op(line, no)) regChange(cm, no, no + 1);
27205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else return null;
27215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return line;
27225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
27235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function findPosH(doc, pos, dir, unit, visually) {
272593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var line = pos.line, ch = pos.ch, origDir = dir;
27265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var lineObj = getLine(doc, line);
2727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var possible = true;
27285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function findNextLine() {
27295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var l = line + dir;
2730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
27315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      line = l;
27325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return lineObj = getLine(doc, l);
27335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function moveOnce(boundToLine) {
27355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
27365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (next == null) {
27375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!boundToLine && findNextLine()) {
27385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
27395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          else ch = dir < 0 ? lineObj.text.length : 0;
2740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else return (possible = false);
27415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else ch = next;
27425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return true;
27435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
27455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (unit == "char") moveOnce();
27465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (unit == "column") moveOnce(true);
2747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (unit == "word" || unit == "group") {
2748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sawType = null, group = unit == "group";
2749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var first = true;; first = false) {
2750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (dir < 0 && !moveOnce(!first)) break;
2751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cur = lineObj.text.charAt(ch) || "\n";
2752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var type = isWordChar(cur) ? "w"
2753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          : !group ? null
2754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          : /\s/.test(cur) ? null
2755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          : "p";
2756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (sawType && sawType != type) {
2757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (dir < 0) {dir = 1; moveOnce();}
2758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          break;
2759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2760926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (type) sawType = type;
2761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (dir > 0 && !moveOnce(!first)) break;
27625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
27635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
276493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var result = skipAtomic(doc, Pos(line, ch), origDir, true);
2765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!possible) result.hitSide = true;
2766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return result;
2767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
2768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function findPosV(cm, pos, dir, unit) {
2770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var doc = cm.doc, x = pos.left, y;
2771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (unit == "page") {
2772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
2773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
2774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (unit == "line") {
2775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
2776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (;;) {
2778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var target = coordsChar(cm, x, y);
2779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!target.outside) break;
2780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
2781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      y += dir * 5;
2782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return target;
27845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
27855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function findWordAt(line, pos) {
27875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var start = pos.ch, end = pos.ch;
27885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (line) {
2789e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
27905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var startChar = line.charAt(start);
2791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var check = isWordChar(startChar) ? isWordChar
2792926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
2793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
27945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      while (start > 0 && check(line.charAt(start - 1))) --start;
27955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      while (end < line.length && check(line.charAt(end))) ++end;
27965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
27985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
27995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function selectLine(cm, line) {
2801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
28025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
28035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // PROTOTYPE
28055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // The publicly visible API. Note that operation(null, f) means
28075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // 'wrap f in an operation, performed on its `this` parameter'
28085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.prototype = {
281093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    constructor: CodeMirror,
28115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
28125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setOption: function(option, value) {
28145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var options = this.options, old = options[option];
28155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (options[option] == value && option != "mode") return;
28165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      options[option] = value;
28175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (optionHandlers.hasOwnProperty(option))
28185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        operation(this, optionHandlers[option])(this, value, old);
28195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
28205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getOption: function(option) {return this.options[option];},
2822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getDoc: function() {return this.doc;},
28235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
282453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    addKeyMap: function(map, bottom) {
282553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      this.state.keyMaps[bottom ? "push" : "unshift"](map);
2826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
2827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeKeyMap: function(map) {
2828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var maps = this.state.keyMaps;
2829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0; i < maps.length; ++i)
2830e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
2831926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          maps.splice(i, 1);
2832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          return true;
2833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
28355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    addOverlay: operation(null, function(spec, options) {
2837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
2838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (mode.startState) throw new Error("Overlays may not be stateful.");
2839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
2840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.state.modeGen++;
2841926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      regChange(this);
28425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
2843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeOverlay: operation(null, function(spec) {
2844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var overlays = this.state.overlays;
2845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0; i < overlays.length; ++i) {
284693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var cur = overlays[i].modeSpec;
284793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (cur == spec || typeof spec == "string" && cur.name == spec) {
2848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          overlays.splice(i, 1);
2849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          this.state.modeGen++;
2850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          regChange(this);
2851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          return;
2852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
28545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
28555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    indentLine: operation(null, function(n, dir, aggressive) {
28575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (typeof dir != "string" && typeof dir != "number") {
28585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
28595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else dir = dir ? "add" : "subtract";
28605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
2861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
28625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
28635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    indentSelection: operation(null, function(how) {
2864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sel = this.doc.sel;
28655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
28665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var e = sel.to.line - (sel.to.ch ? 0 : 1);
28675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
28685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
28695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Fetch the parser token for a given character. Useful for hacks
2871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // that want to inspect the mode state (say, for completion).
2872591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    getTokenAt: function(pos, precise) {
2873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var doc = this.doc;
28745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      pos = clipPos(doc, pos);
2875591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
2876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var line = getLine(doc, pos.line);
2877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var stream = new StringStream(line.text, this.options.tabSize);
2878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      while (stream.pos < pos.ch && !stream.eol()) {
2879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        stream.start = stream.pos;
2880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var style = mode.token(stream, state);
2881926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
2882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return {start: stream.start,
2883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              end: stream.pos,
2884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              string: stream.current(),
2885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              className: style || null, // Deprecated, use 'type' instead
2886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              type: style || null,
2887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              state: state};
28885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
28895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2890591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    getTokenTypeAt: function(pos) {
2891591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      pos = clipPos(this.doc, pos);
2892591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var styles = getLineStyles(this, getLine(this.doc, pos.line));
2893591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2894e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (ch == 0) return styles[2];
2895591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      for (;;) {
2896591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var mid = (before + after) >> 1;
2897591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
2898591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        else if (styles[mid * 2 + 1] < ch) before = mid + 1;
2899591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        else return styles[mid * 2 + 2];
2900591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      }
2901591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
2902591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
2903e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    getModeAt: function(pos) {
2904e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      var mode = this.doc.mode;
2905e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (!mode.innerMode) return mode;
2906e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
2907e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
2908e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2909e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    getHelper: function(pos, type) {
2910e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (!helpers.hasOwnProperty(type)) return;
2911e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      var help = helpers[type], mode = this.getModeAt(pos);
2912e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return mode[type] && help[mode[type]] ||
2913e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        mode.helperType && help[mode.helperType] ||
2914e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        help[mode.name];
2915e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
2916e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2917591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    getStateAfter: function(line, precise) {
2918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var doc = this.doc;
2919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2920591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      return getStateBefore(this, line + 1, precise);
29215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
29225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cursorCoords: function(start, mode) {
2924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var pos, sel = this.doc.sel;
2925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (start == null) pos = sel.head;
2926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else if (typeof start == "object") pos = clipPos(this.doc, start);
29275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else pos = start ? sel.from : sel.to;
29285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return cursorCoords(this, pos, mode || "page");
29295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
29305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    charCoords: function(pos, mode) {
2932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return charCoords(this, clipPos(this.doc, pos), mode || "page");
29335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
29345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    coordsChar: function(coords, mode) {
2936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      coords = fromCoordSystem(this, coords, mode || "page");
2937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return coordsChar(this, coords.left, coords.top);
29385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
29395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    lineAtHeight: function(height, mode) {
29415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
29425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      return lineAtHeight(this.doc, height + this.display.viewOffset);
29435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    },
2944591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    heightAtLine: function(line, mode) {
2945591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var end = false, last = this.doc.first + this.doc.size - 1;
2946591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (line < this.doc.first) line = this.doc.first;
2947591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      else if (line > last) { line = last; end = true; }
2948591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var lineObj = getLine(this.doc, line);
2949591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
2950591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        (end ? lineObj.height : 0);
2951591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
29525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
29535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    defaultTextHeight: function() { return textHeight(this.display); },
2954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    defaultCharWidth: function() { return charWidth(this.display); },
29555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setGutterMarker: operation(null, function(line, gutterID, value) {
29575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return changeLine(this, line, function(line) {
29585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var markers = line.gutterMarkers || (line.gutterMarkers = {});
29595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markers[gutterID] = value;
29605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!value && isEmpty(markers)) line.gutterMarkers = null;
29615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
29625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
29635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
29645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearGutter: operation(null, function(gutterID) {
2966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var cm = this, doc = cm.doc, i = doc.first;
2967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      doc.iter(function(line) {
29685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
29695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          line.gutterMarkers[gutterID] = null;
29705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          regChange(cm, i, i + 1);
29715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
29725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
29735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
29745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
29755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
29765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addLineClass: operation(null, function(handle, where, cls) {
29785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return changeLine(this, handle, function(line) {
29795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
29805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!line[prop]) line[prop] = cls;
2981591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
29825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else line[prop] += " " + cls;
29835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
29845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
29855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
29865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeLineClass: operation(null, function(handle, where, cls) {
29885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return changeLine(this, handle, function(line) {
29895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
29905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var cur = line[prop];
29915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!cur) return false;
29925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (cls == null) line[prop] = null;
29935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
2994591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
2995591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          if (!found) return false;
2996591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          var end = found.index + found[0].length;
2997591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
29985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
29995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
30005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      });
30015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
30025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    addLineWidget: operation(null, function(handle, node, options) {
3004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return addLineWidget(this, handle, node, options);
30055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
30065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeLineWidget: function(widget) { widget.clear(); },
30085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lineInfo: function(line) {
30105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (typeof line == "number") {
3011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!isLine(this.doc, line)) return null;
30125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var n = line;
3013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        line = getLine(this.doc, line);
30145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!line) return null;
30155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
30165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var n = lineNo(line);
30175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (n == null) return null;
30185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
30195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
30205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
30215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              widgets: line.widgets};
30225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
30235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
30255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addWidget: function(pos, node, scroll, vert, horiz) {
30275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var display = this.display;
3028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      pos = cursorCoords(this, clipPos(this.doc, pos));
3029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var top = pos.bottom, left = pos.left;
30305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      node.style.position = "absolute";
30315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      display.sizer.appendChild(node);
3032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (vert == "over") {
3033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        top = pos.top;
3034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else if (vert == "above" || vert == "near") {
3035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
30365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
3037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Default to positioning above (if specified and possible); otherwise default to positioning below
3038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
30395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          top = pos.top - node.offsetHeight;
3040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (pos.bottom + node.offsetHeight <= vspace)
3041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          top = pos.bottom;
30425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (left + node.offsetWidth > hspace)
30435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          left = hspace - node.offsetWidth;
30445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
30455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      node.style.top = top + "px";
30465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      node.style.left = node.style.right = "";
30475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (horiz == "right") {
30485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        left = display.sizer.clientWidth - node.offsetWidth;
30495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node.style.right = "0px";
30505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
30515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (horiz == "left") left = 0;
30525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
30535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node.style.left = left + "px";
30545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
30555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (scroll)
3056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
30575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
30585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    triggerOnKeyDown: operation(null, onKeyDown),
30605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    execCommand: function(cmd) {return commands[cmd](this);},
30625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3063926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    findPosH: function(from, amount, unit, visually) {
3064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var dir = 1;
3065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (amount < 0) { dir = -1; amount = -amount; }
3066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cur = findPosH(this.doc, cur, dir, unit, visually);
3068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cur.hitSide) break;
3069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
3070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return cur;
3071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
3072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
30735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    moveH: operation(null, function(dir, unit) {
3074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sel = this.doc.sel, pos;
3075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (sel.shift || sel.extend || posEq(sel.from, sel.to))
3076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
3077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else
3078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        pos = dir < 0 ? sel.from : sel.to;
3079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      extendSelection(this.doc, pos, pos, dir);
30805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
30815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    deleteH: operation(null, function(dir, unit) {
3083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sel = this.doc.sel;
3084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
3085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
30865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      this.curOp.userSelChange = true;
30875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
30885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    findPosV: function(from, amount, unit, goalColumn) {
3090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var dir = 1, x = goalColumn;
3091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (amount < 0) { dir = -1; amount = -amount; }
3092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var coords = cursorCoords(this, cur, "div");
3094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (x == null) x = coords.left;
3095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else coords.left = x;
3096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cur = findPosV(this, coords, dir, unit);
3097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cur.hitSide) break;
30985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
3099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return cur;
3100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
31015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    moveV: operation(null, function(dir, unit) {
3103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sel = this.doc.sel;
3104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var pos = cursorCoords(this, sel.head, "div");
3105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (sel.goalColumn != null) pos.left = sel.goalColumn;
3106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var target = findPosV(this, pos, dir, unit);
3107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      extendSelection(this.doc, target, target, dir);
3110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      sel.goalColumn = pos.left;
31115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }),
31125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
311393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    toggleOverwrite: function(value) {
311493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (value != null && value == this.state.overwrite) return;
3115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (this.state.overwrite = !this.state.overwrite)
31165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.display.cursor.className += " CodeMirror-overwrite";
31175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else
31185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
31195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
3120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    hasFocus: function() { return this.state.focused; },
31215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    scrollTo: operation(null, function(x, y) {
3123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateScrollPos(this, x, y);
3124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }),
31255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getScrollInfo: function() {
31265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var scroller = this.display.scroller, co = scrollerCutOff;
31275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return {left: scroller.scrollLeft, top: scroller.scrollTop,
31285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
31295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
31305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
31315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
313253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    scrollIntoView: operation(null, function(pos, margin) {
3133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (typeof pos == "number") pos = Pos(pos, 0);
313453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (!margin) margin = 0;
313553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var coords = pos;
313653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!pos || pos.line != null) {
313853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
313953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this.curOp.scrollToPosMargin = margin;
314053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        coords = cursorCoords(this, this.curOp.scrollToPos);
3141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
314253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
314353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
314453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }),
31455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3146f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    setSize: operation(null, function(width, height) {
31475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      function interpret(val) {
31485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
31495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
31505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (width != null) this.display.wrapper.style.width = interpret(width);
31515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (height != null) this.display.wrapper.style.height = interpret(height);
3152f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      if (this.options.lineWrapping)
3153f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
3154f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      this.curOp.forceUpdate = true;
3155f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    }),
31565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    operation: function(f){return runInOp(this, f);},
31585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    refresh: operation(null, function() {
3160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      clearCaches(this);
3161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
3162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      regChange(this);
3163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }),
3164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    swapDoc: operation(null, function(doc) {
3166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var old = this.doc;
3167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      old.cm = null;
3168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      attachDoc(this, doc);
3169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      clearCaches(this);
317053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      resetInput(this, true);
3171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
3172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return old;
3173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }),
31745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getInputField: function(){return this.display.input;},
31765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getWrapperElement: function(){return this.display.wrapper;},
31775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getScrollerElement: function(){return this.display.scroller;},
31785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getGutterElement: function(){return this.display.gutters;}
31795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
3180e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  eventMixin(CodeMirror);
31815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // OPTION DEFAULTS
31835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var optionHandlers = CodeMirror.optionHandlers = {};
31855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // The default configuration options.
31875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var defaults = CodeMirror.defaults = {};
31885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function option(name, deflt, handle, notOnInit) {
31905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CodeMirror.defaults[name] = deflt;
31915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (handle) optionHandlers[name] =
31925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
31935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
31945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
31965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // These two are, on init, called from the constructor because they
31985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // have to be initialized before the editor can start at all.
3199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("value", "", function(cm, val) {
3200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.setValue(val);
3201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }, true);
3202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("mode", null, function(cm, val) {
3203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc.modeOption = val;
3204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    loadMode(cm);
3205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }, true);
32065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("indentUnit", 2, loadMode, true);
32085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("indentWithTabs", false);
32095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("smartIndent", true);
3210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("tabSize", 4, function(cm) {
3211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    loadMode(cm);
3212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clearCaches(cm);
3213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    regChange(cm);
3214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }, true);
32155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("electricChars", true);
3216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("rtlMoveVisually", !windows);
32175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("theme", "default", function(cm) {
32195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    themeChanged(cm);
3220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    guttersChanged(cm);
3221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }, true);
32225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("keyMap", "default", keyMapChanged);
32235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("extraKeys", null);
32245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("onKeyEvent", null);
32265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("onDragEvent", null);
32275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("lineWrapping", false, wrappingChanged, true);
32295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("gutters", [], function(cm) {
32305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setGuttersForLineNumbers(cm.options);
32315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    guttersChanged(cm);
32325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }, true);
3233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("fixedGutter", true, function(cm, val) {
3234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.refresh();
3236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }, true);
323793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  option("coverGutterNextToScrollbar", false, updateScrollbars, true);
32385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("lineNumbers", false, function(cm) {
32395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setGuttersForLineNumbers(cm.options);
32405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    guttersChanged(cm);
32415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }, true);
3242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("firstLineNumber", 1, guttersChanged, true);
3243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
3244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("showCursorWhenSelecting", false, updateSelection, true);
3245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
32465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("readOnly", false, function(cm, val) {
32475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
32485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (!val) resetInput(cm, true);
32495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  });
32505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("dragDrop", true);
32515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("cursorBlinkRate", 530);
325393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  option("cursorScrollMargin", 0);
32545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("cursorHeight", 1);
32555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("workTime", 100);
32565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("workDelay", 100);
32575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("flattenSpans", true);
32585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("pollInterval", 100);
3259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
326053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  option("historyEventDelay", 500);
32615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("viewportMargin", 10, function(cm){cm.refresh();}, true);
326253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
326353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  option("moveInputWithCursor", true, function(cm, val) {
326453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
326553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  });
32665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("tabindex", null, function(cm, val) {
32685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.display.input.tabIndex = val || "";
32695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  });
32705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  option("autofocus", null);
32715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // MODE DEFINITION AND QUERYING
32735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Known modes, by name and by MIME
32755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
32765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.defineMode = function(name, mode) {
32785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
32795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (arguments.length > 2) {
32805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      mode.dependencies = [];
32815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
32825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
32835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    modes[name] = mode;
32845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
32855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.defineMIME = function(mime, spec) {
32875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    mimeModes[mime] = spec;
32885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
32895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.resolveMode = function(spec) {
329193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
32925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      spec = mimeModes[spec];
329393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
329493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      var found = mimeModes[spec.name];
329593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      spec = createObj(found, spec);
329693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      spec.name = found.name;
329793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
32985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return CodeMirror.resolveMode("application/xml");
329993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
33005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof spec == "string") return {name: spec};
33015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else return spec || {name: "null"};
33025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
33035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.getMode = function(options, spec) {
3305e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    var spec = CodeMirror.resolveMode(spec);
33065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var mfactory = modes[spec.name];
33075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!mfactory) return CodeMirror.getMode(options, "text/plain");
33085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var modeObj = mfactory(options, spec);
33095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (modeExtensions.hasOwnProperty(spec.name)) {
33105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var exts = modeExtensions[spec.name];
3311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var prop in exts) {
3312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!exts.hasOwnProperty(prop)) continue;
3313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
3314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        modeObj[prop] = exts[prop];
3315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
33165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
33175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    modeObj.name = spec.name;
3318e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
33195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return modeObj;
33205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
33215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.defineMode("null", function() {
33235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return {token: function(stream) {stream.skipToEnd();}};
33245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  });
33255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.defineMIME("text/plain", "null");
33265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var modeExtensions = CodeMirror.modeExtensions = {};
33285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.extendMode = function(mode, properties) {
33295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
3330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    copyObj(properties, exts);
33315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
33325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // EXTENSIONS
33345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.defineExtension = function(name, func) {
33365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CodeMirror.prototype[name] = func;
33375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
333853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  CodeMirror.defineDocExtension = function(name, func) {
333953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    Doc.prototype[name] = func;
334053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  };
33415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.defineOption = option;
33425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var initHooks = [];
33445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
33455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3346e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  var helpers = CodeMirror.helpers = {};
3347e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  CodeMirror.registerHelper = function(type, name, value) {
3348e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3349e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    helpers[type][name] = value;
3350e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  };
3351e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
3352e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  // UTILITIES
3353e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
3354e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  CodeMirror.isWordChar = isWordChar;
3355e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
33565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // MODE STATE HANDLING
33575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Utility functions for working with state. Exported because modes
33595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // sometimes need to do this.
33605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function copyState(mode, state) {
33615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (state === true) return state;
33625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mode.copyState) return mode.copyState(state);
33635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var nstate = {};
33645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var n in state) {
33655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var val = state[n];
33665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (val instanceof Array) val = val.concat([]);
33675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      nstate[n] = val;
33685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
33695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return nstate;
33705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
33715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.copyState = copyState;
33725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function startState(mode, a1, a2) {
33745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return mode.startState ? mode.startState(a1, a2) : true;
33755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
33765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.startState = startState;
33775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.innerMode = function(mode, state) {
33795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (mode.innerMode) {
33805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var info = mode.innerMode(state);
3381f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      if (!info || info.mode == mode) break;
33825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      state = info.state;
33835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      mode = info.mode;
33845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
33855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return info || {mode: mode, state: state};
33865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
33875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // STANDARD COMMANDS
33895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var commands = CodeMirror.commands = {
3391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
33925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    killLine: function(cm) {
33935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
33945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!sel && cm.getLine(from.line).length == from.ch)
3395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
3396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
3397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
3398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    deleteLine: function(cm) {
3399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var l = cm.getCursor().line;
3400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
34015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
3402591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    delLineLeft: function(cm) {
3403591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var cur = cm.getCursor();
3404591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
3405591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
34065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    undo: function(cm) {cm.undo();},
34075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    redo: function(cm) {cm.redo();},
3408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
3409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
34105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goLineStart: function(cm) {
3411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.extendSelection(lineStart(cm, cm.getCursor().line));
34125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goLineStartSmart: function(cm) {
34145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var cur = cm.getCursor(), start = lineStart(cm, cur.line);
34155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var line = cm.getLineHandle(start.line);
34165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var order = getOrder(line);
34175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!order || order[0].level == 0) {
34185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var firstNonWS = Math.max(0, line.text.search(/\S/));
34195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
3420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
3421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else cm.extendSelection(start);
34225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goLineEnd: function(cm) {
3424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.extendSelection(lineEnd(cm, cm.getCursor().line));
3425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
3426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    goLineRight: function(cm) {
3427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
3429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
3430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    goLineLeft: function(cm) {
3431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
34335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goLineUp: function(cm) {cm.moveV(-1, "line");},
34355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goLineDown: function(cm) {cm.moveV(1, "line");},
34365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goPageUp: function(cm) {cm.moveV(-1, "page");},
34375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goPageDown: function(cm) {cm.moveV(1, "page");},
34385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goCharLeft: function(cm) {cm.moveH(-1, "char");},
34395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goCharRight: function(cm) {cm.moveH(1, "char");},
34405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goColumnLeft: function(cm) {cm.moveH(-1, "column");},
34415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goColumnRight: function(cm) {cm.moveH(1, "column");},
34425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goWordLeft: function(cm) {cm.moveH(-1, "word");},
3443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    goGroupRight: function(cm) {cm.moveH(1, "group");},
3444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    goGroupLeft: function(cm) {cm.moveH(-1, "group");},
34455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    goWordRight: function(cm) {cm.moveH(1, "word");},
34465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    delCharBefore: function(cm) {cm.deleteH(-1, "char");},
34475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    delCharAfter: function(cm) {cm.deleteH(1, "char");},
34485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    delWordBefore: function(cm) {cm.deleteH(-1, "word");},
34495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    delWordAfter: function(cm) {cm.deleteH(1, "word");},
3450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
3451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delGroupAfter: function(cm) {cm.deleteH(1, "group");},
34525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    indentAuto: function(cm) {cm.indentSelection("smart");},
34535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    indentMore: function(cm) {cm.indentSelection("add");},
34545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    indentLess: function(cm) {cm.indentSelection("subtract");},
3455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
34565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    defaultTab: function(cm) {
34575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (cm.somethingSelected()) cm.indentSelection("add");
3458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else cm.replaceSelection("\t", "end", "+input");
34595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    transposeChars: function(cm) {
34615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var cur = cm.getCursor(), line = cm.getLine(cur.line);
34625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (cur.ch > 0 && cur.ch < line.length - 1)
34635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
3464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
34655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newlineAndIndent: function(cm) {
3467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      operation(cm, function() {
3468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.replaceSelection("\n", "end", "+input");
3469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.indentLine(cm.getCursor().line, null, true);
3470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      })();
34715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    toggleOverwrite: function(cm) {cm.toggleOverwrite();}
34735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
34745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // STANDARD KEYMAPS
34765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var keyMap = CodeMirror.keyMap = {};
34785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  keyMap.basic = {
34795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
34805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
34815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
34825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
34835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
34845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Note that the save and find-related commands aren't defined by
34855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // default. Unknown commands are simply ignored.
34865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  keyMap.pcDefault = {
34875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
34885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
3489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
3490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
34915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
34925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
34935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fallthrough: "basic"
34945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
34955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  keyMap.macDefault = {
34965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
3497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
3498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
35005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3501591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
35025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fallthrough: ["basic", "emacsy"]
35035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
35045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
35055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  keyMap.emacsy = {
35065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
35075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
3508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
35095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
35105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
35115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // KEYMAP DISPATCH
35135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function getKeyMap(val) {
35155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof val == "string") return keyMap[val];
35165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else return val;
35175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
35185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3519926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function lookupKey(name, maps, handle) {
35205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function lookup(map) {
35215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      map = getKeyMap(map);
35225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var found = map[name];
3523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (found === false) return "stop";
35245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (found != null && handle(found)) return true;
3525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (map.nofallthrough) return "stop";
3526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
35275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var fallthrough = map.fallthrough;
35285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (fallthrough == null) return false;
35295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (Object.prototype.toString.call(fallthrough) != "[object Array]")
35305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return lookup(fallthrough);
35315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0, e = fallthrough.length; i < e; ++i) {
3532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var done = lookup(fallthrough[i]);
3533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (done) return done;
35345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
35355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return false;
35365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < maps.length; ++i) {
3539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var done = lookup(maps[i]);
35405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (done) return done != "stop";
3541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
35425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
35435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function isModifierKey(event) {
3544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var name = keyNames[event.keyCode];
35455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
35465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function keyName(event, noShift) {
354853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (opera && event.keyCode == 34 && event["char"]) return false;
3549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var name = keyNames[event.keyCode];
3550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == null || event.altGraphKey) return false;
3551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (event.altKey) name = "Alt-" + name;
3552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
3553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
3554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!noShift && event.shiftKey) name = "Shift-" + name;
3555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return name;
3556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
3557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  CodeMirror.lookupKey = lookupKey;
35585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.isModifierKey = isModifierKey;
3559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  CodeMirror.keyName = keyName;
35605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // FROMTEXTAREA
35625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.fromTextArea = function(textarea, options) {
35645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!options) options = {};
35655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    options.value = textarea.value;
35665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!options.tabindex && textarea.tabindex)
35675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      options.tabindex = textarea.tabindex;
3568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!options.placeholder && textarea.placeholder)
3569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      options.placeholder = textarea.placeholder;
35705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Set autofocus to true if this textarea is focused, or if it has
35715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // autofocus and no other element is focused.
35725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (options.autofocus == null) {
35735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var hasFocus = document.body;
35745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // doc.activeElement occasionally throws on IE
35755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      try { hasFocus = document.activeElement; } catch(e) {}
35765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      options.autofocus = hasFocus == textarea ||
35775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
35785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
35795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function save() {textarea.value = cm.getValue();}
35815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (textarea.form) {
35825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      on(textarea.form, "submit", save);
3583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // Deplorable hack to make the submit method do the right thing.
3584926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!options.leaveSubmitMethodAlone) {
3585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var form = textarea.form, realSubmit = form.submit;
3586926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        try {
3587926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var wrappedSubmit = form.submit = function() {
3588926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            save();
3589926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            form.submit = realSubmit;
3590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            form.submit();
3591926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            form.submit = wrappedSubmit;
3592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          };
3593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } catch(e) {}
35945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
35955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
35965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    textarea.style.display = "none";
35985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var cm = CodeMirror(function(node) {
35995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      textarea.parentNode.insertBefore(node, textarea.nextSibling);
36005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }, options);
36015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.save = save;
36025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.getTextArea = function() { return textarea; };
36035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cm.toTextArea = function() {
36045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      save();
36055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      textarea.parentNode.removeChild(cm.getWrapperElement());
36065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      textarea.style.display = "";
36075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (textarea.form) {
36085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        off(textarea.form, "submit", save);
36095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (typeof textarea.form.submit == "function")
36105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          textarea.form.submit = realSubmit;
36115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
36125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
36135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return cm;
36145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
36155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // STRING STREAM
36175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Fed to the mode parsers, provides helper functions to make
36195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // parsers more succinct.
36205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // The character stream used by a mode's parser.
36225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function StringStream(string, tabSize) {
36235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.pos = this.start = 0;
36245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.string = string;
36255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.tabSize = tabSize || 8;
3626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.lastColumnPos = this.lastColumnValue = 0;
36275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
36285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  StringStream.prototype = {
36305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    eol: function() {return this.pos >= this.string.length;},
36315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sol: function() {return this.pos == 0;},
36325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    peek: function() {return this.string.charAt(this.pos) || undefined;},
36335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    next: function() {
36345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (this.pos < this.string.length)
36355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this.string.charAt(this.pos++);
36365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
36375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    eat: function(match) {
36385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var ch = this.string.charAt(this.pos);
36395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (typeof match == "string") var ok = ch == match;
36405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else var ok = ch && (match.test ? match.test(ch) : match(ch));
36415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (ok) {++this.pos; return ch;}
36425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
36435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    eatWhile: function(match) {
36445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var start = this.pos;
36455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      while (this.eat(match)){}
36465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return this.pos > start;
36475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
36485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    eatSpace: function() {
36495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var start = this.pos;
36505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
36515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return this.pos > start;
36525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
36535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    skipToEnd: function() {this.pos = this.string.length;},
36545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    skipTo: function(ch) {
36555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var found = this.string.indexOf(ch, this.pos);
36565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (found > -1) {this.pos = found; return true;}
36575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
36585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    backUp: function(n) {this.pos -= n;},
3659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    column: function() {
3660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (this.lastColumnPos < this.start) {
3661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
3662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.lastColumnPos = this.start;
3663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
3664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return this.lastColumnValue;
3665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
36665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    indentation: function() {return countColumn(this.string, null, this.tabSize);},
36675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    match: function(pattern, consume, caseInsensitive) {
36685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (typeof pattern == "string") {
36695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
3670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var substr = this.string.substr(this.pos, pattern.length);
3671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cased(substr) == cased(pattern)) {
36725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (consume !== false) this.pos += pattern.length;
36735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          return true;
36745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
36755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
36765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var match = this.string.slice(this.pos).match(pattern);
36775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (match && match.index > 0) return null;
36785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (match && consume !== false) this.pos += match[0].length;
36795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return match;
36805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
36815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
36825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    current: function(){return this.string.slice(this.start, this.pos);}
36835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
36845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.StringStream = StringStream;
36855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // TEXTMARKERS
36875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function TextMarker(doc, type) {
36895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.lines = [];
36905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.type = type;
3691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.doc = doc;
36925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
3693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  CodeMirror.TextMarker = TextMarker;
3694e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  eventMixin(TextMarker);
36955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  TextMarker.prototype.clear = function() {
36975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (this.explicitlyCleared) return;
3698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cm = this.doc.cm, withOp = cm && !cm.curOp;
3699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (withOp) startOperation(cm);
3700f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (hasHandler(this, "clear")) {
3701f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      var found = this.find();
3702f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      if (found) signalLater(this, "clear", found.from, found.to);
3703f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    }
37045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var min = null, max = null;
37055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < this.lines.length; ++i) {
37065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var line = this.lines[i];
37075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var span = getMarkedSpanFor(line.markedSpans, this);
37085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (span.to != null) max = lineNo(line);
37095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      line.markedSpans = removeMarkedSpan(line.markedSpans, span);
37105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (span.from != null)
37115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        min = lineNo(line);
3712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
3713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        updateLineHeight(line, textHeight(cm.display));
3714926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
3716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
3717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (len > cm.display.maxLineLength) {
3718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.display.maxLine = visual;
3719926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.display.maxLineLength = len;
3720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cm.display.maxLineChanged = true;
3721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
37225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (min != null && cm) regChange(cm, min, max + 1);
37255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.lines.length = 0;
37265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.explicitlyCleared = true;
37275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (this.atomic && this.doc.cantEdit) {
3728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.doc.cantEdit = false;
3729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm) reCheckSelection(cm);
37305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (withOp) endOperation(cm);
37325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
37335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
37345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  TextMarker.prototype.find = function() {
37355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var from, to;
37365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < this.lines.length; ++i) {
37375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var line = this.lines[i];
37385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var span = getMarkedSpanFor(line.markedSpans, this);
37395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (span.from != null || span.to != null) {
37405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var found = lineNo(line);
3741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (span.from != null) from = Pos(found, span.from);
3742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (span.to != null) to = Pos(found, span.to);
37435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
37445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
37455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (this.type == "bookmark") return from;
37465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return from && {from: from, to: to};
37475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
37485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
374993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  TextMarker.prototype.changed = function() {
375093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var pos = this.find(), cm = this.doc.cm;
375193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (!pos || !cm) return;
3752f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (this.type != "bookmark") pos = pos.from;
3753f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    var line = getLine(this.doc, pos.line);
375493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    clearCachedMeasurement(cm, line);
3755f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {
375693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
375793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
375893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        break;
375993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      }
3760f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      runInOp(cm, function() {
3761f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
3762f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      });
376393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
3764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  };
3765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  TextMarker.prototype.attachLine = function(line) {
3767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this.lines.length && this.doc.cm) {
3768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var op = this.doc.cm.curOp;
3769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
3770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
3771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.lines.push(line);
3773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  };
3774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  TextMarker.prototype.detachLine = function(line) {
3775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.lines.splice(indexOf(this.lines, line), 1);
3776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this.lines.length && this.doc.cm) {
3777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var op = this.doc.cm.curOp;
3778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
3779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  };
3781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function markText(doc, from, to, options, type) {
3783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (options && options.shared) return markTextShared(doc, from, to, options, type);
3784926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
3785926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var marker = new TextMarker(doc, type);
37875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (type == "range" && !posLess(from, to)) return marker;
3788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (options) copyObj(options, marker);
37895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (marker.replacedWith) {
37905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      marker.collapsed = true;
37915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
37925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
37935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
37945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (marker.collapsed) sawCollapsedSpans = true;
37955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
379653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (marker.addToHistory)
379753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      addToHistory(doc, {from: from, to: to, origin: "markText"},
379853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                   {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
379953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
38015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    doc.iter(curLine, to.line + 1, function(line) {
3802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
3803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        updateMaxLine = true;
38045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var span = {from: null, to: null, marker: marker};
38055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      size += line.text.length;
38065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
38075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
38085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (marker.collapsed) {
38095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
38105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
38115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else updateLineHeight(line, 0);
38125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
38135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      addMarkedSpan(line, span);
38145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      ++curLine;
38155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
3816926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
3817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
3818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
38195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
382053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
382153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
38225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (marker.readOnly) {
38235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      sawReadOnlySpans = true;
3824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (doc.history.done.length || doc.history.undone.length)
3825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        doc.clearHistory();
38265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
38275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (marker.collapsed) {
38285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (collapsedAtStart != collapsedAtEnd)
38295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throw new Error("Inserting collapsed marker overlapping an existing one");
38305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      marker.size = size;
38315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      marker.atomic = true;
38325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cm) {
3834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (updateMaxLine) cm.curOp.updateMaxLine = true;
3835e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
3836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        regChange(cm, from.line, to.line + 1);
3837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (marker.atomic) reCheckSelection(cm);
3838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
38395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return marker;
38405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
38415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // SHARED TEXTMARKERS
3843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function SharedTextMarker(markers, primary) {
3845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.markers = markers;
3846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.primary = primary;
3847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0, me = this; i < markers.length; ++i) {
3848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      markers[i].parent = this;
3849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      on(markers[i], "clear", function(){me.clear();});
3850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
3852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  CodeMirror.SharedTextMarker = SharedTextMarker;
3853e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  eventMixin(SharedTextMarker);
3854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  SharedTextMarker.prototype.clear = function() {
3856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.explicitlyCleared) return;
3857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.explicitlyCleared = true;
3858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < this.markers.length; ++i)
3859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.markers[i].clear();
3860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    signalLater(this, "clear");
3861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  };
3862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  SharedTextMarker.prototype.find = function() {
3863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.primary.find();
3864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  };
3865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function markTextShared(doc, from, to, options, type) {
3867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    options = copyObj(options);
3868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    options.shared = false;
3869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var markers = [markText(doc, from, to, options, type)], primary = markers[0];
3870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var widget = options.replacedWith;
3871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    linkedDocs(doc, function(doc) {
3872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (widget) options.replacedWith = widget.cloneNode(true);
3873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
3874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0; i < doc.linked.length; ++i)
3875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (doc.linked[i].isParent) return;
3876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      primary = lst(markers);
3877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
3878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new SharedTextMarker(markers, primary);
3879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
3880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
38815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // TEXTMARKER SPANS
38825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
38835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function getMarkedSpanFor(spans, marker) {
38845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (spans) for (var i = 0; i < spans.length; ++i) {
38855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var span = spans[i];
38865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (span.marker == marker) return span;
38875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
38885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
38895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function removeMarkedSpan(spans, span) {
38905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var r, i = 0; i < spans.length; ++i)
38915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (spans[i] != span) (r || (r = [])).push(spans[i]);
38925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return r;
38935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
38945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function addMarkedSpan(line, span) {
38955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
3896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    span.marker.attachLine(line);
38975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
38985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function markedSpansBefore(old, startCh, isInsert) {
39005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (old) for (var i = 0, nw; i < old.length; ++i) {
39015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var span = old[i], marker = span.marker;
39025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
39045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
39055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        (nw || (nw = [])).push({from: span.from,
39065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                to: endsAfter ? null : span.to,
39075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                marker: marker});
39085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
39095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
39105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return nw;
39115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
39125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function markedSpansAfter(old, endCh, isInsert) {
39145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (old) for (var i = 0, nw; i < old.length; ++i) {
39155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var span = old[i], marker = span.marker;
39165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
3917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
39185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
39195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
39205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                to: span.to == null ? null : span.to - endCh,
39215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                marker: marker});
39225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
39235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
39245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return nw;
39255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
39265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function stretchSpansOverChange(doc, change) {
3928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
3929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
3930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!oldFirst && !oldLast) return null;
3931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
39335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Get the spans that 'stick out' on both sides
3934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var first = markedSpansBefore(oldFirst, startCh, isInsert);
3935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var last = markedSpansAfter(oldLast, endCh, isInsert);
39365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Next, merge those two ends
3938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
39395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (first) {
39405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Fix up .to properties of first
39415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < first.length; ++i) {
39425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var span = first[i];
39435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (span.to == null) {
39445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var found = getMarkedSpanFor(last, span.marker);
39455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (!found) span.to = startCh;
39465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          else if (sameLine) span.to = found.to == null ? null : found.to + offset;
39475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
39485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
39495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
39505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (last) {
39515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Fix up .from in last (or move them into first in case of sameLine)
39525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < last.length; ++i) {
39535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var span = last[i];
39545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (span.to != null) span.to += offset;
39555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (span.from == null) {
39565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var found = getMarkedSpanFor(first, span.marker);
39575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (!found) {
39585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            span.from = offset;
39595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (sameLine) (first || (first = [])).push(span);
39605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
39615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
39625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          span.from += offset;
39635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (sameLine) (first || (first = [])).push(span);
39645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
39655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
39665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
39675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (sameLine && first) {
39685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      // Make sure we didn't create any zero-length spans
39695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      for (var i = 0; i < first.length; ++i)
39705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
39715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)          first.splice(i--, 1);
39725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (!first.length) first = null;
39735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
39745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var newMarkers = [first];
39765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!sameLine) {
39775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Fill gap with whole-line-spans
3978926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var gap = change.text.length - 2, gapMarkers;
39795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (gap > 0 && first)
39805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < first.length; ++i)
39815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (first[i].to == null)
39825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
39835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < gap; ++i)
3984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        newMarkers.push(gapMarkers);
3985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      newMarkers.push(last);
39865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
39875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newMarkers;
39885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
39895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function mergeOldSpans(doc, change) {
3991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var old = getOldSpans(doc, change);
3992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var stretched = stretchSpansOverChange(doc, change);
3993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!old) return stretched;
3994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!stretched) return old;
3995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < old.length; ++i) {
3997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var oldCur = old[i], stretchCur = stretched[i];
3998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (oldCur && stretchCur) {
3999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        spans: for (var j = 0; j < stretchCur.length; ++j) {
4000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var span = stretchCur[j];
4001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          for (var k = 0; k < oldCur.length; ++k)
4002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (oldCur[k].marker == span.marker) continue spans;
4003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          oldCur.push(span);
4004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
4005926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else if (stretchCur) {
4006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        old[i] = stretchCur;
4007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return old;
4010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
40125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function removeReadOnlyRanges(doc, from, to) {
40135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var markers = null;
40145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    doc.iter(from.line, to.line + 1, function(line) {
40155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
40165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var mark = line.markedSpans[i].marker;
40175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
40185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          (markers || (markers = [])).push(mark);
40195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
40205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
40215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!markers) return null;
40225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var parts = [{from: from, to: to}];
40235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < markers.length; ++i) {
4024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var mk = markers[i], m = mk.find();
40255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var j = 0; j < parts.length; ++j) {
40265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var p = parts[j];
4027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
40285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var newParts = [j, 1];
4029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
4030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          newParts.push({from: p.from, to: m.from});
4031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
4032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          newParts.push({from: m.to, to: p.to});
40335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        parts.splice.apply(parts, newParts);
40345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        j += newParts.length - 1;
40355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
40365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return parts;
40385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
40395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function collapsedSpanAt(line, ch) {
40415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var sps = sawCollapsedSpans && line.markedSpans, found;
40425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
40435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      sp = sps[i];
40445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!sp.marker.collapsed) continue;
40455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if ((sp.from == null || sp.from < ch) &&
40465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          (sp.to == null || sp.to > ch) &&
40475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          (!found || found.width < sp.marker.width))
40485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        found = sp.marker;
40495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return found;
40515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
40525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
40535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
40545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function visualLine(doc, line) {
4056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var merged;
4057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (merged = collapsedSpanAtStart(line))
4058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      line = getLine(doc, merged.find().from.line);
4059926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return line;
4060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4061926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4062926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function lineIsHidden(doc, line) {
40635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var sps = sawCollapsedSpans && line.markedSpans;
40645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
40655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      sp = sps[i];
40665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!sp.marker.collapsed) continue;
40675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (sp.from == null) return true;
40685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (sp.marker.replacedWith) continue;
4069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
40705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
40715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
4073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function lineIsHiddenInner(doc, line, span) {
4074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (span.to == null) {
4075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var end = span.marker.find().to, endLine = getLine(doc, end.line);
4076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
4077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (span.marker.inclusiveRight && span.to == line.text.length)
40795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return true;
40805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var sp, i = 0; i < line.markedSpans.length; ++i) {
40815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      sp = line.markedSpans[i];
40825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
40835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          lineIsHiddenInner(doc, line, sp)) return true;
40855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
40875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function detachMarkedSpans(line) {
40895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var spans = line.markedSpans;
40905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!spans) return;
4091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < spans.length; ++i)
4092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      spans[i].marker.detachLine(line);
40935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    line.markedSpans = null;
40945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
40955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function attachMarkedSpans(line, spans) {
40975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!spans) return;
40985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < spans.length; ++i)
4099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      spans[i].marker.attachLine(line);
41005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    line.markedSpans = spans;
41015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
41025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // LINE WIDGETS
4104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
4106e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (options) for (var opt in options) if (options.hasOwnProperty(opt))
4107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this[opt] = options[opt];
4108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.cm = cm;
4109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.node = node;
4110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  };
4111e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  eventMixin(LineWidget);
4112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function widgetOperation(f) {
4113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return function() {
4114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var withOp = !this.cm.curOp;
4115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (withOp) startOperation(this.cm);
4116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      try {var result = f.apply(this, arguments);}
4117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      finally {if (withOp) endOperation(this.cm);}
4118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return result;
4119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
4120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  LineWidget.prototype.clear = widgetOperation(function() {
4122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var ws = this.line.widgets, no = lineNo(this.line);
4123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (no == null || !ws) return;
4124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
4125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!ws.length) this.line.widgets = null;
4126e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
4127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
4128e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
4129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    regChange(this.cm, no, no + 1);
4130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  });
4131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  LineWidget.prototype.changed = widgetOperation(function() {
4132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var oldH = this.height;
4133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.height = null;
4134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var diff = widgetHeight(this) - oldH;
4135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!diff) return;
4136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    updateLineHeight(this.line, this.line.height + diff);
4137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var no = lineNo(this.line);
4138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    regChange(this.cm, no, no + 1);
4139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  });
4140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function widgetHeight(widget) {
4142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (widget.height != null) return widget.height;
4143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
4144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
4145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return widget.height = widget.node.offsetHeight;
4146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function addLineWidget(cm, handle, node, options) {
4149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var widget = new LineWidget(cm, node, options);
4150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (widget.noHScroll) cm.display.alignWidgets = true;
4151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    changeLine(cm, handle, function(line) {
4152e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      var widgets = line.widgets || (line.widgets = []);
4153e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (widget.insertAt == null) widgets.push(widget);
4154e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
4155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      widget.line = line;
4156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
4157e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
4158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        updateLineHeight(line, line.height + widgetHeight(widget));
4159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (aboveVisible) addToScrollPos(cm, 0, widget.height);
4160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return true;
4162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
4163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return widget;
4164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
41665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // LINE DATA STRUCTURE
41675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Line objects. These hold state related to a line, including
41695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // highlighting info (the styles array).
4170e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
4171e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this.text = text;
4172e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    attachMarkedSpans(this, markedSpans);
4173e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this.height = estimateHeight ? estimateHeight(this) : 1;
4174e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  };
4175e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  eventMixin(Line);
41765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function updateLine(line, text, markedSpans, estimateHeight) {
41785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    line.text = text;
4179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (line.stateAfter) line.stateAfter = null;
4180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (line.styles) line.styles = null;
41815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (line.order != null) line.order = null;
41825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    detachMarkedSpans(line);
41835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    attachMarkedSpans(line, markedSpans);
4184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var estHeight = estimateHeight ? estimateHeight(line) : 1;
4185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (estHeight != line.height) updateLineHeight(line, estHeight);
41865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
41875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function cleanUpLine(line) {
41895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    line.parent = null;
41905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    detachMarkedSpans(line);
41915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
41925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Run the given mode's parser over a line, update the styles
41945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // array, which contains alternating fragments of text and CSS
41955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // classes.
4196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function runMode(cm, text, mode, state, f) {
4197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var flattenSpans = mode.flattenSpans;
4198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    var curStart = 0, curStyle = null;
420053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    var stream = new StringStream(text, cm.options.tabSize), style;
4201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (text == "" && mode.blankLine) mode.blankLine(state);
42025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (!stream.eol()) {
420353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (stream.pos > cm.options.maxHighlightLength) {
4204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        flattenSpans = false;
4205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Webkit seems to refuse to render text nodes longer than 57444 characters
4206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        stream.pos = Math.min(text.length, stream.start + 50000);
4207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        style = null;
420853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      } else {
420953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        style = mode.token(stream, state);
4210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
42115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!flattenSpans || curStyle != style) {
4212591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (curStart < stream.start) f(stream.start, curStyle);
4213591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        curStart = stream.start; curStyle = style;
4214591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      }
4215591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      stream.start = stream.pos;
42165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4217591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (curStart < stream.pos) f(stream.pos, curStyle);
4218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function highlightLine(cm, line, state) {
4221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // A styles array always starts with a number identifying the
4222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // mode/overlays that it is based on (for easy invalidation).
4223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var st = [cm.state.modeGen];
4224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Compute the base array of styles
4225591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
4226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Run overlays, adjust style array.
4228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var o = 0; o < cm.state.overlays.length; ++o) {
4229591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var overlay = cm.state.overlays[o], i = 1, at = 0;
4230591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      runMode(cm, line.text, overlay.mode, true, function(end, style) {
4231591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var start = i;
4232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Ensure there's a token end at the current position, and that i points at it
4233591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        while (at < end) {
4234591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          var i_end = st[i];
4235591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          if (i_end > end)
4236591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            st.splice(i, 1, end, st[i+1], i_end);
4237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          i += 2;
4238591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          at = Math.min(end, i_end);
4239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
4240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!style) return;
4241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (overlay.opaque) {
4242591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          st.splice(start, i - start, end, style);
4243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          i = start + 2;
4244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else {
4245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          for (; start < i; start += 2) {
4246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var cur = st[start+1];
4247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            st[start+1] = cur ? cur + " " + style : style;
4248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          }
4249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
4250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      });
42515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return st;
4254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function getLineStyles(cm, line) {
4257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!line.styles || line.styles[0] != cm.state.modeGen)
4258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
4259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return line.styles;
42605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
42615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Lightweight form of highlight -- proceed over this line and
42635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // update state, but don't save a style array.
42645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function processLine(cm, line, state) {
4265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var mode = cm.doc.mode;
42665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var stream = new StringStream(line.text, cm.options.tabSize);
42675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (line.text == "" && mode.blankLine) mode.blankLine(state);
426853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
42695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      mode.token(stream, state);
42705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      stream.start = stream.pos;
42715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
42725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
42735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var styleToClassCache = {};
42755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function styleToClass(style) {
42765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!style) return null;
42775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return styleToClassCache[style] ||
42785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
42795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
42805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4281f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  function lineContent(cm, realLine, measure, copyWidgets, from, to) {
4282591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    var merged, line = realLine, empty = true;
4283591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    while (merged = collapsedSpanAtStart(line))
4284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      line = getLine(cm.doc, merged.find().from.line);
42855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4286f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    var builder = {pre: elt("pre"), col: 0, pos: 0,
4287f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                   measure: null, measuredSomething: false, cm: cm, from: from, to: to,
4288f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                   copyWidgets: copyWidgets};
42895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (line.textClass) builder.pre.className = line.textClass;
42905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    do {
42925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (line.text) empty = false;
42935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      builder.measure = line == realLine && measure;
42945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      builder.pos = 0;
42955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if ((ie || webkit) && cm.getOption("lineWrapping"))
4297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        builder.addToken = buildTokenSplitSpaces(builder.addToken);
4298591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      var next = insertLineContent(line, builder, getLineStyles(cm, line));
4299591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (measure && line == realLine && !builder.measuredSomething) {
4300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4301591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        builder.measuredSomething = true;
43025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
43035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      if (next) line = getLine(cm.doc, next.to.line);
43045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } while (next);
43055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4306591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (measure && !builder.measuredSomething && !measure[0])
43075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
43095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      builder.pre.appendChild(document.createTextNode("\u00a0"));
43105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var order;
4312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Work around problem with the reported dimensions of single-char
4313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // direction spans on IE (issue #1129). See also the comment in
4314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // cursorCoords.
4315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (measure && ie && (order = getOrder(line))) {
4316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var l = order.length - 1;
4317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (order[l].from == order[l].to) --l;
4318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var last = order[l], prev = order[l - 1];
4319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (last.from + 1 == last.to && prev && last.level < prev.level) {
4320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var span = measure[builder.pos - 1];
4321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
4322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                                               span.nextSibling);
4323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    signal(cm, "renderLine", cm, realLine, builder.pre);
43275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return builder.pre;
43285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
43295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
4331e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  function buildToken(builder, text, style, startStyle, endStyle, title) {
43325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!text) return;
43335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!tokenSpecialChars.test(text)) {
43345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      builder.col += text.length;
43355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var content = document.createTextNode(text);
43365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
43375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var content = document.createDocumentFragment(), pos = 0;
43385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      while (true) {
43395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        tokenSpecialChars.lastIndex = pos;
43405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var m = tokenSpecialChars.exec(text);
43415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var skipped = m ? m.index - pos : text.length - pos;
43425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (skipped) {
43435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
43445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          builder.col += skipped;
43455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
43465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m) break;
43475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pos += skipped + 1;
43485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m[0] == "\t") {
43495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
43505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
43515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          builder.col += tabWidth;
43525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
43535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var token = elt("span", "\u2022", "cm-invalidchar");
43545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          token.title = "\\u" + m[0].charCodeAt(0).toString(16);
43555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          content.appendChild(token);
43565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          builder.col += 1;
43575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
43585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
43595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
43605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (style || startStyle || endStyle || builder.measure) {
43615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var fullStyle = style || "";
43625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (startStyle) fullStyle += startStyle;
43635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (endStyle) fullStyle += endStyle;
4364e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      var token = elt("span", [content], fullStyle);
4365e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (title) token.title = title;
4366e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return builder.pre.appendChild(token);
43675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
43685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    builder.pre.appendChild(content);
43695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
43705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
43715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
4372591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    //FIXME consider 2-byte chars
4373591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (builder.from || builder.to) {
4374591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (builder.from >= builder.pos + text.length) {
4375591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        buildToken(builder, text, style, startStyle, endStyle);
4376591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        builder.pos += text.length;
4377591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return;
4378591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      }
4379591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
4380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var wrapping = builder.cm.options.lineWrapping;
43815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < text.length; ++i) {
4382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var ch = text.charAt(i), start = i == 0;
4383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ch = text.slice(i, i + 2);
4385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++i;
438693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      } else if (i && wrapping && spanAffectsWrapping(text, i)) {
43875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        builder.pre.appendChild(elt("wbr"));
4388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4389e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      var old = builder.measure[builder.pos];
4390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var span = builder.measure[builder.pos] =
4391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        buildToken(builder, ch, style,
4392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                   start && startStyle, i == text.length - 1 && endStyle);
4393e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (old) span.leftSide = old.leftSide || old;
4394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // In IE single-space nodes wrap differently than spaces
4395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // embedded in larger text nodes, except when set to
4396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // white-space: normal (issue #1268).
4397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
4399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        span.style.whiteSpace = "normal";
4400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      builder.pos += ch.length;
44015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4402591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (text.length) builder.measuredSomething = true;
44035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
44045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function buildTokenSplitSpaces(inner) {
4406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function split(old) {
4407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var out = " ";
4408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
4409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      out += " ";
4410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return out;
4411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4412e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return function(builder, text, style, startStyle, endStyle, title) {
4413e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
4414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
4415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4417e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
4418e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    var widget = !ignoreWidget && marker.replacedWith;
44195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (widget) {
4420f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      if (builder.copyWidgets) widget = widget.cloneNode(true);
4421e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      builder.pre.appendChild(widget);
4422591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (builder.measure) {
4423e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (size) {
4424e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          builder.measure[builder.pos] = widget;
4425e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        } else {
4426e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
4427e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          if (marker.type != "bookmark" || marker.insertLeft)
4428e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            builder.pre.insertBefore(elt, widget);
4429e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          else
4430e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            builder.pre.appendChild(elt);
4431e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
4432591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        builder.measuredSomething = true;
44335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
44345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
44355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    builder.pos += size;
44365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
44375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Outputs a number of spans to make up a line, taking highlighting
44395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // and marked text into account.
4440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function insertLineContent(line, builder, styles) {
4441591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    var spans = line.markedSpans, allText = line.text, at = 0;
44425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!spans) {
4443591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      if (builder.to || builder.from) {
4444591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (var i = 1; i < styles.length && (!builder.to || builder.pos < builder.to); i+=2) {
4445591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          var text = allText.slice(at, at = styles[i]);
4446591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          var textLength = text.length;
4447591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          var resolvedStyles = styleToClass(styles[i+1]);
4448591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          if (builder.pos + textLength <= builder.from) {
4449591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            builder.addToken(builder, text, resolvedStyles);
4450591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            continue;
4451591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          }
4452591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          // if we are not inside, but will get over it
4453591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          if (builder.pos < builder.from && builder.pos + textLength > builder.from) {
4454591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var overlap = builder.from - builder.pos;
4455591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            builder.addToken(builder, text.substring(0, overlap), resolvedStyles);
4456591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            text = text.substring(overlap);
4457591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          }
4458591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          builder.addToken(builder, text.substr(0, Math.min(builder.to - builder.from, text.length)), resolvedStyles);
4459591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
4460591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      } else {
4461591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (var i = 1; i < styles.length; i+=2)
4462591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch          builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
4463591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      }
44645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return;
44655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
44665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4467591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    var len = allText.length, pos = 0, i = 1, text = "", style;
4468e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
44695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (;;) {
44705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (nextChange == pos) { // Update current marker set
4471e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        spanStyle = spanEndStyle = spanStartStyle = title = "";
44725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        collapsed = null; nextChange = Infinity;
4473f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        var foundBookmarks = [];
44745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var j = 0; j < spans.length; ++j) {
44755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var sp = spans[j], m = sp.marker;
44765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
44775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
44785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (m.className) spanStyle += " " + m.className;
44795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
44805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4481e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (m.title && !title) title = m.title;
4482591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
44835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              collapsed = sp;
44845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          } else if (sp.from > pos && nextChange > sp.from) {
44855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            nextChange = sp.from;
44865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
4487f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)          if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);
44885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
44895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (collapsed && (collapsed.from || 0) == pos) {
44905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
4491e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                             collapsed.marker, collapsed.from == null);
44925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (collapsed.to == null) return collapsed.marker.find();
44935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4494f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
4495f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)          buildCollapsedSpan(builder, 0, foundBookmarks[j]);
44965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
44975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (pos >= len) break;
44985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var upto = Math.min(len, nextChange);
45005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      while (true) {
45015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (text) {
45025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var end = pos + text.length;
45035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (!collapsed) {
45045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var tokenText = end > upto ? text.slice(0, upto - pos) : text;
4505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
4506e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
4507591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (builder.to && builder.pos >= builder.to)
4508591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch              return;
45095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
45105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
45115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          pos = end;
45125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          spanStartStyle = "";
45135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4514591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        text = allText.slice(at, at = styles[i++]);
4515591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        style = styleToClass(styles[i++]);
45165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
45175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
45185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
45195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // DOCUMENT DATA STRUCTURE
45215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
4523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
4524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function update(line, text, spans) {
4525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      updateLine(line, text, spans, estimateHeight);
4526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      signalLater(line, "change", line, change);
4527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var from = change.from, to = change.to, text = change.text;
4530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
4531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
4532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // First adjust the line structure
4534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (from.ch == 0 && to.ch == 0 && lastText == "") {
4535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // This is a whole-line replace. Treated specially to make
4536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // sure line objects move the way they are supposed to.
4537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
4538e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        added.push(new Line(text[i], spansFor(i), estimateHeight));
4539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      update(lastLine, lastLine.text, lastSpans);
4540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (nlines) doc.remove(from.line, nlines);
4541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (added.length) doc.insert(from.line, added);
4542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (firstLine == lastLine) {
4543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (text.length == 1) {
4544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else {
4546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
4547e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch          added.push(new Line(text[i], spansFor(i), estimateHeight));
4548e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        doc.insert(from.line + 1, added);
4551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (text.length == 1) {
4553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
4554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      doc.remove(from.line + 1, nlines);
4555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
4556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4558926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
4559e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        added.push(new Line(text[i], spansFor(i), estimateHeight));
4560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
4561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      doc.insert(from.line + 1, added);
4562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    signalLater(doc, "change", doc, change);
4565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setSelection(doc, selAfter.anchor, selAfter.head, null, true);
4566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
45685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function LeafChunk(lines) {
45695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.lines = lines;
45705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.parent = null;
45715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
45725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      lines[i].parent = this;
45735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      height += lines[i].height;
45745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
45755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.height = height;
45765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
45775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  LeafChunk.prototype = {
45795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    chunkSize: function() { return this.lines.length; },
4580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeInner: function(at, n) {
45815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = at, e = at + n; i < e; ++i) {
45825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var line = this.lines[i];
45835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.height -= line.height;
45845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cleanUpLine(line);
4585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        signalLater(line, "delete");
45865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
45875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      this.lines.splice(at, n);
45885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
45895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    collapse: function(lines) {
45905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
45915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    insertInner: function(at, lines, height) {
45935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      this.height += height;
45945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
45955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
45965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
45975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    iterN: function(at, n, op) {
45985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var e = at + n; at < e; ++at)
45995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (op(this.lines[at])) return true;
46005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
46015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
46025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
46035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function BranchChunk(children) {
46045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.children = children;
46055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var size = 0, height = 0;
46065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0, e = children.length; i < e; ++i) {
46075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var ch = children[i];
46085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      size += ch.chunkSize(); height += ch.height;
46095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      ch.parent = this;
46105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
46115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.size = size;
46125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.height = height;
46135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.parent = null;
46145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
46155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
46165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  BranchChunk.prototype = {
46175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    chunkSize: function() { return this.size; },
4618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeInner: function(at, n) {
46195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      this.size -= n;
46205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < this.children.length; ++i) {
46215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var child = this.children[i], sz = child.chunkSize();
46225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (at < sz) {
46235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var rm = Math.min(n, sz - at), oldHeight = child.height;
4624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          child.removeInner(at, rm);
46255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          this.height -= oldHeight - child.height;
46265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
46275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if ((n -= rm) == 0) break;
46285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          at = 0;
46295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else at -= sz;
46305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
46315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (this.size - n < 25) {
46325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lines = [];
46335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.collapse(lines);
46345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.children = [new LeafChunk(lines)];
46355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.children[0].parent = this;
46365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
46375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
46385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    collapse: function(lines) {
46395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
46405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    insertInner: function(at, lines, height) {
46425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      this.size += lines.length;
46435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      this.height += height;
46445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0, e = this.children.length; i < e; ++i) {
46455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var child = this.children[i], sz = child.chunkSize();
46465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (at <= sz) {
4647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          child.insertInner(at, lines, height);
46485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (child.lines && child.lines.length > 50) {
46495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (child.lines.length > 50) {
46505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              var spilled = child.lines.splice(child.lines.length - 25, 25);
46515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              var newleaf = new LeafChunk(spilled);
46525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              child.height -= newleaf.height;
46535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              this.children.splice(i + 1, 0, newleaf);
46545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              newleaf.parent = this;
46555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
46565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this.maybeSpill();
46575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
46585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          break;
46595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
46605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        at -= sz;
46615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
46625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
46635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    maybeSpill: function() {
46645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (this.children.length <= 10) return;
46655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var me = this;
46665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      do {
46675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var spilled = me.children.splice(me.children.length - 5, 5);
46685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var sibling = new BranchChunk(spilled);
46695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!me.parent) { // Become the parent node
46705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var copy = new BranchChunk(me.children);
46715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          copy.parent = me;
46725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          me.children = [copy, sibling];
46735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          me = copy;
46745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
46755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          me.size -= sibling.size;
46765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          me.height -= sibling.height;
46775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var myIndex = indexOf(me.parent.children, me);
46785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          me.parent.children.splice(myIndex + 1, 0, sibling);
46795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
46805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        sibling.parent = me.parent;
46815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } while (me.children.length > 10);
46825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      me.parent.maybeSpill();
46835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
46845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    iterN: function(at, n, op) {
46855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0, e = this.children.length; i < e; ++i) {
46865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var child = this.children[i], sz = child.chunkSize();
46875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (at < sz) {
46885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var used = Math.min(n, sz - at);
46895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (child.iterN(at, used, op)) return true;
46905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if ((n -= used) == 0) break;
46915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          at = 0;
46925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else at -= sz;
46935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
46945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
46955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
46965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var nextDocId = 0;
4698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
4699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
4700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (firstLine == null) firstLine = 0;
4701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4702e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
4703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.first = firstLine;
4704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollTop = this.scrollLeft = 0;
4705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.cantEdit = false;
4706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.history = makeHistory();
47075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    this.cleanGeneration = 1;
4708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.frontier = firstLine;
4709926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var start = Pos(firstLine, 0);
4710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
4711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.id = ++nextDocId;
4712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.modeOption = mode;
4713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4714926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof text == "string") text = splitLines(text);
4715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
4716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  };
47175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  Doc.prototype = createObj(BranchChunk.prototype, {
471993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    constructor: Doc,
4720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    iter: function(from, to, op) {
4721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (op) this.iterN(from - this.first, to - from, op);
4722926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else this.iterN(this.first, this.first + this.size, from);
4723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    insert: function(at, lines) {
4726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var height = 0;
4727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
4728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.insertInner(at - this.first, lines, height);
4729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    remove: function(at, n) { this.removeInner(at - this.first, n); },
4731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getValue: function(lineSep) {
4733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var lines = getLines(this, this.first, this.first + this.size);
4734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (lineSep === false) return lines;
4735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return lines.join(lineSep || "\n");
4736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setValue: function(code) {
4738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var top = Pos(this.first, 0), last = this.first + this.size - 1;
4739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
4740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        text: splitLines(code), origin: "setValue"},
4741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                 {head: top, anchor: top}, true);
4742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    replaceRange: function(code, from, to, origin) {
4744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      from = clipPos(this, from);
4745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      to = to ? clipPos(this, to) : from;
4746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      replaceRange(this, code, from, to, origin);
4747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getRange: function(from, to, lineSep) {
4749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
4750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (lineSep === false) return lines;
4751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return lines.join(lineSep || "\n");
4752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
4755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setLine: function(line, text) {
4756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (isLine(this, line))
4757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
4758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeLine: function(line) {
476053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));
476153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));
4762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4763926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
4765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getLineNumber: function(line) {return lineNo(line);},
4766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4767e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    getLineHandleVisualStart: function(line) {
4768e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (typeof line == "number") line = getLine(this, line);
4769e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return visualLine(this, line);
4770e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
4771e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
4772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    lineCount: function() {return this.size;},
4773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    firstLine: function() {return this.first;},
4774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    lastLine: function() {return this.first + this.size - 1;},
4775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clipPos: function(pos) {return clipPos(this, pos);},
4777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getCursor: function(start) {
4779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sel = this.sel, pos;
4780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (start == null || start == "head") pos = sel.head;
4781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else if (start == "anchor") pos = sel.anchor;
4782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else if (start == "end" || start === false) pos = sel.to;
4783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else pos = sel.from;
4784926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return copyPos(pos);
4785926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
4787926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setCursor: docOperation(function(line, ch, extend) {
4789926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
4790926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (extend) extendSelection(this, pos);
4791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else setSelection(this, pos, pos);
4792926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }),
4793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setSelection: docOperation(function(anchor, head) {
4794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
4795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }),
4796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    extendSelection: docOperation(function(from, to) {
4797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      extendSelection(this, clipPos(this, from), to && clipPos(this, to));
4798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }),
4799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
4801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    replaceSelection: function(code, collapse, origin) {
4802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
4803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4804926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
4805926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
4806926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4807926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setExtending: function(val) {this.sel.extend = val;},
4808926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4809926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    historySize: function() {
4810926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var hist = this.history;
4811926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return {undo: hist.done.length, redo: hist.undone.length};
4812926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
48135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4814926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    markClean: function() {
48165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      this.cleanGeneration = this.changeGeneration();
48175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    },
48185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    changeGeneration: function() {
4819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.history.lastOp = this.history.lastOrigin = null;
48205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      return this.history.generation;
48215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    },
48225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    isClean: function (gen) {
48235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      return this.history.generation == (gen || this.cleanGeneration);
4824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getHistory: function() {
4827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return {done: copyHistoryArray(this.history.done),
4828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)              undone: copyHistoryArray(this.history.undone)};
4829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4830926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setHistory: function(histData) {
48315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      var hist = this.history = makeHistory(this.history.maxGeneration);
4832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      hist.done = histData.done.slice(0);
4833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      hist.undone = histData.undone.slice(0);
4834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4835926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    markText: function(from, to, options) {
4837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
4838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setBookmark: function(pos, options) {
4840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4841926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                      insertLeft: options && options.insertLeft};
4842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      pos = clipPos(this, pos);
4843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return markText(this, pos, pos, realOpts, "bookmark");
4844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    findMarksAt: function(pos) {
4846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      pos = clipPos(this, pos);
4847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var markers = [], spans = getLine(this, pos.line).markedSpans;
4848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (spans) for (var i = 0; i < spans.length; ++i) {
4849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var span = spans[i];
4850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if ((span.from == null || span.from <= pos.ch) &&
4851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            (span.to == null || span.to >= pos.ch))
4852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          markers.push(span.marker.parent || span.marker);
4853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return markers;
4855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getAllMarks: function() {
4857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var markers = [];
4858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.iter(function(line) {
4859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var sps = line.markedSpans;
4860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (sps) for (var i = 0; i < sps.length; ++i)
4861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (sps[i].from != null) markers.push(sps[i].marker);
4862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      });
4863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return markers;
4864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    posFromIndex: function(off) {
4867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var ch, lineNo = this.first;
4868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.iter(function(line) {
4869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var sz = line.text.length + 1;
4870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (sz > off) { ch = off; return true; }
4871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        off -= sz;
4872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++lineNo;
4873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      });
4874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return clipPos(this, Pos(lineNo, ch));
4875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    indexFromPos: function (coords) {
4877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      coords = clipPos(this, coords);
4878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var index = coords.ch;
4879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (coords.line < this.first || coords.ch < 0) return 0;
4880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      this.iter(this.first, coords.line, function (line) {
4881926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        index += line.text.length + 1;
4882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      });
4883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return index;
4884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    copy: function(copyHistory) {
4887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
4888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
4889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
4890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                 shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
4891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (copyHistory) {
4892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        doc.history.undoDepth = this.history.undoDepth;
4893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        doc.setHistory(this.getHistory());
4894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return doc;
4896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    linkedDoc: function(options) {
4899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!options) options = {};
4900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var from = this.first, to = this.first + this.size;
4901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (options.from != null && options.from > from) from = options.from;
4902926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (options.to != null && options.to < to) to = options.to;
4903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
4904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (options.sharedHist) copy.history = this.history;
4905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
4906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
4907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return copy;
4908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unlinkDoc: function(other) {
4910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (other instanceof CodeMirror) other = other.doc;
4911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
4912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var link = this.linked[i];
4913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (link.doc != other) continue;
4914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.linked.splice(i, 1);
4915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        other.unlinkDoc(this);
4916926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        break;
4917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // If the histories were shared, split them again
4919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (other.history == this.history) {
4920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var splitIds = [other.id];
4921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
4922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        other.history = makeHistory();
4923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        other.history.done = copyHistoryArray(this.history.done, splitIds);
4924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        other.history.undone = copyHistoryArray(this.history.undone, splitIds);
4925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    iterLinkedDocs: function(f) {linkedDocs(this, f);},
4928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getMode: function() {return this.mode;},
4930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    getEditor: function() {return this.cm;}
4931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  });
4932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  Doc.prototype.eachLine = Doc.prototype.iter;
4934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // The Doc methods that should be available on CodeMirror instances
4936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var dontDelegate = "iter insert remove copy getEditor".split(" ");
4937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
4938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    CodeMirror.prototype[prop] = (function(method) {
4939926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      return function() {return method.apply(this.doc, arguments);};
4940926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    })(Doc.prototype[prop]);
4941926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4942e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  eventMixin(Doc);
4943e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
4944926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function linkedDocs(doc, f, sharedHistOnly) {
4945926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function propagate(doc, skip, sharedHist) {
4946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
4947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var rel = doc.linked[i];
4948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (rel.doc == skip) continue;
4949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var shared = sharedHist && rel.sharedHist;
4950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (sharedHistOnly && !shared) continue;
4951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        f(rel.doc, shared);
4952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        propagate(rel.doc, doc, shared);
4953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
4954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    propagate(doc, null, true);
4956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4958926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function attachDoc(cm, doc) {
4959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (doc.cm) throw new Error("This document is already in use.");
4960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.doc = doc;
4961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.cm = cm;
4962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    estimateLineHeights(cm);
4963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    loadMode(cm);
4964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cm.options.lineWrapping) computeMaxLength(cm);
4965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cm.options.mode = doc.modeOption;
4966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    regChange(cm);
49675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
49685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // LINE UTILITIES
4970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
49715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function getLine(chunk, n) {
4972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    n -= chunk.first;
49735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (!chunk.lines) {
49745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0;; ++i) {
49755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var child = chunk.children[i], sz = child.chunkSize();
49765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (n < sz) { chunk = child; break; }
49775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        n -= sz;
49785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
49795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
49805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return chunk.lines[n];
49815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
49825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function getBetween(doc, start, end) {
4984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var out = [], n = start.line;
4985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.iter(start.line, end.line + 1, function(line) {
4986926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var text = line.text;
4987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (n == end.line) text = text.slice(0, end.ch);
4988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (n == start.line) text = text.slice(start.ch);
4989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      out.push(text);
4990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      ++n;
4991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
4992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return out;
4993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function getLines(doc, from, to) {
4995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var out = [];
4996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.iter(from, to, function(line) { out.push(line.text); });
4997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return out;
4998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
4999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
50005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function updateLineHeight(line, height) {
50015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var diff = height - line.height;
50025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var n = line; n; n = n.parent) n.height += diff;
50035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
50045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function lineNo(line) {
50065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (line.parent == null) return null;
50075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var cur = line.parent, no = indexOf(cur.lines, line);
50085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
5009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0;; ++i) {
50105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (chunk.children[i] == cur) break;
50115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        no += chunk.children[i].chunkSize();
50125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
50135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return no + cur.first;
50155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
50165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function lineAtHeight(chunk, h) {
5018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var n = chunk.first;
50195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    outer: do {
50205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0, e = chunk.children.length; i < e; ++i) {
50215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var child = chunk.children[i], ch = child.height;
50225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (h < ch) { chunk = child; continue outer; }
50235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        h -= ch;
50245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        n += child.chunkSize();
50255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
50265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return n;
50275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } while (!chunk.lines);
50285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0, e = chunk.lines.length; i < e; ++i) {
50295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var line = chunk.lines[i], lh = line.height;
50305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (h < lh) break;
50315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      h -= lh;
50325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
50335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return n + i;
50345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
50355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function heightAtLine(cm, lineObj) {
5037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    lineObj = visualLine(cm.doc, lineObj);
50385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var h = 0, chunk = lineObj.parent;
50405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < chunk.lines.length; ++i) {
50415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var line = chunk.lines[i];
50425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (line == lineObj) break;
50435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else h += line.height;
50445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
50455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
50465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < p.children.length; ++i) {
50475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var cur = p.children[i];
50485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (cur == chunk) break;
50495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else h += cur.height;
50505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
50515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
50525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return h;
50535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
50545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function getOrder(line) {
50565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var order = line.order;
50575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (order == null) order = line.order = bidiOrdering(line.text);
50585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return order;
50595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
50605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // HISTORY
50625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  function makeHistory(startGen) {
5064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return {
5065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // Arrays of history events. Doing something adds an event to
5066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // done and clears undo. Undoing moves events from done to
5067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // undone, redoing moves them in the other direction.
5068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      done: [], undone: [], undoDepth: Infinity,
5069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // Used to track when changes can be merged into a single undo
5070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // event
5071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      lastTime: 0, lastOp: null, lastOrigin: null,
5072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // Used by the isClean() method
50735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      generation: startGen || 1, maxGeneration: startGen || 1
5074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
5075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function attachLocalSpans(doc, change, from, to) {
5078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var existing = change["spans_" + doc.id], n = 0;
5079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
5080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (line.markedSpans)
5081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
5082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      ++n;
5083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
5084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function historyChangeFromChange(doc, change) {
5087e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    var from = { line: change.from.line, ch: change.from.ch };
5088e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
5089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
5090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
5091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return histChange;
5092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function addToHistory(doc, change, selAfter, opId) {
5095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var hist = doc.history;
5096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    hist.undone.length = 0;
5097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var time = +new Date, cur = lst(hist.done);
5098926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cur &&
5100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        (hist.lastOp == opId ||
5101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)         hist.lastOrigin == change.origin && change.origin &&
510253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)         ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||
510353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)          change.origin.charAt(0) == "*"))) {
5104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // Merge this change into the last event
5105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var last = lst(cur.changes);
5106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
5107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Optimized case for simple insertion -- don't want to add
5108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // new changesets for every character typed
5109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        last.to = changeEnd(change);
5110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else {
5111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Add new sub-event
5112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cur.changes.push(historyChangeFromChange(doc, change));
51135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
5114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
5115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
5116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      // Can not be merged, start a new event.
5117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      cur = {changes: [historyChangeFromChange(doc, change)],
51185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)             generation: hist.generation,
5119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
5120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             anchorAfter: selAfter.anchor, headAfter: selAfter.head};
5121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      hist.done.push(cur);
51225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      hist.generation = ++hist.maxGeneration;
5123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      while (hist.done.length > hist.undoDepth)
5124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        hist.done.shift();
51255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    hist.lastTime = time;
5127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    hist.lastOp = opId;
5128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    hist.lastOrigin = change.origin;
5129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
51305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function removeClearedSpans(spans) {
5132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!spans) return null;
5133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0, out; i < spans.length; ++i) {
5134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
5135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      else if (out) out.push(spans[i]);
51365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return !out ? spans : out.length ? out : null;
51385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
51395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function getOldSpans(doc, change) {
5141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var found = change["spans_" + doc.id];
5142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!found) return null;
5143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0, nw = []; i < change.text.length; ++i)
5144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      nw.push(removeClearedSpans(found[i]));
5145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return nw;
5146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Used both to provide a JSON-safe object in .getHistory, and, when
5149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // detaching a document, to split the history in two
5150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function copyHistoryArray(events, newGroup) {
5151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0, copy = []; i < events.length; ++i) {
5152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var event = events[i], changes = event.changes, newChanges = [];
5153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
5154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                 anchorAfter: event.anchorAfter, headAfter: event.headAfter});
5155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var j = 0; j < changes.length; ++j) {
5156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var change = changes[j], m;
5157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        newChanges.push({from: change.from, to: change.to, text: change.text});
5158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
5159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          if (indexOf(newGroup, Number(m[1])) > -1) {
5160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            lst(newChanges)[prop] = change[prop];
5161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            delete change[prop];
5162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          }
5163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
5164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
5165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
5166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return copy;
5167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Rebasing/resetting history to deal with externally-sourced changes
5170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function rebaseHistSel(pos, from, to, diff) {
5172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (to < pos.line) {
5173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      pos.line += diff;
5174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (from < pos.line) {
5175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      pos.line = from;
5176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      pos.ch = 0;
5177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
5178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // Tries to rebase an array of history events given a change in the
5181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // document. If the change touches the same lines as the event, the
5182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // event, and everything 'behind' it, is discarded. If the change is
5183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // before the event, the event's positions are updated. Uses a
5184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // copy-on-write scheme for the positions, to avoid having to
5185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // reallocate them all on every rebase, but also avoid problems with
5186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  // shared position objects being unsafely updated.
5187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function rebaseHistArray(array, from, to, diff) {
5188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < array.length; ++i) {
5189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var sub = array[i], ok = true;
5190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var j = 0; j < sub.changes.length; ++j) {
5191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cur = sub.changes[j];
5192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
5193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (to < cur.from.line) {
5194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          cur.from.line += diff;
5195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          cur.to.line += diff;
5196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else if (from <= cur.to.line) {
5197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          ok = false;
5198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          break;
5199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
5200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
5201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!sub.copied) {
5202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
5203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
5204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        sub.copied = true;
5205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
5206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (!ok) {
5207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        array.splice(0, i + 1);
5208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        i = 0;
5209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      } else {
5210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
5211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
5212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      }
5213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
5214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function rebaseHist(hist, change) {
5217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
5218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    rebaseHistArray(hist.done, from, to, diff);
5219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    rebaseHistArray(hist.undone, from, to, diff);
52205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
52215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // EVENT OPERATORS
52235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function stopMethod() {e_stop(this);}
52255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Ensure an event has a stop method.
52265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function addStop(event) {
52275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!event.stop) event.stop = stopMethod;
52285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return event;
52295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
52305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function e_preventDefault(e) {
52325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (e.preventDefault) e.preventDefault();
52335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else e.returnValue = false;
52345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
52355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function e_stopPropagation(e) {
52365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (e.stopPropagation) e.stopPropagation();
52375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else e.cancelBubble = true;
52385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
5239591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  function e_defaultPrevented(e) {
5240591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5241591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  }
52425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
52435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.e_stop = e_stop;
52445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.e_preventDefault = e_preventDefault;
52455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.e_stopPropagation = e_stopPropagation;
52465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function e_target(e) {return e.target || e.srcElement;}
52485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function e_button(e) {
52495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var b = e.which;
52505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (b == null) {
52515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (e.button & 1) b = 1;
52525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else if (e.button & 2) b = 3;
52535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else if (e.button & 4) b = 2;
52545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
52555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mac && e.ctrlKey && b == 1) b = 3;
52565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return b;
52575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
52585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // EVENT HANDLING
52605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function on(emitter, type, f) {
52625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (emitter.addEventListener)
52635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      emitter.addEventListener(type, f, false);
52645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (emitter.attachEvent)
52655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      emitter.attachEvent("on" + type, f);
52665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
52675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var map = emitter._handlers || (emitter._handlers = {});
52685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var arr = map[type] || (map[type] = []);
52695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      arr.push(f);
52705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
52715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
52725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function off(emitter, type, f) {
52745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (emitter.removeEventListener)
52755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      emitter.removeEventListener(type, f, false);
52765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (emitter.detachEvent)
52775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      emitter.detachEvent("on" + type, f);
52785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
52795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var arr = emitter._handlers && emitter._handlers[type];
52805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!arr) return;
52815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < arr.length; ++i)
52825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (arr[i] == f) { arr.splice(i, 1); break; }
52835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
52845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
52855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function signal(emitter, type /*, values...*/) {
52875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var arr = emitter._handlers && emitter._handlers[type];
52885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!arr) return;
52895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var args = Array.prototype.slice.call(arguments, 2);
52905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
52915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
52925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var delayedCallbacks, delayedCallbackDepth = 0;
5294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function signalLater(emitter, type /*, values...*/) {
52955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var arr = emitter._handlers && emitter._handlers[type];
52965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!arr) return;
5297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var args = Array.prototype.slice.call(arguments, 2);
5298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!delayedCallbacks) {
5299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      ++delayedCallbackDepth;
5300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      delayedCallbacks = [];
5301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      setTimeout(fireDelayed, 0);
5302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
53035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function bnd(f) {return function(){f.apply(null, args);};};
53045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < arr.length; ++i)
5305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      delayedCallbacks.push(bnd(arr[i]));
5306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5308e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  function signalDOMEvent(cm, e, override) {
5309e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    signal(cm, override || e.type, cm, e);
5310f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return e_defaultPrevented(e) || e.codemirrorIgnore;
5311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch  }
5312591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
5313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function fireDelayed() {
5314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    --delayedCallbackDepth;
5315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var delayed = delayedCallbacks;
5316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delayedCallbacks = null;
5317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < delayed.length; ++i) delayed[i]();
53185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
53195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function hasHandler(emitter, type) {
53215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var arr = emitter._handlers && emitter._handlers[type];
53225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return arr && arr.length > 0;
53235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
53245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
53265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5327e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  function eventMixin(ctor) {
5328e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ctor.prototype.on = function(type, f) {on(this, type, f);};
5329e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ctor.prototype.off = function(type, f) {off(this, type, f);};
5330e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  }
5331e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
53325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // MISC UTILITIES
53335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Number of pixels added to scroller and sizer to hide scrollbar
53355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var scrollerCutOff = 30;
53365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Returned or thrown by various protocols to signal 'I'm not
53385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // handling this'.
53395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
53405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function Delayed() {this.id = null;}
53425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
53435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Counts the column offset in a string, taking tabs into account.
53455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Used mostly to find indentation.
5346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function countColumn(string, end, tabSize, startIndex, startValue) {
53475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (end == null) {
53485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      end = string.search(/[^\s\u00a0]/);
53495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (end == -1) end = string.length;
53505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
53525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
53535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else ++n;
53545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
53555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return n;
53565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
53575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.countColumn = countColumn;
53585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var spaceStrs = [""];
53605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function spaceStr(n) {
53615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (spaceStrs.length <= n)
53625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      spaceStrs.push(lst(spaceStrs) + " ");
53635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return spaceStrs[n];
53645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
53655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function lst(arr) { return arr[arr.length-1]; }
53675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function selectInput(node) {
53695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ios) { // Mobile Safari apparently has a bug where select() is broken.
53705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      node.selectionStart = 0;
53715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      node.selectionEnd = node.value.length;
5372591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else {
5373591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      // Suppress mysterious IE10 errors
5374591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      try { node.select(); }
5375591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch      catch(_e) {}
5376591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
53775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
53785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function indexOf(collection, elt) {
53805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (collection.indexOf) return collection.indexOf(elt);
53815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0, e = collection.length; i < e; ++i)
53825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (collection[i] == elt) return i;
53835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return -1;
53845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
53855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function createObj(base, props) {
5387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function Obj() {}
5388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Obj.prototype = base;
5389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var inst = new Obj();
5390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (props) copyObj(props, inst);
5391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return inst;
5392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function copyObj(obj, target) {
5395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!target) target = {};
5396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
5397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return target;
5398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
54005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function emptyArray(size) {
54015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var a = [], i = 0; i < size; ++i) a.push(undefined);
54025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return a;
54035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function bind(f) {
54065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var args = Array.prototype.slice.call(arguments, 1);
54075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return function(){return f.apply(null, args);};
54085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
541093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
54115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function isWordChar(ch) {
54125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return /\w/.test(ch) || ch > "\x80" &&
54135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
54145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function isEmpty(obj) {
5417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
5418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return true;
54195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
54225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // DOM UTILITIES
54245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function elt(tag, content, className, style) {
54265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var e = document.createElement(tag);
54275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (className) e.className = className;
54285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (style) e.style.cssText = style;
54295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof content == "string") setTextContent(e, content);
54305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
54315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return e;
54325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function removeChildren(e) {
543553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    for (var count = e.childNodes.length; count > 0; --count)
543653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      e.removeChild(e.firstChild);
54375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return e;
54385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function removeChildrenAndAdd(parent, e) {
54415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return removeChildren(parent).appendChild(e);
54425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function setTextContent(e, str) {
54455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ie_lt9) {
54465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e.innerHTML = "";
54475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e.appendChild(document.createTextNode(str));
54485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else e.textContent = str;
54495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
54505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function getRect(node) {
5452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return node.getBoundingClientRect();
5453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  CodeMirror.replaceGetRect = function(f) { getRect = f; };
5455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
54565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // FEATURE DETECTION
54575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Detect drag-and-drop
54595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var dragAndDrop = function() {
54605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There is *some* kind of drag-and-drop support in IE6-8, but I
54615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // couldn't get it to work yet.
54625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ie_lt9) return false;
54635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var div = elt('div');
54645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return "draggable" in div || "dragDrop" in div;
54655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }();
54665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // For a reason I have yet to figure out, some browsers disallow
54685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // word wrapping between certain characters *only* if a new inline
54695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // element is started between them. This makes it hard to reliably
54705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // measure the position of things, since that requires inserting an
547193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  // extra span. This terribly fragile set of tests matches the
54725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // character combinations that suffer from this phenomenon on the
54735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // various browsers.
547493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  function spanAffectsWrapping() { return false; }
547593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  if (gecko) // Only for "$'"
547693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    spanAffectsWrapping = function(str, i) {
547793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;
547893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    };
547993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
548093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    spanAffectsWrapping = function(str, i) {
548193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
548293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    };
5483e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
548493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    spanAffectsWrapping = function(str, i) {
5485e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (i > 1 && str.charCodeAt(i - 1) == 45) {
5486e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5487e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5488e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      }
54895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)      return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
549093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    };
54915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var knownScrollbarWidth;
54935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function scrollbarWidth(measure) {
54945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (knownScrollbarWidth != null) return knownScrollbarWidth;
54955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
54965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeChildrenAndAdd(measure, test);
54975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (test.offsetWidth)
54985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      knownScrollbarWidth = test.offsetHeight - test.clientHeight;
54995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return knownScrollbarWidth || 0;
55005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
55015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  var zwspSupported;
5503926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function zeroWidthElement(measure) {
5504926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (zwspSupported == null) {
5505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var test = elt("span", "\u200b");
5506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
5507926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      if (measure.firstChild.offsetHeight != 0)
5508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
5509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
5510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (zwspSupported) return elt("span", "\u200b");
5511926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
5512926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  }
5513926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
55145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // See if "".split is the broken IE version, if so, provide an
55155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // alternative way to split lines.
55165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
55175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var pos = 0, result = [], l = string.length;
55185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (pos <= l) {
55195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var nl = string.indexOf("\n", pos);
55205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (nl == -1) nl = string.length;
55215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
55225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var rt = line.indexOf("\r");
55235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (rt != -1) {
55245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.push(line.slice(0, rt));
55255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pos += rt + 1;
55265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
55275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.push(line);
55285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pos = nl + 1;
55295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
55305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
55315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
55325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  } : function(string){return string.split(/\r\n?|\n/);};
55335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.splitLines = splitLines;
55345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var hasSelection = window.getSelection ? function(te) {
55365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    try { return te.selectionStart != te.selectionEnd; }
55375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    catch(e) { return false; }
55385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  } : function(te) {
55395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    try {var range = te.ownerDocument.selection.createRange();}
55405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    catch(e) {}
55415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!range || range.parentElement() != te) return false;
55425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return range.compareEndPoints("StartToEnd", range) != 0;
55435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
55445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var hasCopyEvent = (function() {
55465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var e = elt("div");
55475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ("oncopy" in e) return true;
55485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    e.setAttribute("oncopy", "return;");
55495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return typeof e.oncopy == 'function';
55505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  })();
55515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // KEY NAMING
55535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
55555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
55565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
55575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
55585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
55595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
55605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
55615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  CodeMirror.keyNames = keyNames;
55625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  (function() {
55635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Number keys
55645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
55655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Alphabetic keys
55665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
55675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Function keys
55685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
55695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  })();
55705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // BIDI HELPERS
55725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function iterateBidiSections(order, from, to, f) {
55745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!order) return f(from, to, "ltr");
5575e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    var found = false;
55765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0; i < order.length; ++i) {
55775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var part = order[i];
5578e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      if (part.from < to && part.to > from || from == to && part.to == from) {
55795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
5580e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        found = true;
5581e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      }
55825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5583e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (!found) f(from, to, "ltr");
55845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
55855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
55875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
55885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
55905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function lineRight(line) {
55915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var order = getOrder(line);
55925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!order) return line.text.length;
55935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return bidiRight(lst(order));
55945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
55955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function lineStart(cm, lineN) {
5597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var line = getLine(cm.doc, lineN);
5598926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var visual = visualLine(cm.doc, line);
5599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (visual != line) lineN = lineNo(visual);
5600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var order = getOrder(visual);
5601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
5602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Pos(lineN, ch);
56035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
5604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  function lineEnd(cm, lineN) {
56055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var merged, line;
5606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
5607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      lineN = merged.find().to.line;
56085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var order = getOrder(line);
56095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
5610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Pos(lineN, ch);
56115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
56125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
561393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  function compareBidiLevel(order, a, b) {
561493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var linedir = order[0].level;
561593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (a == linedir) return true;
561693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (b == linedir) return false;
561793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return a < b;
561893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  }
561993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  var bidiOther;
562093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  function getBidiPartAt(order, pos) {
562193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    for (var i = 0, found; i < order.length; ++i) {
562293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      var cur = order[i];
562393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
562493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (cur.from == pos || cur.to == pos) {
562593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (found == null) {
562693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          found = i;
562793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        } else if (compareBidiLevel(order, cur.level, order[found].level)) {
562893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          bidiOther = found;
562993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          return i;
563093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        } else {
563193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          bidiOther = i;
563293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          return found;
563393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
563493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      }
563593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
563693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    bidiOther = null;
563793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return found;
563893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  }
563993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
564093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  function moveInLine(line, pos, dir, byUnit) {
564193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (!byUnit) return pos + dir;
564293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    do pos += dir;
564393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
564493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return pos;
564593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)  }
564693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
56475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // This is somewhat involved. It is needed in order to move
56485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // 'visually' through bi-directional text -- i.e., pressing left
56495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // should make the cursor go left, even when in RTL text. The
56505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // tricky part is the 'jumps', where RTL and LTR text touch each
56515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // other. This often requires the cursor offset to move more than
56525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // one unit, in order to visually move one unit.
56535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function moveVisually(line, start, dir, byUnit) {
56545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var bidi = getOrder(line);
56555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!bidi) return moveLogically(line, start, dir, byUnit);
565693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var pos = getBidiPartAt(bidi, start), part = bidi[pos];
565793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
565893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
565993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    for (;;) {
566093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (target > part.from && target < part.to) return target;
566193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)      if (target == part.from || target == part.to) {
566293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (getBidiPartAt(bidi, target) == pos) return target;
566393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        part = bidi[pos += dir];
566493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        return (dir > 0) == part.level % 2 ? part.to : part.from;
56655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      } else {
566693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        part = bidi[pos += dir];
566793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (!part) return null;
566893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if ((dir > 0) == part.level % 2)
566993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          target = moveInLine(line, part.to, -1, byUnit);
567093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        else
567193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)          target = moveInLine(line, part.from, 1, byUnit);
56725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
56735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
56745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
56755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
56765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  function moveLogically(line, start, dir, byUnit) {
56775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var target = start + dir;
56785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
56795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return target < 0 || target > line.text.length ? null : target;
56805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
56815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
56825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Bidirectional ordering algorithm
56835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
56845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // that this (partially) implements.
56855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
56865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // One-char codes used for character types:
56875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // L (L):   Left-to-Right
56885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // R (R):   Right-to-Left
56895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // r (AL):  Right-to-Left Arabic
56905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // 1 (EN):  European Number
56915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // + (ES):  European Number Separator
56925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // % (ET):  European Number Terminator
56935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // n (AN):  Arabic Number
56945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // , (CS):  Common Number Separator
56955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // m (NSM): Non-Spacing Mark
56965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // b (BN):  Boundary Neutral
56975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // s (B):   Paragraph Separator
56985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // t (S):   Segment Separator
56995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // w (WS):  Whitespace
57005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // N (ON):  Other Neutrals
57015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Returns null if characters are ordered as they appear
57035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // (left-to-right), or an array of sections ({from, to, level}
57045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // objects) in the order in which they occur visually.
57055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  var bidiOrdering = (function() {
57065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Character types for codepoints 0 to 0xff
57075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
57085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Character types for codepoints 0x600 to 0x6ff
57095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
57105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function charType(code) {
57115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (code <= 0xff) return lowTypes.charAt(code);
57125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else if (0x590 <= code && code <= 0x5f4) return "R";
57135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
57145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else if (0x700 <= code && code <= 0x8ac) return "r";
57155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else return "L";
57165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
57175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
57195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
5720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Browsers seem to always treat the boundaries of block elements as being L.
5721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var outerType = "L";
57225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return function(str) {
57245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!bidiRE.test(str)) return false;
5725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      var len = str.length, types = [];
5726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, type; i < len; ++i)
57275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        types.push(type = charType(str.charCodeAt(i)));
57285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // W1. Examine each non-spacing mark (NSM) in the level run, and
57305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // change the type of the NSM to the type of the previous
57315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // character. If the NSM is at the start of the level run, it will
57325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // get the type of sor.
5733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, prev = outerType; i < len; ++i) {
57345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var type = types[i];
57355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (type == "m") types[i] = prev;
57365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else prev = type;
57375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
57385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // W2. Search backwards from each instance of a European number
57405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // until the first strong type (R, L, AL, or sor) is found. If an
57415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // AL is found, change the type of the European number to Arabic
57425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // number.
57435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // W3. Change all ALs to R.
5744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, cur = outerType; i < len; ++i) {
57455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var type = types[i];
57465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (type == "1" && cur == "r") types[i] = "n";
57475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
57485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
57495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // W4. A single European separator between two European numbers
57515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // changes to a European number. A single common separator between
57525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // two numbers of the same type changes to that type.
57535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 1, prev = types[0]; i < len - 1; ++i) {
57545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var type = types[i];
57555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
57565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == "," && prev == types[i+1] &&
57575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                 (prev == "1" || prev == "n")) types[i] = prev;
57585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        prev = type;
57595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
57605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // W5. A sequence of European terminators adjacent to European
57625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // numbers changes to all European numbers.
57635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // W6. Otherwise, separators and terminators change to Other
57645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Neutral.
57655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < len; ++i) {
57665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var type = types[i];
57675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (type == ",") types[i] = "N";
57685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == "%") {
57695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
57705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
57715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          for (var j = i; j < end; ++j) types[j] = replace;
57725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          i = end - 1;
57735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
57745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
57755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // W7. Search backwards from each instance of a European number
57775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // until the first strong type (R, L, or sor) is found. If an L is
57785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // found, then change the type of the European number to L.
5779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      for (var i = 0, cur = outerType; i < len; ++i) {
57805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var type = types[i];
57815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (cur == "L" && type == "1") types[i] = "L";
57825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (isStrong.test(type)) cur = type;
57835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
57845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
57855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // N1. A sequence of neutrals takes the direction of the
57865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // surrounding strong text if the text on both sides has the same
57875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // direction. European and Arabic numbers act as if they were R in
57885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // terms of their influence on neutrals. Start-of-level-run (sor)
57895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // and end-of-level-run (eor) are used at level run boundaries.
57905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // N2. Any remaining neutrals take the embedding direction.
57915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < len; ++i) {
57925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isNeutral.test(types[i])) {
57935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
5794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var before = (i ? types[i-1] : outerType) == "L";
5795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)          var after = (end < len - 1 ? types[end] : outerType) == "L";
57965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var replace = before || after ? "L" : "R";
57975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          for (var j = i; j < end; ++j) types[j] = replace;
57985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          i = end - 1;
57995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
58005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
58015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
58025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // Here we depart from the documented algorithm, in order to avoid
58035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // building up an actual levels array. Since there are only three
58045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // levels (0, 1, 2) in an implementation that doesn't take
58055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // explicit embedding into account, we can build up the order on
58065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      // the fly, without following the level-based algorithm.
58075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var order = [], m;
58085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var i = 0; i < len;) {
58095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (countsAsLeft.test(types[i])) {
58105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var start = i;
58115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
58125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          order.push({from: start, to: i, level: 0});
58135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
58145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          var pos = i, at = order.length;
58155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          for (++i; i < len && types[i] != "L"; ++i) {}
58165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          for (var j = pos; j < i;) {
58175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (countsAsNum.test(types[j])) {
58185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
58195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              var nstart = j;
58205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
58215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              order.splice(at, 0, {from: nstart, to: j, level: 2});
58225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              pos = j;
58235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else ++j;
58245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
58255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
58265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
58275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
58285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (order[0].level == 1 && (m = str.match(/^\s+/))) {
58295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        order[0].from = m[0].length;
58305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        order.unshift({from: 0, to: m[0].length, level: 0});
58315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
58325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
58335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lst(order).to -= m[0].length;
58345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        order.push({from: len - m[0].length, to: len, level: 0});
58355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
58365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (order[0].level != lst(order).level)
58375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        order.push({from: len, to: len, level: order[0].level});
58385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
58395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return order;
58405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
58415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  })();
58425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
58435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // THE END
58445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5845f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  CodeMirror.version = "3.15.1";
58465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
58475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  return CodeMirror;
58485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})();
5849