Vergleich admin/jscripts/codemirror/lib/codemirror.js - 1.8.0 - 1.8.9

  Keine Änderungen   Hinzugefügt   Modifiziert   Entfernt
Zeile 61Zeile 61
  function CodeMirror(place, options) {
if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);


  function CodeMirror(place, options) {
if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);


    this.options = options = options || {};

    this.options = options = options ? copyObj(options) : {};

    // Determine effective options based on given values and defaults.
copyObj(defaults, options, false);
setGuttersForLineNumbers(options);

    // Determine effective options based on given values and defaults.
copyObj(defaults, options, false);
setGuttersForLineNumbers(options);

Zeile 77Zeile 77
    if (options.lineWrapping)
this.display.wrapper.className += " CodeMirror-wrap";
if (options.autofocus && !mobile) focusInput(this);

    if (options.lineWrapping)
this.display.wrapper.className += " CodeMirror-wrap";
if (options.autofocus && !mobile) focusInput(this);

 
    initScrollbars(this);


this.state = {
keyMaps: [], // stores maps added by addKeyMap


this.state = {
keyMaps: [], // stores maps added by addKeyMap

Zeile 86Zeile 87
      suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput
draggingText: false,

      suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput
draggingText: false,

      highlight: new Delayed() // stores highlight worker timeout


      highlight: new Delayed(), // stores highlight worker timeout
keySeq: null // Unfinished key sequence

    };

// Override magic textarea content restore that IE sometimes does

    };

// Override magic textarea content restore that IE sometimes does

Zeile 96Zeile 98
    registerEventHandlers(this);
ensureGlobalHandlers();


    registerEventHandlers(this);
ensureGlobalHandlers();


    var cm = this;
runInOp(this, function() {
cm.curOp.forceUpdate = true;
attachDoc(cm, doc);





    startOperation(this);
this.curOp.forceUpdate = true;
attachDoc(this, doc);

if ((options.autofocus && !mobile) || activeElt() == display.input)
setTimeout(bind(onFocus, this), 20);
else
onBlur(this);





      if ((options.autofocus && !mobile) || activeElt() == display.input)
setTimeout(bind(onFocus, cm), 20);
else
onBlur(cm);

for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
optionHandlers[opt](cm, options[opt], Init);
for (var i = 0; i < initHooks.length; ++i) initHooks[i](cm);
});


    for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
optionHandlers[opt](this, options[opt], Init);
maybeUpdateLineNumberWidth(this);
for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
endOperation(this);
// Suppress optimizelegibility in Webkit, since it breaks text
// measuring on line wrapping boundaries.
if (webkit && options.lineWrapping &&
getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
display.lineDiv.style.textRendering = "auto";

  }

// DISPLAY CONSTRUCTOR

  }

// DISPLAY CONSTRUCTOR

Zeile 136Zeile 143

// Wraps and hides input textarea
d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");


// Wraps and hides input textarea
d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");

    // The fake scrollbar elements.
d.scrollbarH = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
d.scrollbarV = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");

 
    // Covers bottom-right square when both scrollbars are present.
d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");

    // Covers bottom-right square when both scrollbars are present.
d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");

 
    d.scrollbarFiller.setAttribute("not-content", "true");

    // Covers bottom of gutter when coverGutterNextToScrollbar is on
// and h scrollbar is present.
d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");

    // Covers bottom of gutter when coverGutterNextToScrollbar is on
// and h scrollbar is present.
d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");

 
    d.gutterFiller.setAttribute("not-content", "true");

    // Will contain the actual code, positioned to cover the viewport.
d.lineDiv = elt("div", null, "CodeMirror-code");
// Elements are added to these to represent selection and cursors.

    // Will contain the actual code, positioned to cover the viewport.
d.lineDiv = elt("div", null, "CodeMirror-code");
// Elements are added to these to represent selection and cursors.

Zeile 160Zeile 166
    d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
// Set to the height of the document, allowing scrolling.
d.sizer = elt("div", [d.mover], "CodeMirror-sizer");

    d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
// Set to the height of the document, allowing scrolling.
d.sizer = elt("div", [d.mover], "CodeMirror-sizer");

 
    d.sizerWidth = null;

    // Behavior of elts with overflow: auto and padding is
// inconsistent across browsers. This is used to ensure the
// scrollable area is big enough.

    // Behavior of elts with overflow: auto and padding is
// inconsistent across browsers. This is used to ensure the
// scrollable area is big enough.

    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");

    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");

    // Will contain the gutters, if any.
d.gutters = elt("div", null, "CodeMirror-gutters");
d.lineGutter = null;

    // Will contain the gutters, if any.
d.gutters = elt("div", null, "CodeMirror-gutters");
d.lineGutter = null;

Zeile 171Zeile 178
    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
d.scroller.setAttribute("tabIndex", "-1");
// The element in which the editor lives.

    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
d.scroller.setAttribute("tabIndex", "-1");
// The element in which the editor lives.

    d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");

    d.wrapper = elt("div", [d.inputDiv, d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");



// Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }


// Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }

Zeile 181Zeile 187
    if (!webkit) d.scroller.draggable = true;
// Needed to handle Tab key in KHTML
if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }

    if (!webkit) d.scroller.draggable = true;
// Needed to handle Tab key in KHTML
if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }

    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
if (ie && ie_version < 8) d.scrollbarH.style.minHeight = d.scrollbarV.style.minWidth = "18px";

if (place.appendChild) place.appendChild(d.wrapper);
else place(d.wrapper);


if (place) {
if (place.appendChild) place.appendChild(d.wrapper);
else place(d.wrapper);
}


// Current rendered range (may be bigger than the view window).
d.viewFrom = d.viewTo = doc.first;


// Current rendered range (may be bigger than the view window).
d.viewFrom = d.viewTo = doc.first;

 
    d.reportedViewFrom = d.reportedViewTo = doc.first;

    // Information about the rendered lines.
d.view = [];

    // Information about the rendered lines.
d.view = [];

 
    d.renderedView = null;

    // Holds info about a single rendered line when it was rendered
// for measurement, while not in view.
d.externalMeasured = null;
// Empty space (in pixels) above the view
d.viewOffset = 0;

    // Holds info about a single rendered line when it was rendered
// for measurement, while not in view.
d.externalMeasured = null;
// Empty space (in pixels) above the view
d.viewOffset = 0;

    d.lastSizeC = 0;

    d.lastWrapHeight = d.lastWrapWidth = 0;

    d.updateLineNumbers = null;

    d.updateLineNumbers = null;

 

d.nativeBarWidth = d.barHeight = d.barWidth = 0;
d.scrollbarsClipped = false;


// Used to only resize the line number gutter when necessary (when
// the amount of lines crosses a boundary that makes its width change)


// Used to only resize the line number gutter when necessary (when
// the amount of lines crosses a boundary that makes its width change)

Zeile 262Zeile 273
    if (cm.options.lineWrapping) {
addClass(cm.display.wrapper, "CodeMirror-wrap");
cm.display.sizer.style.minWidth = "";

    if (cm.options.lineWrapping) {
addClass(cm.display.wrapper, "CodeMirror-wrap");
cm.display.sizer.style.minWidth = "";

 
      cm.display.sizerWidth = null;

    } else {
rmClass(cm.display.wrapper, "CodeMirror-wrap");
findMaxLine(cm);

    } else {
rmClass(cm.display.wrapper, "CodeMirror-wrap");
findMaxLine(cm);

Zeile 299Zeile 311
      var estHeight = est(line);
if (estHeight != line.height) updateLineHeight(line, estHeight);
});

      var estHeight = est(line);
if (estHeight != line.height) updateLineHeight(line, estHeight);
});

  }

function keyMapChanged(cm) {
var map = keyMap[cm.options.keyMap], style = map.style;
cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
(style ? " cm-keymap-" + style : "");

 
  }

function themeChanged(cm) {

  }

function themeChanged(cm) {

Zeile 339Zeile 345
  function updateGutterSpace(cm) {
var width = cm.display.gutters.offsetWidth;
cm.display.sizer.style.marginLeft = width + "px";

  function updateGutterSpace(cm) {
var width = cm.display.gutters.offsetWidth;
cm.display.sizer.style.marginLeft = width + "px";

    cm.display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;

 
  }

// Compute the character length of a line, taking into account

  }

// Compute the character length of a line, taking into account

Zeile 391Zeile 396
  }

// SCROLLBARS

  }

// SCROLLBARS


function hScrollbarTakesSpace(cm) {
return cm.display.scroller.clientHeight - cm.display.wrapper.clientHeight < scrollerCutOff - 3;
}

 

// Prepare DOM reads needed to update the scrollbars. Done in one
// shot to minimize update/measure roundtrips.
function measureForScrollbars(cm) {


// Prepare DOM reads needed to update the scrollbars. Done in one
// shot to minimize update/measure roundtrips.
function measureForScrollbars(cm) {

    var scroll = cm.display.scroller;


    var d = cm.display, gutterW = d.gutters.offsetWidth;
var docH = Math.round(cm.doc.height + paddingVert(cm.display));

    return {

    return {

      clientHeight: scroll.clientHeight,
barHeight: cm.display.scrollbarV.clientHeight,
scrollWidth: scroll.scrollWidth, clientWidth: scroll.clientWidth,
hScrollbarTakesSpace: hScrollbarTakesSpace(cm),
barWidth: cm.display.scrollbarH.clientWidth,
docHeight: Math.round(cm.doc.height + paddingVert(cm.display))




      clientHeight: d.scroller.clientHeight,
viewHeight: d.wrapper.clientHeight,
scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
viewWidth: d.wrapper.clientWidth,
barLeft: cm.options.fixedGutter ? gutterW : 0,
docHeight: docH,
scrollHeight: docH + scrollGap(cm) + d.barHeight,
nativeBarWidth: d.nativeBarWidth,
gutterWidth: gutterW

    };
}


    };
}


  // Re-synchronize the fake scrollbars with the actual size of the
// content.














































































































  function NativeScrollbars(place, scroll, cm) {
this.cm = cm;
var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
place(vert); place(horiz);

on(vert, "scroll", function() {
if (vert.clientHeight) scroll(vert.scrollTop, "vertical");
});
on(horiz, "scroll", function() {
if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
});

this.checkedOverlay = false;
// Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
}

NativeScrollbars.prototype = copyObj({
update: function(measure) {
var needsH = measure.scrollWidth > measure.clientWidth + 1;
var needsV = measure.scrollHeight > measure.clientHeight + 1;
var sWidth = measure.nativeBarWidth;

if (needsV) {
this.vert.style.display = "block";
this.vert.style.bottom = needsH ? sWidth + "px" : "0";
var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
// A bug in IE8 can cause this value to be negative, so guard it.
this.vert.firstChild.style.height =
Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
} else {
this.vert.style.display = "";
this.vert.firstChild.style.height = "0";
}

if (needsH) {
this.horiz.style.display = "block";
this.horiz.style.right = needsV ? sWidth + "px" : "0";
this.horiz.style.left = measure.barLeft + "px";
var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
this.horiz.firstChild.style.width =
(measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
} else {
this.horiz.style.display = "";
this.horiz.firstChild.style.width = "0";
}

if (!this.checkedOverlay && measure.clientHeight > 0) {
if (sWidth == 0) this.overlayHack();
this.checkedOverlay = true;
}

return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
},
setScrollLeft: function(pos) {
if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
},
setScrollTop: function(pos) {
if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
},
overlayHack: function() {
var w = mac && !mac_geMountainLion ? "12px" : "18px";
this.horiz.style.minHeight = this.vert.style.minWidth = w;
var self = this;
var barMouseDown = function(e) {
if (e_target(e) != self.vert && e_target(e) != self.horiz)
operation(self.cm, onMouseDown)(e);
};
on(this.vert, "mousedown", barMouseDown);
on(this.horiz, "mousedown", barMouseDown);
},
clear: function() {
var parent = this.horiz.parentNode;
parent.removeChild(this.horiz);
parent.removeChild(this.vert);
}
}, NativeScrollbars.prototype);

function NullScrollbars() {}

NullScrollbars.prototype = copyObj({
update: function() { return {bottom: 0, right: 0}; },
setScrollLeft: function() {},
setScrollTop: function() {},
clear: function() {}
}, NullScrollbars.prototype);

CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};

function initScrollbars(cm) {
if (cm.display.scrollbars) {
cm.display.scrollbars.clear();
if (cm.display.scrollbars.addClass)
rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);
}

cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
on(node, "mousedown", function() {
if (cm.state.focused) setTimeout(bind(focusInput, cm), 0);
});
node.setAttribute("not-content", "true");
}, function(pos, axis) {
if (axis == "horizontal") setScrollLeft(cm, pos);
else setScrollTop(cm, pos);
}, cm);
if (cm.display.scrollbars.addClass)
addClass(cm.display.wrapper, cm.display.scrollbars.addClass);
}


  function updateScrollbars(cm, measure) {
if (!measure) measure = measureForScrollbars(cm);

  function updateScrollbars(cm, measure) {
if (!measure) measure = measureForScrollbars(cm);

    var d = cm.display, sWidth = scrollbarWidth(d.measure);
var scrollHeight = measure.docHeight + scrollerCutOff;
var needsH = measure.scrollWidth > measure.clientWidth;
if (needsH && measure.scrollWidth <= measure.clientWidth + 1 &&
sWidth > 0 && !measure.hScrollbarTakesSpace)
needsH = false; // (Issue #2562)
var needsV = scrollHeight > measure.clientHeight;

if (needsV) {
d.scrollbarV.style.display = "block";
d.scrollbarV.style.bottom = needsH ? sWidth + "px" : "0";
// A bug in IE8 can cause this value to be negative, so guard it.
d.scrollbarV.firstChild.style.height =
Math.max(0, scrollHeight - measure.clientHeight + (measure.barHeight || d.scrollbarV.clientHeight)) + "px";
} else {
d.scrollbarV.style.display = "";
d.scrollbarV.firstChild.style.height = "0";
}
if (needsH) {
d.scrollbarH.style.display = "block";
d.scrollbarH.style.right = needsV ? sWidth + "px" : "0";
d.scrollbarH.firstChild.style.width =
(measure.scrollWidth - measure.clientWidth + (measure.barWidth || d.scrollbarH.clientWidth)) + "px";
} else {
d.scrollbarH.style.display = "";
d.scrollbarH.firstChild.style.width = "0";

    var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
updateScrollbarsInner(cm, measure);
for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
updateHeightsInViewport(cm);
updateScrollbarsInner(cm, measureForScrollbars(cm));
startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;




















    }

    }

    if (needsH && needsV) {












  }

// Re-synchronize the fake scrollbars with the actual size of the
// content.
function updateScrollbarsInner(cm, measure) {
var d = cm.display;
var sizes = d.scrollbars.update(measure);

d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";

if (sizes.right && sizes.bottom) {

      d.scrollbarFiller.style.display = "block";

      d.scrollbarFiller.style.display = "block";

      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = sWidth + "px";


      d.scrollbarFiller.style.height = sizes.bottom + "px";
d.scrollbarFiller.style.width = sizes.right + "px";

    } else d.scrollbarFiller.style.display = "";

    } else d.scrollbarFiller.style.display = "";

    if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {

    if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {

      d.gutterFiller.style.display = "block";

      d.gutterFiller.style.display = "block";

      d.gutterFiller.style.height = sWidth + "px";
d.gutterFiller.style.width = d.gutters.offsetWidth + "px";

      d.gutterFiller.style.height = sizes.bottom + "px";
d.gutterFiller.style.width = measure.gutterWidth + "px";

    } else d.gutterFiller.style.display = "";

    } else d.gutterFiller.style.display = "";


if (!cm.state.checkedOverlayScrollbar && measure.clientHeight > 0) {
if (sWidth === 0) {
var w = mac && !mac_geMountainLion ? "12px" : "18px";
d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = w;
var barMouseDown = function(e) {
if (e_target(e) != d.scrollbarV && e_target(e) != d.scrollbarH)
operation(cm, onMouseDown)(e);
};
on(d.scrollbarV, "mousedown", barMouseDown);
on(d.scrollbarH, "mousedown", barMouseDown);
}
cm.state.checkedOverlayScrollbar = true;
}
}


  }
















  // Compute the lines that are visible in a given viewport (defaults

  // Compute the lines that are visible in a given viewport (defaults

  // the the current scroll position). viewPort may contain top,

  // the the current scroll position). viewport may contain top,

  // height, and ensure (see op.scrollToPos) properties.

  // height, and ensure (see op.scrollToPos) properties.

  function visibleLines(display, doc, viewPort) {
var top = viewPort && viewPort.top != null ? Math.max(0, viewPort.top) : display.scroller.scrollTop;

  function visibleLines(display, doc, viewport) {
var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;

    top = Math.floor(top - paddingTop(display));

    top = Math.floor(top - paddingTop(display));

    var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight;

    var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;


var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
// Ensure is a {from: {line, ch}, to: {line, ch}} object, and
// forces those lines into the viewport (if possible).


var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
// Ensure is a {from: {line, ch}, to: {line, ch}} object, and
// forces those lines into the viewport (if possible).

    if (viewPort && viewPort.ensure) {
var ensureFrom = viewPort.ensure.from.line, ensureTo = viewPort.ensure.to.line;
if (ensureFrom < from)
return {from: ensureFrom,
to: lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)};
if (Math.min(ensureTo, doc.lastLine()) >= to)
return {from: lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight),
to: ensureTo};


    if (viewport && viewport.ensure) {
var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
if (ensureFrom < from) {
from = ensureFrom;
to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
} else if (Math.min(ensureTo, doc.lastLine()) >= to) {
from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
to = ensureTo;
}

    }
return {from: from, to: Math.max(to, from + 1)};
}

    }
return {from: from, to: Math.max(to, from + 1)};
}

Zeile 507Zeile 601
    }
if (cm.options.fixedGutter)
display.gutters.style.left = (comp + gutterW) + "px";

    }
if (cm.options.fixedGutter)
display.gutters.style.left = (comp + gutterW) + "px";

  }


  }


  // Used to ensure that the line number gutter is still the right
// size for the current document size. Returns true when an update
// is needed.

  // Used to ensure that the line number gutter is still the right
// size for the current document size. Returns true when an update
// is needed.

Zeile 543Zeile 637

// DISPLAY DRAWING



// DISPLAY DRAWING


  // Updates the display, selection, and scrollbars, using the
// information in display.view to find out which nodes are no longer
// up-to-date. Tries to bail out early when no changes are needed,
// unless forced is true.
// Returns true if an actual update happened, false otherwise.
function updateDisplay(cm, viewPort, forced) {
var oldFrom = cm.display.viewFrom, oldTo = cm.display.viewTo, updated;
var visible = visibleLines(cm.display, cm.doc, viewPort);
for (var first = true;; first = false) {
var oldWidth = cm.display.scroller.clientWidth;
if (!updateDisplayInner(cm, visible, forced)) break;
updated = true;

// If the max line changed since it was last measured, measure it,
// and ensure the document's width matches it.
if (cm.display.maxLineChanged && !cm.options.lineWrapping)
adjustContentWidth(cm);

var barMeasure = measureForScrollbars(cm);
updateSelection(cm);
setDocumentHeight(cm, barMeasure);
updateScrollbars(cm, barMeasure);
if (webkit && cm.options.lineWrapping)
checkForWebkitWidthBug(cm, barMeasure); // (Issue #2420)
if (webkit && barMeasure.scrollWidth > barMeasure.clientWidth &&
barMeasure.scrollWidth < barMeasure.clientWidth + 1 &&
!hScrollbarTakesSpace(cm))
updateScrollbars(cm); // (Issue #2562)
if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {
forced = true;
continue;
}
forced = false;

// Clip forced viewport to actual scrollable area.
if (viewPort && viewPort.top != null)
viewPort = {top: Math.min(barMeasure.docHeight - scrollerCutOff - barMeasure.clientHeight, viewPort.top)};
// Updated line heights might result in the drawn area not
// actually covering the viewport. Keep looping until it does.
visible = visibleLines(cm.display, cm.doc, viewPort);
if (visible.from >= cm.display.viewFrom && visible.to <= cm.display.viewTo)
break;
}

cm.display.updateLineNumbers = null;
if (updated) {
signalLater(cm, "update", cm);
if (cm.display.viewFrom != oldFrom || cm.display.viewTo != oldTo)
signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);

  function DisplayUpdate(cm, viewport, force) {
var display = cm.display;

this.viewport = viewport;
// Store some values that we'll need later (but don't want to force a relayout for)
this.visible = visibleLines(display, cm.doc, viewport);
this.editorIsHidden = !display.wrapper.offsetWidth;
this.wrapperHeight = display.wrapper.clientHeight;
this.wrapperWidth = display.wrapper.clientWidth;
this.oldDisplayWidth = displayWidth(cm);
this.force = force;
this.dims = getDimensions(cm);
}

function maybeClipScrollbars(cm) {
var display = cm.display;
if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
display.heightForcer.style.height = scrollGap(cm) + "px";
display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
display.scrollbarsClipped = true;




























    }

    }

    return updated;

 
  }

// Does the actual updating of the line display. Bails out
// (returning false) when there is nothing to be done and forced is
// false.

  }

// Does the actual updating of the line display. Bails out
// (returning false) when there is nothing to be done and forced is
// false.

  function updateDisplayInner(cm, visible, forced) {

  function updateDisplayIfNeeded(cm, update) {

    var display = cm.display, doc = cm.doc;

    var display = cm.display, doc = cm.doc;

    if (!display.wrapper.offsetWidth) {
resetView(cm);
return;



if (update.editorIsHidden) {
resetView(cm);
return false;

    }

// Bail out if the visible area is already rendered and nothing changed.

    }

// Bail out if the visible area is already rendered and nothing changed.

    if (!forced && visible.from >= display.viewFrom && visible.to <= display.viewTo &&


    if (!update.force &&
update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&

        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&

        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&

        countDirtyView(cm) == 0)
return;

if (maybeUpdateLineNumberWidth(cm))

        display.renderedView == display.view && countDirtyView(cm) == 0)
return false;

if (maybeUpdateLineNumberWidth(cm)) {

      resetView(cm);

      resetView(cm);

    var dims = getDimensions(cm);


      update.dims = getDimensions(cm);
}


// Compute a suitable new viewport (from & to)
var end = doc.first + doc.size;


// Compute a suitable new viewport (from & to)
var end = doc.first + doc.size;

    var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
var to = Math.min(end, visible.to + cm.options.viewportMargin);

    var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
var to = Math.min(end, update.visible.to + cm.options.viewportMargin);

    if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
if (sawCollapsedSpans) {

    if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
if (sawCollapsedSpans) {

Zeile 628Zeile 697
    }

var different = from != display.viewFrom || to != display.viewTo ||

    }

var different = from != display.viewFrom || to != display.viewTo ||

      display.lastSizeC != display.wrapper.clientHeight;

      display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;

    adjustView(cm, from, to);

    adjustView(cm, from, to);





    display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
// Position the mover div to align with the current scroll position
cm.display.mover.style.top = display.viewOffset + "px";

var toUpdate = countDirtyView(cm);

    display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
// Position the mover div to align with the current scroll position
cm.display.mover.style.top = display.viewOffset + "px";

var toUpdate = countDirtyView(cm);

    if (!different && toUpdate == 0 && !forced) return;



    if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
(display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
return false;


// For big changes, we hide the enclosing element during the
// update, since that speeds up the operations on most browsers.
var focused = activeElt();
if (toUpdate > 4) display.lineDiv.style.display = "none";


// For big changes, we hide the enclosing element during the
// update, since that speeds up the operations on most browsers.
var focused = activeElt();
if (toUpdate > 4) display.lineDiv.style.display = "none";

    patchDisplay(cm, display.updateLineNumbers, dims);

    patchDisplay(cm, display.updateLineNumbers, update.dims);

    if (toUpdate > 4) display.lineDiv.style.display = "";

    if (toUpdate > 4) display.lineDiv.style.display = "";

 
    display.renderedView = display.view;

    // There might have been a widget with a focused element that got
// hidden or updated, if so re-focus it.
if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();

// Prevent selection and cursors from interfering with the scroll

    // There might have been a widget with a focused element that got
// hidden or updated, if so re-focus it.
if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();

// Prevent selection and cursors from interfering with the scroll

    // width.

    // width and height.

    removeChildren(display.cursorDiv);
removeChildren(display.selectionDiv);

    removeChildren(display.cursorDiv);
removeChildren(display.selectionDiv);

 
    display.gutters.style.height = 0;


if (different) {


if (different) {

      display.lastSizeC = display.wrapper.clientHeight;


      display.lastWrapHeight = update.wrapperHeight;
display.lastWrapWidth = update.wrapperWidth;

      startWorker(cm, 400);
}


      startWorker(cm, 400);
}


    updateHeightsInViewport(cm);

    display.updateLineNumbers = null;


return true;
}



return true;
}


  function adjustContentWidth(cm) {
var display = cm.display;
var width = measureChar(cm, display.maxLine, display.maxLine.text.length).left;
display.maxLineChanged = false;
var minWidth = Math.max(0, width + 3);
var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + minWidth + scrollerCutOff - display.scroller.clientWidth);
display.sizer.style.minWidth = minWidth + "px";
if (maxScrollLeft < cm.doc.scrollLeft)
setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
}

function setDocumentHeight(cm, measure) {
cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measure.docHeight + "px";
cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px";




























  function postUpdateDisplay(cm, update) {
var force = update.force, viewport = update.viewport;
for (var first = true;; first = false) {
if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {
force = true;
} else {
force = false;
// Clip forced viewport to actual scrollable area.
if (viewport && viewport.top != null)
viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
// Updated line heights might result in the drawn area not
// actually covering the viewport. Keep looping until it does.
update.visible = visibleLines(cm.display, cm.doc, viewport);
if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
break;
}
if (!updateDisplayIfNeeded(cm, update)) break;
updateHeightsInViewport(cm);
var barMeasure = measureForScrollbars(cm);
updateSelection(cm);
setDocumentHeight(cm, barMeasure);
updateScrollbars(cm, barMeasure);
}

signalLater(cm, "update", cm);
if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
}
}

function updateDisplaySimple(cm, viewport) {
var update = new DisplayUpdate(cm, viewport);
if (updateDisplayIfNeeded(cm, update)) {
updateHeightsInViewport(cm);
postUpdateDisplay(cm, update);
var barMeasure = measureForScrollbars(cm);
updateSelection(cm);
setDocumentHeight(cm, barMeasure);
updateScrollbars(cm, barMeasure);
}

  }


  }


  function checkForWebkitWidthBug(cm, measure) {
// Work around Webkit bug where it sometimes reserves space for a
// non-existing phantom scrollbar in the scroller (Issue #2420)
if (cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.display.scroller.clientWidth - 1) {
cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = "0px";
cm.display.gutters.style.height = measure.docHeight + "px";
}

  function setDocumentHeight(cm, measure) {
cm.display.sizer.style.minHeight = measure.docHeight + "px";
var total = measure.docHeight + cm.display.barHeight;
cm.display.heightForcer.style.top = total + "px";
cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";



  }

// Read the actual heights of the rendered lines, and update their

  }

// Read the actual heights of the rendered lines, and update their

Zeile 726Zeile 825
  // view, so that we don't interleave reading and writing to the DOM.
function getDimensions(cm) {
var d = cm.display, left = {}, width = {};

  // view, so that we don't interleave reading and writing to the DOM.
function getDimensions(cm) {
var d = cm.display, left = {}, width = {};

 
    var gutterLeft = d.gutters.clientLeft;

    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {

    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {

      left[cm.options.gutters[i]] = n.offsetLeft;
width[cm.options.gutters[i]] = n.offsetWidth;

      left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
width[cm.options.gutters[i]] = n.clientWidth;

    }
return {fixedPos: compensateForHScroll(d),
gutterTotalWidth: d.gutters.offsetWidth,

    }
return {fixedPos: compensateForHScroll(d),
gutterTotalWidth: d.gutters.offsetWidth,

Zeile 871Zeile 971
    if (cm.options.lineNumbers || markers) {
var wrap = ensureLineWrapped(lineView);
var gutterWrap = lineView.gutter =

    if (cm.options.lineNumbers || markers) {
var wrap = ensureLineWrapped(lineView);
var gutterWrap = lineView.gutter =

        wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "position: absolute; left: " +
(cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),


        wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
(cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
"px; width: " + dims.gutterTotalWidth + "px"),

                          lineView.text);

                          lineView.text);

 
      if (lineView.line.gutterClass)
gutterWrap.className += " " + lineView.line.gutterClass;

      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
lineView.lineNumber = gutterWrap.appendChild(
elt("div", lineNumberFor(cm.options, lineN),

      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
lineView.lineNumber = gutterWrap.appendChild(
elt("div", lineNumberFor(cm.options, lineN),

Zeile 925Zeile 1028
    var wrap = ensureLineWrapped(lineView);
for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");

    var wrap = ensureLineWrapped(lineView);
for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");

      if (!widget.handleMouseEvents) node.ignoreEvents = true;

      if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");

      positionLineWidget(widget, node, lineView, dims);
if (allowAbove && widget.above)
wrap.insertBefore(node, lineView.gutter || lineView.text);

      positionLineWidget(widget, node, lineView, dims);
if (allowAbove && widget.above)
wrap.insertBefore(node, lineView.gutter || lineView.text);

Zeile 1257Zeile 1360
  // SELECTION DRAWING

// Redraw the selection and/or cursor

  // SELECTION DRAWING

// Redraw the selection and/or cursor

  function updateSelection(cm) {
var display = cm.display, doc = cm.doc;
var curFragment = document.createDocumentFragment();
var selFragment = document.createDocumentFragment();

  function drawSelection(cm) {
var display = cm.display, doc = cm.doc, result = {};
var curFragment = result.cursors = document.createDocumentFragment();
var selFragment = result.selection = document.createDocumentFragment();


for (var i = 0; i < doc.sel.ranges.length; i++) {
var range = doc.sel.ranges[i];


for (var i = 0; i < doc.sel.ranges.length; i++) {
var range = doc.sel.ranges[i];

Zeile 1269Zeile 1372
        drawSelectionCursor(cm, range, curFragment);
if (!collapsed)
drawSelectionRange(cm, range, selFragment);

        drawSelectionCursor(cm, range, curFragment);
if (!collapsed)
drawSelectionRange(cm, range, selFragment);

    }


    }


    // Move the hidden textarea near the cursor to prevent scrolling artifacts
if (cm.options.moveInputWithCursor) {
var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();

    // Move the hidden textarea near the cursor to prevent scrolling artifacts
if (cm.options.moveInputWithCursor) {
var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();

      var top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
headPos.top + lineOff.top - wrapOff.top));
var left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
headPos.left + lineOff.left - wrapOff.left));
display.inputDiv.style.top = top + "px";
display.inputDiv.style.left = left + "px";

      result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
headPos.top + lineOff.top - wrapOff.top));
result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
headPos.left + lineOff.left - wrapOff.left));



    }


    }


    removeChildrenAndAdd(display.cursorDiv, curFragment);
removeChildrenAndAdd(display.selectionDiv, selFragment);













    return result;
}

function showSelection(cm, drawn) {
removeChildrenAndAdd(cm.display.cursorDiv, drawn.cursors);
removeChildrenAndAdd(cm.display.selectionDiv, drawn.selection);
if (drawn.teTop != null) {
cm.display.inputDiv.style.top = drawn.teTop + "px";
cm.display.inputDiv.style.left = drawn.teLeft + "px";
}
}

function updateSelection(cm) {
showSelection(cm, drawSelection(cm));

  }

// Draws a cursor for the given range

  }

// Draws a cursor for the given range

Zeile 1310Zeile 1423
  function drawSelectionRange(cm, range, output) {
var display = cm.display, doc = cm.doc;
var fragment = document.createDocumentFragment();

  function drawSelectionRange(cm, range, output) {
var display = cm.display, doc = cm.doc;
var fragment = document.createDocumentFragment();

    var padding = paddingH(cm.display), leftSide = padding.left, rightSide = display.lineSpace.offsetWidth - padding.right;



    var padding = paddingH(cm.display), leftSide = padding.left;
var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;


    function add(left, top, width, bottom) {
if (top < 0) top = 0;
top = Math.round(top);

    function add(left, top, width, bottom) {
if (top < 0) top = 0;
top = Math.round(top);

Zeile 1355Zeile 1469
        add(left, rightPos.top, right - left, rightPos.bottom);
});
return {start: start, end: end};

        add(left, rightPos.top, right - left, rightPos.bottom);
});
return {start: start, end: end};

    }

    }


var sFrom = range.from(), sTo = range.to();
if (sFrom.line == sTo.line) {


var sFrom = range.from(), sTo = range.to();
if (sFrom.line == sTo.line) {

Zeile 1376Zeile 1490
      if (leftEnd.bottom < rightStart.top)
add(leftSide, leftEnd.bottom, null, rightStart.top);
}

      if (leftEnd.bottom < rightStart.top)
add(leftSide, leftEnd.bottom, null, rightStart.top);
}





    output.appendChild(fragment);
}


    output.appendChild(fragment);
}


Zeile 1393Zeile 1507
      }, cm.options.cursorBlinkRate);
else if (cm.options.cursorBlinkRate < 0)
display.cursorDiv.style.visibility = "hidden";

      }, cm.options.cursorBlinkRate);
else if (cm.options.cursorBlinkRate < 0)
display.cursorDiv.style.visibility = "hidden";

  }

// HIGHLIGHT WORKER


  }

// HIGHLIGHT WORKER


  function startWorker(cm, time) {
if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
cm.state.highlight.set(time, bind(highlightWorker, cm));

  function startWorker(cm, time) {
if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
cm.state.highlight.set(time, bind(highlightWorker, cm));

Zeile 1408Zeile 1522
    if (doc.frontier >= cm.display.viewTo) return;
var end = +new Date + cm.options.workTime;
var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));

    if (doc.frontier >= cm.display.viewTo) return;
var end = +new Date + cm.options.workTime;
var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));

 
    var changedLines = [];





    runInOp(cm, function() {

 
    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
if (doc.frontier >= cm.display.viewFrom) { // Visible
var oldStyles = line.styles;

    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
if (doc.frontier >= cm.display.viewFrom) { // Visible
var oldStyles = line.styles;

Zeile 1421Zeile 1535
        var ischange = !oldStyles || oldStyles.length != line.styles.length ||
oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];

        var ischange = !oldStyles || oldStyles.length != line.styles.length ||
oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];

        if (ischange) regLineChange(cm, doc.frontier, "text");

        if (ischange) changedLines.push(doc.frontier);

        line.stateAfter = copyState(doc.mode, state);
} else {
processLine(cm, line.text, state);

        line.stateAfter = copyState(doc.mode, state);
} else {
processLine(cm, line.text, state);

Zeile 1433Zeile 1547
        return true;
}
});

        return true;
}
});

 
    if (changedLines.length) runInOp(cm, function() {
for (var i = 0; i < changedLines.length; i++)
regLineChange(cm, changedLines[i], "text");

    });
}


    });
}


Zeile 1484Zeile 1601
    var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
return data;

    var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
return data;

 
  }

function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }
function displayWidth(cm) {
return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;
}
function displayHeight(cm) {
return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;

  }

// Ensure the lineView.wrapping.heights array is populated. This is

  }

// Ensure the lineView.wrapping.heights array is populated. This is

Zeile 1492Zeile 1617
  // height.
function ensureLineHeights(cm, lineView, rect) {
var wrapping = cm.options.lineWrapping;

  // height.
function ensureLineHeights(cm, lineView, rect) {
var wrapping = cm.options.lineWrapping;

    var curWidth = wrapping && cm.display.scroller.clientWidth;

    var curWidth = wrapping && displayWidth(cm);

    if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
var heights = lineView.measure.heights = [];
if (wrapping) {

    if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
var heights = lineView.measure.heights = [];
if (wrapping) {

Zeile 1533Zeile 1658
    view.text = built.pre;
removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
return view;

    view.text = built.pre;
removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
return view;

  }

  }


// Get a {top, bottom, left, right} box (in line-local coordinates)
// for a given character.


// Get a {top, bottom, left, right} box (in line-local coordinates)
// for a given character.

Zeile 1636Zeile 1761

var rect;
if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.


var rect;
if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.

      while (start && isExtendingChar(prepared.line.text.charAt(mStart + start))) --start;
while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end))) ++end;
if (ie && ie_version < 9 && start == 0 && end == mEnd - mStart) {
rect = node.parentNode.getBoundingClientRect();
} else if (ie && cm.options.lineWrapping) {
var rects = range(node, start, end).getClientRects();
if (rects.length)
rect = rects[bias == "right" ? rects.length - 1 : 0];
else
rect = nullRect;
} else {
rect = range(node, start, end).getBoundingClientRect() || nullRect;







      for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
while (start && isExtendingChar(prepared.line.text.charAt(mStart + start))) --start;
while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end))) ++end;
if (ie && ie_version < 9 && start == 0 && end == mEnd - mStart) {
rect = node.parentNode.getBoundingClientRect();
} else if (ie && cm.options.lineWrapping) {
var rects = range(node, start, end).getClientRects();
if (rects.length)
rect = rects[bias == "right" ? rects.length - 1 : 0];
else
rect = nullRect;
} else {
rect = range(node, start, end).getBoundingClientRect() || nullRect;
}
if (rect.left || rect.right || start == 0) break;
end = start;
start = start - 1;
collapse = "right";

      }

      }

 
      if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);

    } else { // If it is a widget, simply get the box for the whole widget.
if (start > 0) collapse = bias = "right";
var rects;

    } else { // If it is a widget, simply get the box for the whole widget.
if (start > 0) collapse = bias = "right";
var rects;

Zeile 1676Zeile 1808
                  top: top, bottom: bot};
if (!rect.left && !rect.right) result.bogus = true;
if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }

                  top: top, bottom: bot};
if (!rect.left && !rect.right) result.bogus = true;
if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }

 


    return result;

    return result;

 
  }

// Work around problem with bounding client rects on ranges being
// returned incorrectly when zoomed on IE10 and below.
function maybeUpdateRectForZooming(measure, rect) {
if (!window.screen || screen.logicalXDPI == null ||
screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
return rect;
var scaleX = screen.logicalXDPI / screen.deviceXDPI;
var scaleY = screen.logicalYDPI / screen.deviceYDPI;
return {left: rect.left * scaleX, right: rect.right * scaleX,
top: rect.top * scaleY, bottom: rect.bottom * scaleY};

  }

function clearLineMeasurementCacheFor(lineView) {

  }

function clearLineMeasurementCacheFor(lineView) {

Zeile 1707Zeile 1852

// Converts a {top, bottom, left, right} box from line-local
// coordinates into another coordinate system. Context may be one of


// Converts a {top, bottom, left, right} box from line-local
// coordinates into another coordinate system. Context may be one of

  // "line", "div" (display.lineDiv), "local"/null (editor), or "page".


  // "line", "div" (display.lineDiv), "local"/null (editor), "window",
// or "page".

  function intoCoordSystem(cm, lineObj, rect, context) {
if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
var size = widgetHeight(lineObj.widgets[i]);

  function intoCoordSystem(cm, lineObj, rect, context) {
if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
var size = widgetHeight(lineObj.widgets[i]);

Zeile 1910Zeile 2056
  // cursor and display (which would be awkward, slow, and
// error-prone). Instead, display updates are batched and then all
// combined and executed at once.

  // cursor and display (which would be awkward, slow, and
// error-prone). Instead, display updates are batched and then all
// combined and executed at once.

 

var operationGroup = null;


var nextOpId = 0;
// Start a new operation.
function startOperation(cm) {
cm.curOp = {


var nextOpId = 0;
// Start a new operation.
function startOperation(cm) {
cm.curOp = {

 
      cm: cm,

      viewChanged: false,      // Flag that indicates that lines might need to be redrawn
startHeight: cm.doc.height, // Used to detect need to update scrollbar
forceUpdate: false, // Used to force a redraw

      viewChanged: false,      // Flag that indicates that lines might need to be redrawn
startHeight: cm.doc.height, // Used to detect need to update scrollbar
forceUpdate: false, // Used to force a redraw

Zeile 1922Zeile 2071
      typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
changeObjs: null, // Accumulated changes, for firing change events
cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on

      typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
changeObjs: null, // Accumulated changes, for firing change events
cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on

 
      cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already

      selectionChanged: false, // Whether the selection needs to be redrawn
updateMaxLine: false, // Set when the widest line needs to be determined anew
scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
scrollToPos: null, // Used to scroll to a specific position
id: ++nextOpId // Unique ID
};

      selectionChanged: false, // Whether the selection needs to be redrawn
updateMaxLine: false, // Set when the widest line needs to be determined anew
scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
scrollToPos: null, // Used to scroll to a specific position
id: ++nextOpId // Unique ID
};

    if (!delayedCallbackDepth++) delayedCallbacks = [];
}

























    if (operationGroup) {
operationGroup.ops.push(cm.curOp);
} else {
cm.curOp.ownsGroup = operationGroup = {
ops: [cm.curOp],
delayedCallbacks: []
};
}
}

function fireCallbacksForOps(group) {
// Calls delayed callbacks and cursorActivity handlers until no
// new ones appear
var callbacks = group.delayedCallbacks, i = 0;
do {
for (; i < callbacks.length; i++)
callbacks[i]();
for (var j = 0; j < group.ops.length; j++) {
var op = group.ops[j];
if (op.cursorActivityHandlers)
while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm);
}
} while (i < callbacks.length);
}


  // Finish an operation, updating the display and signalling delayed events
function endOperation(cm) {

  // Finish an operation, updating the display and signalling delayed events
function endOperation(cm) {

    var op = cm.curOp, doc = cm.doc, display = cm.display;
cm.curOp = null;






























    var op = cm.curOp, group = op.ownsGroup;
if (!group) return;

try { fireCallbacksForOps(group); }
finally {
operationGroup = null;
for (var i = 0; i < group.ops.length; i++)
group.ops[i].cm.curOp = null;
endOperations(group);
}
}

// The DOM updates done when an operation finishes are batched so
// that the minimum number of relayouts are required.
function endOperations(group) {
var ops = group.ops;
for (var i = 0; i < ops.length; i++) // Read DOM
endOperation_R1(ops[i]);
for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
endOperation_W1(ops[i]);
for (var i = 0; i < ops.length; i++) // Read DOM
endOperation_R2(ops[i]);
for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
endOperation_W2(ops[i]);
for (var i = 0; i < ops.length; i++) // Read DOM
endOperation_finish(ops[i]);
}

function endOperation_R1(op) {
var cm = op.cm, display = cm.display;
maybeClipScrollbars(cm);

    if (op.updateMaxLine) findMaxLine(cm);

    if (op.updateMaxLine) findMaxLine(cm);


// If it looks like an update might be needed, call updateDisplay
if (op.viewChanged || op.forceUpdate || op.scrollTop != null ||
op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
op.scrollToPos.to.line >= display.viewTo) ||
display.maxLineChanged && cm.options.lineWrapping) {
var updated = updateDisplay(cm, {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;




































op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
op.scrollToPos.to.line >= display.viewTo) ||
display.maxLineChanged && cm.options.lineWrapping;
op.update = op.mustUpdate &&
new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
}

function endOperation_W1(op) {
op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
}

function endOperation_R2(op) {
var cm = op.cm, display = cm.display;
if (op.updatedDisplay) updateHeightsInViewport(cm);

op.barMeasure = measureForScrollbars(cm);

// If the max line changed since it was last measured, measure it,
// and ensure the document's width matches it.
// updateDisplay_W2 will use these properties to do the actual resizing
if (display.maxLineChanged && !cm.options.lineWrapping) {
op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
cm.display.sizerWidth = op.adjustWidthTo;
op.barMeasure.scrollWidth =
Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
}

if (op.updatedDisplay || op.selectionChanged)
op.newSelectionNodes = drawSelection(cm);
}

function endOperation_W2(op) {
var cm = op.cm;

if (op.adjustWidthTo != null) {
cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
if (op.maxScrollLeft < cm.doc.scrollLeft)
setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);
cm.display.maxLineChanged = false;

    }

    }

    // If no update was run, but the selection changed, redraw that.
if (!updated && op.selectionChanged) updateSelection(cm);
if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm);

















if (op.newSelectionNodes)
showSelection(cm, op.newSelectionNodes);
if (op.updatedDisplay)
setDocumentHeight(cm, op.barMeasure);
if (op.updatedDisplay || op.startHeight != cm.doc.height)
updateScrollbars(cm, op.barMeasure);

if (op.selectionChanged) restartBlink(cm);

if (cm.state.focused && op.updateInput)
resetInput(cm, op.typing);
}

function endOperation_finish(op) {
var cm = op.cm, display = cm.display, doc = cm.doc;

if (op.updatedDisplay) postUpdateDisplay(cm, op.update);


// Abort mouse wheel delta measurement, when scrolling explicitly
if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
display.wheelStartX = display.wheelStartY = null;

// Propagate the scroll position to the actual DOM scroller


// Abort mouse wheel delta measurement, when scrolling explicitly
if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
display.wheelStartX = display.wheelStartY = null;

// Propagate the scroll position to the actual DOM scroller

    if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) {
var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;


    if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
display.scrollbars.setScrollTop(doc.scrollTop);
display.scroller.scrollTop = doc.scrollTop;

    }

    }

    if (op.scrollLeft != null && display.scroller.scrollLeft != op.scrollLeft) {
var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft));
display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;


    if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
display.scrollbars.setScrollLeft(doc.scrollLeft);
display.scroller.scrollLeft = doc.scrollLeft;

      alignHorizontally(cm);
}
// If we need to scroll a specific position into view, do so.
if (op.scrollToPos) {

      alignHorizontally(cm);
}
// If we need to scroll a specific position into view, do so.
if (op.scrollToPos) {

      var coords = scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),
clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);

      var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);

      if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
}

      if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
}


if (op.selectionChanged) restartBlink(cm);

if (cm.state.focused && op.updateInput)
resetInput(cm, op.typing);

 

// Fire events for markers that are hidden/unidden by editing or
// undoing


// Fire events for markers that are hidden/unidden by editing or
// undoing

Zeile 1984Zeile 2231
    if (unhidden) for (var i = 0; i < unhidden.length; ++i)
if (unhidden[i].lines.length) signal(unhidden[i], "unhide");


    if (unhidden) for (var i = 0; i < unhidden.length; ++i)
if (unhidden[i].lines.length) signal(unhidden[i], "unhide");


    var delayed;
if (!--delayedCallbackDepth) {
delayed = delayedCallbacks;
delayedCallbacks = null;
}

    if (display.wrapper.offsetHeight)
doc.scrollTop = cm.display.scroller.scrollTop;




    // Fire change events, and delayed event handlers
if (op.changeObjs)
signal(cm, "changes", cm, op.changeObjs);

    // Fire change events, and delayed event handlers
if (op.changeObjs)
signal(cm, "changes", cm, op.changeObjs);

    if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
if (op.cursorActivityHandlers)
for (var i = 0; i < op.cursorActivityHandlers.length; i++)
op.cursorActivityHandlers[i](cm);

 
  }

// Run the given function in an operation

  }

// Run the given function in an operation

Zeile 2011Zeile 2252
      if (cm.curOp) return f.apply(cm, arguments);
startOperation(cm);
try { return f.apply(cm, arguments); }

      if (cm.curOp) return f.apply(cm, arguments);
startOperation(cm);
try { return f.apply(cm, arguments); }

      finally { endOperation(cm); }
};
}

      finally { endOperation(cm); }
};
}

  // Used to add methods to editor and doc instances, wrapping them in
// operations.
function methodOp(f) {

  // Used to add methods to editor and doc instances, wrapping them in
// operations.
function methodOp(f) {

Zeile 2022Zeile 2263
      startOperation(this);
try { return f.apply(this, arguments); }
finally { endOperation(this); }

      startOperation(this);
try { return f.apply(this, arguments); }
finally { endOperation(this); }

    };
}

    };
}

  function docMethodOp(f) {
return function() {
var cm = this.cm;

  function docMethodOp(f) {
return function() {
var cm = this.cm;

Zeile 2032Zeile 2273
      try { return f.apply(this, arguments); }
finally { endOperation(cm); }
};

      try { return f.apply(this, arguments); }
finally { endOperation(cm); }
};

  }


  }


  // VIEW TRACKING

// These objects are used to represent the visible (currently drawn)

  // VIEW TRACKING

// These objects are used to represent the visible (currently drawn)

Zeile 2093Zeile 2334
      resetView(cm);
} else if (from <= display.viewFrom) { // Top overlap
var cut = viewCuttingPoint(cm, to, to + lendiff, 1);

      resetView(cm);
} else if (from <= display.viewFrom) { // Top overlap
var cut = viewCuttingPoint(cm, to, to + lendiff, 1);

      if (cut) {

      if (cut) {

        display.view = display.view.slice(cut.index);
display.viewFrom = cut.lineN;
display.viewTo += lendiff;

        display.view = display.view.slice(cut.index);
display.viewFrom = cut.lineN;
display.viewTo += lendiff;

Zeile 2246Zeile 2487
    }
cm.display.poll.set(20, p);
}

    }
cm.display.poll.set(20, p);
}

 

// This will be set to an array of strings when copying, so that,
// when pasting, we know what kind of selections the copied text
// was made out of.
var lastCopied = null;


// Read input from the textarea, and update the document to match.
// When something is selected, it is present in the textarea, and


// Read input from the textarea, and update the document to match.
// When something is selected, it is present in the textarea, and

Zeile 2259Zeile 2505
    // possible when it is clear that nothing happened. hasSelection
// will be the case when there is a lot of text in the textarea,
// in which case reading its value would be expensive.

    // possible when it is clear that nothing happened. hasSelection
// will be the case when there is a lot of text in the textarea,
// in which case reading its value would be expensive.

    if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput)

    if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)

      return false;
// See paste handler for more on the fakedLastChar kludge
if (cm.state.pasteIncoming && cm.state.fakedLastChar) {

      return false;
// See paste handler for more on the fakedLastChar kludge
if (cm.state.pasteIncoming && cm.state.fakedLastChar) {

Zeile 2269Zeile 2515
    var text = input.value;
// If nothing changed, bail.
if (text == prevInput && !cm.somethingSelected()) return false;

    var text = input.value;
// If nothing changed, bail.
if (text == prevInput && !cm.somethingSelected()) return false;

    // Work around nonsensical selection resetting in IE9/10
if (ie && ie_version >= 9 && cm.display.inputHasSelection === text) {




    // Work around nonsensical selection resetting in IE9/10, and
// inexplicable appearance of private area unicode characters on
// some key combos in Mac (#2689).
if (ie && ie_version >= 9 && cm.display.inputHasSelection === text ||
mac && /[\uf700-\uf7ff]/.test(text)) {

      resetInput(cm);
return false;
}

      resetInput(cm);
return false;
}

Zeile 2287Zeile 2536
    var inserted = text.slice(same), textLines = splitLines(inserted);

// When pasing N lines into N selections, insert one line per selection

    var inserted = text.slice(same), textLines = splitLines(inserted);

// When pasing N lines into N selections, insert one line per selection

    var multiPaste = cm.state.pasteIncoming && textLines.length > 1 && doc.sel.ranges.length == textLines.length;







    var multiPaste = null;
if (cm.state.pasteIncoming && doc.sel.ranges.length > 1) {
if (lastCopied && lastCopied.join("\n") == inserted)
multiPaste = doc.sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
else if (textLines.length == doc.sel.ranges.length)
multiPaste = map(textLines, function(l) { return [l]; });
}


// Normal behavior is to insert the new text into every selection
for (var i = doc.sel.ranges.length - 1; i >= 0; i--) {


// Normal behavior is to insert the new text into every selection
for (var i = doc.sel.ranges.length - 1; i >= 0; i--) {

Zeile 2300Zeile 2555
      else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming)
to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
var updateInput = cm.curOp.updateInput;

      else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming)
to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
var updateInput = cm.curOp.updateInput;

      var changeEvent = {from: from, to: to, text: multiPaste ? [textLines[i]] : textLines,

      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,

                         origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
makeChange(cm.doc, changeEvent);
signalLater(cm, "inputRead", cm, changeEvent);

                         origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
makeChange(cm.doc, changeEvent);
signalLater(cm, "inputRead", cm, changeEvent);

Zeile 2309Zeile 2564
          cm.options.smartIndent && range.head.ch < 100 &&
(!i || doc.sel.ranges[i - 1].head.line != range.head.line)) {
var mode = cm.getModeAt(range.head);

          cm.options.smartIndent && range.head.ch < 100 &&
(!i || doc.sel.ranges[i - 1].head.line != range.head.line)) {
var mode = cm.getModeAt(range.head);

 
        var end = changeEnd(changeEvent);

        if (mode.electricChars) {
for (var j = 0; j < mode.electricChars.length; j++)
if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {

        if (mode.electricChars) {
for (var j = 0; j < mode.electricChars.length; j++)
if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {

              indentLine(cm, range.head.line, "smart");

              indentLine(cm, end.line, "smart");

              break;
}
} else if (mode.electricInput) {

              break;
}
} else if (mode.electricInput) {

          var end = changeEnd(changeEvent);

 
          if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))

          if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))

            indentLine(cm, range.head.line, "smart");

            indentLine(cm, end.line, "smart");

        }
}
}

        }
}
}

Zeile 2337Zeile 2592
  // Reset the input to correspond to the selection (or to be empty,
// when not typing and nothing is selected)
function resetInput(cm, typing) {

  // Reset the input to correspond to the selection (or to be empty,
// when not typing and nothing is selected)
function resetInput(cm, typing) {

 
    if (cm.display.contextMenuPending) return;

    var minimal, selected, doc = cm.doc;
if (cm.somethingSelected()) {
cm.display.prevInput = "";

    var minimal, selected, doc = cm.doc;
if (cm.somethingSelected()) {
cm.display.prevInput = "";

Zeile 2380Zeile 2636
        var pos = posFromMouse(cm, e);
if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
e_preventDefault(e);

        var pos = posFromMouse(cm, e);
if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
e_preventDefault(e);

        var word = findWordAt(cm, pos);

        var word = cm.findWordAt(pos);

        extendSelection(cm.doc, word.anchor, word.head);
}));
else

        extendSelection(cm.doc, word.anchor, word.head);
}));
else

Zeile 2402Zeile 2658
        setScrollLeft(cm, d.scroller.scrollLeft, true);
signal(cm, "scroll", cm);
}

        setScrollLeft(cm, d.scroller.scrollLeft, true);
signal(cm, "scroll", cm);
}

    });
on(d.scrollbarV, "scroll", function() {
if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
});
on(d.scrollbarH, "scroll", function() {
if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);

 
    });

// Listen to wheel events in order to try and update the viewport on time.
on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});

    });

// Listen to wheel events in order to try and update the viewport on time.
on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});


// Prevent clicks in the scrollbars from killing focus
function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
on(d.scrollbarH, "mousedown", reFocus);
on(d.scrollbarV, "mousedown", reFocus);







    // Prevent wrapper from ever scrolling
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });


    // Prevent wrapper from ever scrolling
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });


    on(d.input, "keyup", operation(cm, onKeyUp));

    on(d.input, "keyup", function(e) { onKeyUp.call(cm, e); });

    on(d.input, "input", function() {
if (ie && ie_version >= 9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;

    on(d.input, "input", function() {
if (ie && ie_version >= 9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;

      fastPoll(cm);

      readInput(cm);

    });
on(d.input, "keydown", operation(cm, onKeyDown));
on(d.input, "keypress", operation(cm, onKeyPress));

    });
on(d.input, "keydown", operation(cm, onKeyDown));
on(d.input, "keypress", operation(cm, onKeyPress));

Zeile 2467Zeile 2713

function prepareCopyCut(e) {
if (cm.somethingSelected()) {


function prepareCopyCut(e) {
if (cm.somethingSelected()) {

 
        lastCopied = cm.getSelections();

        if (d.inaccurateSelection) {
d.prevInput = "";
d.inaccurateSelection = false;

        if (d.inaccurateSelection) {
d.prevInput = "";
d.inaccurateSelection = false;

          d.input.value = cm.getSelection();

          d.input.value = lastCopied.join("\n");

          selectInput(d.input);
}
} else {

          selectInput(d.input);
}
} else {

        var text = "", ranges = [];

        var text = [], ranges = [];

        for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
var line = cm.doc.sel.ranges[i].head.line;
var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
ranges.push(lineRange);

        for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
var line = cm.doc.sel.ranges[i].head.line;
var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
ranges.push(lineRange);

          text += cm.getRange(lineRange.anchor, lineRange.head);

          text.push(cm.getRange(lineRange.anchor, lineRange.head));

        }
if (e.type == "cut") {
cm.setSelections(ranges, null, sel_dontScroll);
} else {
d.prevInput = "";

        }
if (e.type == "cut") {
cm.setSelections(ranges, null, sel_dontScroll);
} else {
d.prevInput = "";

          d.input.value = text;

          d.input.value = text.join("\n");

          selectInput(d.input);
}

          selectInput(d.input);
}

 
        lastCopied = text;

      }
if (e.type == "cut") cm.state.cutIncoming = true;
}

      }
if (e.type == "cut") cm.state.cutIncoming = true;
}

Zeile 2503Zeile 2751

// Called when the window resizes
function onResize(cm) {


// Called when the window resizes
function onResize(cm) {

 
    var d = cm.display;
if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
return;

    // Might be a text scaling operation, clear size caches.

    // Might be a text scaling operation, clear size caches.

    var d = cm.display;

 
    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;

    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;

 
    d.scrollbarsClipped = false;

    cm.setSize();

    cm.setSize();

  }

// MOUSE EVENTS


  }

// MOUSE EVENTS


  // Return true when the given mouse event happened in a widget
function eventInWidget(display, e) {
for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {

  // Return true when the given mouse event happened in a widget
function eventInWidget(display, e) {
for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {

      if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;



      if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
(n.parentNode == display.sizer && n != display.mover))
return true;

    }
}


    }
}


Zeile 2525Zeile 2778
  // coordinates beyond the right of the text.
function posFromMouse(cm, e, liberal, forRect) {
var display = cm.display;

  // coordinates beyond the right of the text.
function posFromMouse(cm, e, liberal, forRect) {
var display = cm.display;

    if (!liberal) {
var target = e_target(e);
if (target == display.scrollbarH || target == display.scrollbarV ||
target == display.scrollbarFiller || target == display.gutterFiller) return null;
}

    if (!liberal && e_target(e).getAttribute("not-content") == "true") return null;





    var x, y, space = display.lineSpace.getBoundingClientRect();
// Fails unpredictably on IE[67] when mouse is dragged around quickly.
try { x = e.clientX - space.left; y = e.clientY - space.top; }

    var x, y, space = display.lineSpace.getBoundingClientRect();
// Fails unpredictably on IE[67] when mouse is dragged around quickly.
try { x = e.clientX - space.left; y = e.clientY - space.top; }

Zeile 2594Zeile 2844
    } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
type = "double";
lastDoubleClick = {time: now, pos: start};

    } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
type = "double";
lastDoubleClick = {time: now, pos: start};

    } else {

    } else {

      type = "single";
lastClick = {time: now, pos: start};
}

      type = "single";
lastClick = {time: now, pos: start};
}


var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey;


var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;

    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&

    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&

        type == "single" && sel.contains(start) > -1 && sel.somethingSelected())


        type == "single" && (contained = sel.contains(start)) > -1 &&
!sel.ranges[contained].empty())

      leftButtonStartDrag(cm, e, start, modifier);
else
leftButtonSelect(cm, e, start, type, modifier);

      leftButtonStartDrag(cm, e, start, modifier);
else
leftButtonSelect(cm, e, start, type, modifier);

  }


  }


  // Start a text drag. When it ends, see if any dragging actually
// happen, and treat as a click if it didn't.
function leftButtonStartDrag(cm, e, start, modifier) {

  // Start a text drag. When it ends, see if any dragging actually
// happen, and treat as a click if it didn't.
function leftButtonStartDrag(cm, e, start, modifier) {

Zeile 2640Zeile 2891
    var display = cm.display, doc = cm.doc;
e_preventDefault(e);


    var display = cm.display, doc = cm.doc;
e_preventDefault(e);


    var ourRange, ourIndex, startSel = doc.sel;

    var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;

    if (addNew && !e.shiftKey) {
ourIndex = doc.sel.contains(start);
if (ourIndex > -1)

    if (addNew && !e.shiftKey) {
ourIndex = doc.sel.contains(start);
if (ourIndex > -1)

        ourRange = doc.sel.ranges[ourIndex];

        ourRange = ranges[ourIndex];

      else
ourRange = new Range(start, start);
} else {

      else
ourRange = new Range(start, start);
} else {

Zeile 2657Zeile 2908
      start = posFromMouse(cm, e, true, true);
ourIndex = -1;
} else if (type == "double") {

      start = posFromMouse(cm, e, true, true);
ourIndex = -1;
} else if (type == "double") {

      var word = findWordAt(cm, start);

      var word = cm.findWordAt(start);

      if (cm.display.shift || doc.extend)
ourRange = extendRange(doc, ourRange, word.anchor, word.head);
else

      if (cm.display.shift || doc.extend)
ourRange = extendRange(doc, ourRange, word.anchor, word.head);
else

Zeile 2676Zeile 2927
      ourIndex = 0;
setSelection(doc, new Selection([ourRange], 0), sel_mouse);
startSel = doc.sel;

      ourIndex = 0;
setSelection(doc, new Selection([ourRange], 0), sel_mouse);
startSel = doc.sel;

    } else if (ourIndex > -1) {
replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
} else {
ourIndex = doc.sel.ranges.length;
setSelection(doc, normalizeSelection(doc.sel.ranges.concat([ourRange]), ourIndex),

    } else if (ourIndex == -1) {
ourIndex = ranges.length;
setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),



                   {scroll: false, origin: "*mouse"});

                   {scroll: false, origin: "*mouse"});

 
    } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") {
setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
startSel = doc.sel;
} else {
replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);

    }

var lastPos = start;

    }

var lastPos = start;

Zeile 2711Zeile 2965
        var anchor = oldRange.anchor, head = pos;
if (type != "single") {
if (type == "double")

        var anchor = oldRange.anchor, head = pos;
if (type != "single") {
if (type == "double")

            var range = findWordAt(cm, pos);

            var range = cm.findWordAt(pos);

          else
var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
if (cmp(range.anchor, anchor) > 0) {

          else
var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
if (cmp(range.anchor, anchor) > 0) {

Zeile 2885Zeile 3139
  function setScrollTop(cm, val) {
if (Math.abs(cm.doc.scrollTop - val) < 2) return;
cm.doc.scrollTop = val;

  function setScrollTop(cm, val) {
if (Math.abs(cm.doc.scrollTop - val) < 2) return;
cm.doc.scrollTop = val;

    if (!gecko) updateDisplay(cm, {top: val});

    if (!gecko) updateDisplaySimple(cm, {top: val});

    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;

    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;

    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
if (gecko) updateDisplay(cm);

    cm.display.scrollbars.setScrollTop(val);
if (gecko) updateDisplaySimple(cm);

    startWorker(cm, 100);
}
// Sync scroller and scrollbar, ensure the gutter elements are

    startWorker(cm, 100);
}
// Sync scroller and scrollbar, ensure the gutter elements are

Zeile 2899Zeile 3153
    cm.doc.scrollLeft = val;
alignHorizontally(cm);
if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;

    cm.doc.scrollLeft = val;
alignHorizontally(cm);
if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;

    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;

    cm.display.scrollbars.setScrollLeft(val);

  }

// Since the delta values reported on mouse wheel events are

  }

// Since the delta values reported on mouse wheel events are

Zeile 2923Zeile 3177
  else if (chrome) wheelPixelsPerUnit = -.7;
else if (safari) wheelPixelsPerUnit = -1/3;


  else if (chrome) wheelPixelsPerUnit = -.7;
else if (safari) wheelPixelsPerUnit = -1/3;


  function onScrollWheel(cm, e) {

  var wheelEventDelta = function(e) {

    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
else if (dy == null) dy = e.wheelDelta;

    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
else if (dy == null) dy = e.wheelDelta;

 
    return {x: dx, y: dy};
};
CodeMirror.wheelEventPixels = function(e) {
var delta = wheelEventDelta(e);
delta.x *= wheelPixelsPerUnit;
delta.y *= wheelPixelsPerUnit;
return delta;
};

function onScrollWheel(cm, e) {
var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;


var display = cm.display, scroll = display.scroller;
// Quit if there's nothing to scroll here


var display = cm.display, scroll = display.scroller;
// Quit if there's nothing to scroll here

Zeile 2962Zeile 3227
      e_preventDefault(e);
display.wheelStartX = null; // Abort measurement, if in progress
return;

      e_preventDefault(e);
display.wheelStartX = null; // Abort measurement, if in progress
return;

    }

    }


// 'Project' the visible viewport to cover the area that is being
// scrolled into view (if we know enough to estimate it).


// 'Project' the visible viewport to cover the area that is being
// scrolled into view (if we know enough to estimate it).

Zeile 2971Zeile 3236
      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
if (pixels < 0) top = Math.max(0, top + pixels - 50);
else bot = Math.min(cm.doc.height, bot + pixels + 50);

      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
if (pixels < 0) top = Math.max(0, top + pixels - 50);
else bot = Math.min(cm.doc.height, bot + pixels + 50);

      updateDisplay(cm, {top: top, bottom: bot});

      updateDisplaySimple(cm, {top: top, bottom: bot});

    }

if (wheelSamples < 20) {

    }

if (wheelSamples < 20) {

Zeile 3016Zeile 3281
      cm.state.suppressEdits = false;
}
return done;

      cm.state.suppressEdits = false;
}
return done;

  }



































  }

function lookupKeyForEditor(cm, name, handle) {
for (var i = 0; i < cm.state.keyMaps.length; i++) {
var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
if (result) return result;
}
return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
|| lookupKey(name, cm.options.keyMap, handle, cm);
}

var stopSeq = new Delayed;
function dispatchKey(cm, name, e, handle) {
var seq = cm.state.keySeq;
if (seq) {
if (isModifierKey(name)) return "handled";
stopSeq.set(50, function() {
if (cm.state.keySeq == seq) {
cm.state.keySeq = null;
resetInput(cm);
}
});
name = seq + " " + name;
}
var result = lookupKeyForEditor(cm, name, handle);

if (result == "multi")
cm.state.keySeq = name;
if (result == "handled")
signalLater(cm, "keyHandled", cm, name, e);

if (result == "handled" || result == "multi") {
e_preventDefault(e);
restartBlink(cm);
}





  // Collect the currently active keymaps.
function allKeyMaps(cm) {
var maps = cm.state.keyMaps.slice(0);
if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
maps.push(cm.options.keyMap);
return maps;

    if (seq && !result && /\'$/.test(name)) {
e_preventDefault(e);
return true;
}
return !!result;


  }


  }


  var maybeTransition;

 
  // Handle a key from the keydown event.
function handleKeyBinding(cm, e) {

  // Handle a key from the keydown event.
function handleKeyBinding(cm, e) {

    // Handle automatic keymap transitions
var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
clearTimeout(maybeTransition);
if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
if (getKeyMap(cm.options.keyMap) == startMap) {
cm.options.keyMap = (next.call ? next.call(null, cm) : next);
keyMapChanged(cm);
}
}, 50);

var name = keyName(e, true), handled = false;

    var name = keyName(e, true);











    if (!name) return false;

    if (!name) return false;

    var keymaps = allKeyMaps(cm);

 




    if (e.shiftKey) {

    if (e.shiftKey && !cm.state.keySeq) {

      // First try to resolve full name (including 'Shift-'). Failing
// that, see if there is a cursor-motion command (starting with
// 'go') bound to the keyname without 'Shift-'.

      // First try to resolve full name (including 'Shift-'). Failing
// that, see if there is a cursor-motion command (starting with
// 'go') bound to the keyname without 'Shift-'.

      handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
|| lookupKey(name, keymaps, function(b) {
if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
return doHandleBinding(cm, b);
});
} else {
handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
}

if (handled) {
e_preventDefault(e);
restartBlink(cm);
signalLater(cm, "keyHandled", cm, name, e);

      return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
|| dispatchKey(cm, name, e, function(b) {
if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
return doHandleBinding(cm, b);
});
} else {
return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });







    }

    }

    return handled;

 
  }

// Handle a key from the keypress event
function handleCharBinding(cm, e, ch) {

  }

// Handle a key from the keypress event
function handleCharBinding(cm, e, ch) {

    var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
function(b) { return doHandleBinding(cm, b, true); });
if (handled) {
e_preventDefault(e);
restartBlink(cm);
signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
}
return handled;

    return dispatchKey(cm, "'" + ch + "'", e,
function(b) { return doHandleBinding(cm, b, true); });







  }

var lastStoppedKey = null;

  }

var lastStoppedKey = null;

Zeile 3096Zeile 3369
    // Turn mouse into crosshair when Alt is held on Mac.
if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
showCrossHair(cm);

    // Turn mouse into crosshair when Alt is held on Mac.
if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
showCrossHair(cm);

  }

  }


function showCrossHair(cm) {
var lineDiv = cm.display.lineDiv;


function showCrossHair(cm) {
var lineDiv = cm.display.lineDiv;

Zeile 3114Zeile 3387
  }

function onKeyUp(e) {

  }

function onKeyUp(e) {

    if (signalDOMEvent(this, e)) return;

 
    if (e.keyCode == 16) this.doc.sel.shift = false;

    if (e.keyCode == 16) this.doc.sel.shift = false;

 
    signalDOMEvent(this, e);

  }

function onKeyPress(e) {
var cm = this;

  }

function onKeyPress(e) {
var cm = this;

    if (signalDOMEvent(cm, e) || e.ctrlKey || mac && e.metaKey) return;

    if (signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;

    var keyCode = e.keyCode, charCode = e.charCode;
if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
if (((presto && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;

    var keyCode = e.keyCode, charCode = e.charCode;
if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
if (((presto && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;

Zeile 3184Zeile 3457
      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
(ie ? "rgba(255, 255, 255, .05)" : "transparent") +
"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";

      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
(ie ? "rgba(255, 255, 255, .05)" : "transparent") +
"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";

 
    if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)

    focusInput(cm);

    focusInput(cm);

 
    if (webkit) window.scrollTo(null, oldScrollY);

    resetInput(cm);
// Adds "Select all" to context menu in FF
if (!cm.somethingSelected()) display.input.value = display.prevInput = " ";

    resetInput(cm);
// Adds "Select all" to context menu in FF
if (!cm.somethingSelected()) display.input.value = display.prevInput = " ";

 
    display.contextMenuPending = true;

    display.selForContextMenu = cm.doc.sel;
clearTimeout(display.detectingSelectAll);


    display.selForContextMenu = cm.doc.sel;
clearTimeout(display.detectingSelectAll);


Zeile 3206Zeile 3482
      }
}
function rehide() {

      }
}
function rehide() {

 
      display.contextMenuPending = false;

      display.inputDiv.style.position = "relative";
display.input.style.cssText = oldCSS;

      display.inputDiv.style.position = "relative";
display.input.style.cssText = oldCSS;

      if (ie && ie_version < 9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;

      if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);

      slowPoll(cm);

// Try to detect the user choosing select-all

      slowPoll(cm);

// Try to detect the user choosing select-all

Zeile 3378Zeile 3655
      event = source[i];
if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
break;

      event = source[i];
if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
break;

    }

    }

    if (i == source.length) return;
hist.lastOrigin = hist.lastSelOrigin = null;


    if (i == source.length) return;
hist.lastOrigin = hist.lastSelOrigin = null;


Zeile 3414Zeile 3691

antiChanges.push(historyChangeFromChange(doc, change));



antiChanges.push(historyChangeFromChange(doc, change));


      var after = i ? computeSelAfterChange(doc, change, null) : lst(source);

      var after = i ? computeSelAfterChange(doc, change) : lst(source);

      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));

      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));

      if (!i && doc.cm) doc.cm.scrollIntoView(change);

      if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});

      var rebased = [];

// Propagate to the linked documents

      var rebased = [];

// Propagate to the linked documents

Zeile 3473Zeile 3750

change.removed = getBetween(doc, change.from, change.to);



change.removed = getBetween(doc, change.from, change.to);


    if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);

    if (!selAfter) selAfter = computeSelAfterChange(doc, change);

    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
else updateDoc(doc, change, spans);
setSelectionNoUndo(doc, selAfter, sel_dontScroll);

    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
else updateDoc(doc, change, spans);
setSelectionNoUndo(doc, selAfter, sel_dontScroll);

Zeile 3519Zeile 3796

var lendiff = change.text.length - (to.line - from.line) - 1;
// Remember that these lines changed, for updating the display


var lendiff = change.text.length - (to.line - from.line) - 1;
// Remember that these lines changed, for updating the display

    if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))



    if (change.full)
regChange(cm);
else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))

      regLineChange(cm, from.line, "text");
else
regChange(cm, from.line, to.line + 1, lendiff);

      regLineChange(cm, from.line, "text");
else
regChange(cm, from.line, to.line + 1, lendiff);

Zeile 3550Zeile 3829
  // If an editor sits on the top or bottom of the window, partially
// scrolled out of view, this ensures that the cursor is visible.
function maybeScrollWindow(cm, coords) {

  // If an editor sits on the top or bottom of the window, partially
// scrolled out of view, this ensures that the cursor is visible.
function maybeScrollWindow(cm, coords) {

 
    if (signalDOMEvent(cm, "scrollCursorIntoView")) return;


    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
if (coords.top + box.top < 0) doScroll = true;
else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
if (doScroll != null && !phantom) {
var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
(coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +

    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
if (coords.top + box.top < 0) doScroll = true;
else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
if (doScroll != null && !phantom) {
var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
(coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +

                           (coords.bottom - coords.top + scrollerCutOff) + "px; left: " +

                           (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +

                           coords.left + "px; width: 2px;");
cm.display.lineSpace.appendChild(scrollNode);
scrollNode.scrollIntoView(doScroll);

                           coords.left + "px; width: 2px;");
cm.display.lineSpace.appendChild(scrollNode);
scrollNode.scrollIntoView(doScroll);

Zeile 3569Zeile 3850
  // measured, the position of something may 'drift' during drawing).
function scrollPosIntoView(cm, pos, end, margin) {
if (margin == null) margin = 0;

  // measured, the position of something may 'drift' during drawing).
function scrollPosIntoView(cm, pos, end, margin) {
if (margin == null) margin = 0;

    for (;;) {

    for (var limit = 0; limit < 5; limit++) {

      var changed = false, coords = cursorCoords(cm, pos);
var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),

      var changed = false, coords = cursorCoords(cm, pos);
var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),

Zeile 3585Zeile 3866
        setScrollLeft(cm, scrollPos.scrollLeft);
if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
}

        setScrollLeft(cm, scrollPos.scrollLeft);
if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
}

      if (!changed) return coords;

      if (!changed) break;

    }

    }

  }



    return coords;
}


  // Scroll a given set of coordinates into view (immediately).
function scrollIntoView(cm, x1, y1, x2, y2) {
var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);

  // Scroll a given set of coordinates into view (immediately).
function scrollIntoView(cm, x1, y1, x2, y2) {
var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);

  }


  }


  // Calculate a new scroll position needed to scroll the given
// rectangle into view. Returns an object with scrollTop and
// scrollLeft properties. When these are undefined, the

  // Calculate a new scroll position needed to scroll the given
// rectangle into view. Returns an object with scrollTop and
// scrollLeft properties. When these are undefined, the

Zeile 3604Zeile 3886
    var display = cm.display, snapMargin = textHeight(cm.display);
if (y1 < 0) y1 = 0;
var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;

    var display = cm.display, snapMargin = textHeight(cm.display);
if (y1 < 0) y1 = 0;
var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;

    var screen = display.scroller.clientHeight - scrollerCutOff, result = {};


    var screen = displayHeight(cm), result = {};
if (y2 - y1 > screen) y2 = y1 + screen;

    var docBottom = cm.doc.height + paddingVert(display);
var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
if (y1 < screentop) {

    var docBottom = cm.doc.height + paddingVert(display);
var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
if (y1 < screentop) {

Zeile 3615Zeile 3898
    }

var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;

    }

var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;

    var screenw = display.scroller.clientWidth - scrollerCutOff;
x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
var gutterw = display.gutters.offsetWidth;
var atLeft = x1 < gutterw + 10;
if (x1 < screenleft + gutterw || atLeft) {
if (atLeft) x1 = 0;
result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
} else if (x2 > screenw + screenleft - 3) {
result.scrollLeft = x2 + 10 - screenw;
}

    var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
var tooWide = x2 - x1 > screenw;
if (tooWide) x2 = x1 + screenw;
if (x1 < 10)
result.scrollLeft = 0;
else if (x1 < screenleft)
result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));
else if (x2 > screenw + screenleft - 3)
result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;


    return result;
}


    return result;
}


Zeile 3680Zeile 3962
    if (how == "smart") {
// Fall back to "prev" when the mode doesn't have an indentation
// method.

    if (how == "smart") {
// Fall back to "prev" when the mode doesn't have an indentation
// method.

      if (!cm.doc.mode.indent) how = "prev";

      if (!doc.mode.indent) how = "prev";

      else state = getStateBefore(cm, n);
}


      else state = getStateBefore(cm, n);
}


Zeile 3692Zeile 3974
      indentation = 0;
how = "not";
} else if (how == "smart") {

      indentation = 0;
how = "not";
} else if (how == "smart") {

      indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
if (indentation == Pass) {

      indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
if (indentation == Pass || indentation > 150) {

        if (!aggressive) return;
how = "prev";
}

        if (!aggressive) return;
how = "prev";
}

Zeile 3716Zeile 3998
    if (pos < indentation) indentString += spaceStr(indentation - pos);

if (indentString != curSpaceString) {

    if (pos < indentation) indentString += spaceStr(indentation - pos);

if (indentString != curSpaceString) {

      replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");

      replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");

    } else {
// Ensure that, if the cursor was in the whitespace at the start
// of the line, it is moved to the end of that space.

    } else {
// Ensure that, if the cursor was in the whitespace at the start
// of the line, it is moved to the end of that space.

Zeile 3819Zeile 4101

if (type) sawType = type;
if (dir > 0 && !moveOnce(!first)) break;


if (type) sawType = type;
if (dir > 0 && !moveOnce(!first)) break;

      }

      }

    }
var result = skipAtomic(doc, Pos(line, ch), origDir, true);
if (!possible) result.hitSide = true;

    }
var result = skipAtomic(doc, Pos(line, ch), origDir, true);
if (!possible) result.hitSide = true;

Zeile 3844Zeile 4126
      y += dir * 5;
}
return target;

      y += dir * 5;
}
return target;

  }

// Find the word at the given position (as returned by coordsChar).
function findWordAt(cm, pos) {
var doc = cm.doc, line = getLine(doc, pos.line).text;
var start = pos.ch, end = pos.ch;
if (line) {
var helper = cm.getHelper(pos, "wordChars");
if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
var startChar = line.charAt(start);
var check = isWordChar(startChar, helper)
? function(ch) { return isWordChar(ch, helper); }
: /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
: function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
while (start > 0 && check(line.charAt(start - 1))) --start;
while (end < line.length && check(line.charAt(end))) ++end;
}
return new Range(Pos(pos.line, start), Pos(pos.line, end));

 
  }

// EDITOR METHODS

  }

// EDITOR METHODS

Zeile 3890Zeile 4154
    getDoc: function() {return this.doc;},

addKeyMap: function(map, bottom) {

    getDoc: function() {return this.doc;},

addKeyMap: function(map, bottom) {

      this.state.keyMaps[bottom ? "push" : "unshift"](map);

      this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));

    },
removeKeyMap: function(map) {
var maps = this.state.keyMaps;
for (var i = 0; i < maps.length; ++i)

    },
removeKeyMap: function(map) {
var maps = this.state.keyMaps;
for (var i = 0; i < maps.length; ++i)

        if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {

        if (maps[i] == map || maps[i].name == map) {

          maps.splice(i, 1);
return true;
}

          maps.splice(i, 1);
return true;
}

Zeile 3927Zeile 4191
        else dir = dir ? "add" : "subtract";
}
if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);

        else dir = dir ? "add" : "subtract";
}
if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);

    }),

    }),

    indentSelection: methodOp(function(how) {
var ranges = this.doc.sel.ranges, end = -1;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (!range.empty()) {

    indentSelection: methodOp(function(how) {
var ranges = this.doc.sel.ranges, end = -1;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (!range.empty()) {

          var start = Math.max(end, range.from().line);
var to = range.to();

          var from = range.from(), to = range.to();
var start = Math.max(end, from.line);

          end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
for (var j = start; j < end; ++j)
indentLine(this, j, how);

          end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
for (var j = start; j < end; ++j)
indentLine(this, j, how);

 
          var newRanges = this.doc.sel.ranges;
if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);

        } else if (range.head.line > end) {
indentLine(this, range.head.line, how, true);
end = range.head.line;
if (i == this.doc.sel.primIndex) ensureCursorVisible(this);

        } else if (range.head.line > end) {
indentLine(this, range.head.line, how, true);
end = range.head.line;
if (i == this.doc.sel.primIndex) ensureCursorVisible(this);

        }
}
}),


        }
}
}),


    // Fetch the parser token for a given character. Useful for hacks
// that want to inspect the mode state (say, for completion).
getTokenAt: function(pos, precise) {

    // Fetch the parser token for a given character. Useful for hacks
// that want to inspect the mode state (say, for completion).
getTokenAt: function(pos, precise) {

      var doc = this.doc;
pos = clipPos(doc, pos);
var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
var line = getLine(doc, pos.line);
var stream = new StringStream(line.text, this.options.tabSize);
while (stream.pos < pos.ch && !stream.eol()) {
stream.start = stream.pos;
var style = readToken(mode, stream, state);
}
return {start: stream.start,
end: stream.pos,
string: stream.current(),
type: style || null,
state: state};

      return takeToken(this, pos, precise);
},

getLineTokens: function(line, precise) {
return takeToken(this, Pos(line), precise, true);










    },

getTokenTypeAt: function(pos) {

    },

getTokenTypeAt: function(pos) {

Zeile 3979Zeile 4237
      }
var cut = type ? type.indexOf("cm-overlay ") : -1;
return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);

      }
var cut = type ? type.indexOf("cm-overlay ") : -1;
return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);

    },


    },


    getModeAt: function(pos) {
var mode = this.doc.mode;
if (!mode.innerMode) return mode;

    getModeAt: function(pos) {
var mode = this.doc.mode;
if (!mode.innerMode) return mode;

Zeile 4006Zeile 4264
        found.push(help[mode.helperType]);
} else if (help[mode.name]) {
found.push(help[mode.name]);

        found.push(help[mode.helperType]);
} else if (help[mode.name]) {
found.push(help[mode.name]);

      }

      }

      for (var i = 0; i < help._global.length; i++) {
var cur = help._global[i];
if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
found.push(cur.val);
}
return found;

      for (var i = 0; i < help._global.length; i++) {
var cur = help._global[i];
if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
found.push(cur.val);
}
return found;

    },


    },


    getStateAfter: function(line, precise) {
var doc = this.doc;
line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
return getStateBefore(this, line + 1, precise);

    getStateAfter: function(line, precise) {
var doc = this.doc;
line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
return getStateBefore(this, line + 1, precise);

    },


    },


    cursorCoords: function(start, mode) {
var pos, range = this.doc.sel.primary();
if (start == null) pos = range.head;

    cursorCoords: function(start, mode) {
var pos, range = this.doc.sel.primary();
if (start == null) pos = range.head;

Zeile 4060Zeile 4318
        markers[gutterID] = value;
if (!value && isEmpty(markers)) line.gutterMarkers = null;
return true;

        markers[gutterID] = value;
if (!value && isEmpty(markers)) line.gutterMarkers = null;
return true;

      });
}),


      });
}),


    clearGutter: methodOp(function(gutterID) {
var cm = this, doc = cm.doc, i = doc.first;
doc.iter(function(line) {

    clearGutter: methodOp(function(gutterID) {
var cm = this, doc = cm.doc, i = doc.first;
doc.iter(function(line) {

Zeile 4103Zeile 4361
      pos = cursorCoords(this, clipPos(this.doc, pos));
var top = pos.bottom, left = pos.left;
node.style.position = "absolute";

      pos = cursorCoords(this, clipPos(this.doc, pos));
var top = pos.bottom, left = pos.left;
node.style.position = "absolute";

 
      node.setAttribute("cm-ignore-events", "true");

      display.sizer.appendChild(node);
if (vert == "over") {
top = pos.top;

      display.sizer.appendChild(node);
if (vert == "over") {
top = pos.top;

Zeile 4116Zeile 4375
          top = pos.bottom;
if (left + node.offsetWidth > hspace)
left = hspace - node.offsetWidth;

          top = pos.bottom;
if (left + node.offsetWidth > hspace)
left = hspace - node.offsetWidth;

      }

      }

      node.style.top = top + "px";
node.style.left = node.style.right = "";
if (horiz == "right") {

      node.style.top = top + "px";
node.style.left = node.style.right = "";
if (horiz == "right") {

Zeile 4129Zeile 4388
      }
if (scroll)
scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);

      }
if (scroll)
scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);

    },

    },


triggerOnKeyDown: methodOp(onKeyDown),
triggerOnKeyPress: methodOp(onKeyPress),


triggerOnKeyDown: methodOp(onKeyDown),
triggerOnKeyPress: methodOp(onKeyPress),

    triggerOnKeyUp: methodOp(onKeyUp),

    triggerOnKeyUp: onKeyUp,


execCommand: function(cmd) {
if (commands.hasOwnProperty(cmd))


execCommand: function(cmd) {
if (commands.hasOwnProperty(cmd))

Zeile 4169Zeile 4428
          var other = findPosH(doc, range.head, dir, unit, false);
return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
});

          var other = findPosH(doc, range.head, dir, unit, false);
return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
});

    }),


    }),


    findPosV: function(from, amount, unit, goalColumn) {
var dir = 1, x = goalColumn;
if (amount < 0) { dir = -1; amount = -amount; }

    findPosV: function(from, amount, unit, goalColumn) {
var dir = 1, x = goalColumn;
if (amount < 0) { dir = -1; amount = -amount; }

Zeile 4201Zeile 4460
      if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
doc.sel.ranges[i].goalColumn = goals[i];
}),

      if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
doc.sel.ranges[i].goalColumn = goals[i];
}),

 

// Find the word at the given position (as returned by coordsChar).
findWordAt: function(pos) {
var doc = this.doc, line = getLine(doc, pos.line).text;
var start = pos.ch, end = pos.ch;
if (line) {
var helper = this.getHelper(pos, "wordChars");
if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
var startChar = line.charAt(start);
var check = isWordChar(startChar, helper)
? function(ch) { return isWordChar(ch, helper); }
: /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
: function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
while (start > 0 && check(line.charAt(start - 1))) --start;
while (end < line.length && check(line.charAt(end))) ++end;
}
return new Range(Pos(pos.line, start), Pos(pos.line, end));
},


toggleOverwrite: function(value) {
if (value != null && value == this.state.overwrite) return;


toggleOverwrite: function(value) {
if (value != null && value == this.state.overwrite) return;

Zeile 4219Zeile 4496
      if (y != null) this.curOp.scrollTop = y;
}),
getScrollInfo: function() {

      if (y != null) this.curOp.scrollTop = y;
}),
getScrollInfo: function() {

      var scroller = this.display.scroller, co = scrollerCutOff;

      var scroller = this.display.scroller;

      return {left: scroller.scrollLeft, top: scroller.scrollTop,

      return {left: scroller.scrollLeft, top: scroller.scrollTop,

              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};


              height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
clientHeight: displayHeight(this), clientWidth: displayWidth(this)};

    },

scrollIntoView: methodOp(function(range, margin) {

    },

scrollIntoView: methodOp(function(range, margin) {

Zeile 4279Zeile 4557
      if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
estimateLineHeights(this);
signal(this, "refresh", this);

      if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
estimateLineHeights(this);
signal(this, "refresh", this);

    }),


    }),


    swapDoc: methodOp(function(doc) {
var old = this.doc;
old.cm = null;

    swapDoc: methodOp(function(doc) {
var old = this.doc;
old.cm = null;

Zeile 4288Zeile 4566
      clearCaches(this);
resetInput(this);
this.scrollTo(doc.scrollLeft, doc.scrollTop);

      clearCaches(this);
resetInput(this);
this.scrollTo(doc.scrollLeft, doc.scrollTop);

 
      this.curOp.forceScroll = true;

      signalLater(this, "swapDoc", this, old);
return old;
}),

      signalLater(this, "swapDoc", this, old);
return old;
}),

Zeile 4333Zeile 4612
    clearCaches(cm);
regChange(cm);
}, true);

    clearCaches(cm);
regChange(cm);
}, true);

  option("specialChars", /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g, function(cm, val) {

  option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val) {

    cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
cm.refresh();
}, true);

    cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
cm.refresh();
}, true);

Zeile 4346Zeile 4625
    themeChanged(cm);
guttersChanged(cm);
}, true);

    themeChanged(cm);
guttersChanged(cm);
}, true);

  option("keyMap", "default", keyMapChanged);






  option("keyMap", "default", function(cm, val, old) {
var next = getKeyMap(val);
var prev = old != CodeMirror.Init && getKeyMap(old);
if (prev && prev.detach) prev.detach(cm, next);
if (next.attach) next.attach(cm, prev || null);
});

  option("extraKeys", null);

option("lineWrapping", false, wrappingChanged, true);

  option("extraKeys", null);

option("lineWrapping", false, wrappingChanged, true);

Zeile 4358Zeile 4642
    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
cm.refresh();
}, true);

    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
cm.refresh();
}, true);

  option("coverGutterNextToScrollbar", false, updateScrollbars, true);







  option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);
option("scrollbarStyle", "native", function(cm) {
initScrollbars(cm);
updateScrollbars(cm);
cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
}, true);

  option("lineNumbers", false, function(cm) {
setGuttersForLineNumbers(cm.options);
guttersChanged(cm);

  option("lineNumbers", false, function(cm) {
setGuttersForLineNumbers(cm.options);
guttersChanged(cm);

Zeile 4414Zeile 4704
  // load a mode. (Preferred mechanism is the require/define calls.)
CodeMirror.defineMode = function(name, mode) {
if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;

  // load a mode. (Preferred mechanism is the require/define calls.)
CodeMirror.defineMode = function(name, mode) {
if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;

    if (arguments.length > 2) {
mode.dependencies = [];
for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
}

    if (arguments.length > 2)
mode.dependencies = Array.prototype.slice.call(arguments, 2);



    modes[name] = mode;
};


    modes[name] = mode;
};


Zeile 4500Zeile 4788
  CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
CodeMirror.registerHelper(type, name, value);
helpers[type]._global.push({pred: predicate, val: value});

  CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
CodeMirror.registerHelper(type, name, value);
helpers[type]._global.push({pred: predicate, val: value});

  };

  };


// MODE STATE HANDLING



// MODE STATE HANDLING


Zeile 4566Zeile 4854
    delLineLeft: function(cm) {
deleteNearSelection(cm, function(range) {
return {from: Pos(range.from().line, 0), to: range.from()};

    delLineLeft: function(cm) {
deleteNearSelection(cm, function(range) {
return {from: Pos(range.from().line, 0), to: range.from()};

 
      });
},
delWrappedLineLeft: function(cm) {
deleteNearSelection(cm, function(range) {
var top = cm.charCoords(range.head, "div").top + 5;
var leftPos = cm.coordsChar({left: 0, top: top}, "div");
return {from: leftPos, to: range.from()};
});
},
delWrappedLineRight: function(cm) {
deleteNearSelection(cm, function(range) {
var top = cm.charCoords(range.head, "div").top + 5;
var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
return {from: range.from(), to: rightPos };

      });
},
undo: function(cm) {cm.undo();},

      });
},
undo: function(cm) {cm.undo();},

Zeile 4580Zeile 4882
    },
goLineStartSmart: function(cm) {
cm.extendSelectionsBy(function(range) {

    },
goLineStartSmart: function(cm) {
cm.extendSelectionsBy(function(range) {

        var start = lineStart(cm, range.head.line);
var line = cm.getLineHandle(start.line);
var order = getOrder(line);
if (!order || order[0].level == 0) {
var firstNonWS = Math.max(0, line.text.search(/\S/));
var inWS = range.head.line == start.line && range.head.ch <= firstNonWS && range.head.ch;
return Pos(start.line, inWS ? 0 : firstNonWS);
}
return start;

        return lineStartSmart(cm, range.head);









      }, {origin: "+move", bias: 1});
},
goLineEnd: function(cm) {

      }, {origin: "+move", bias: 1});
},
goLineEnd: function(cm) {

Zeile 4605Zeile 4899
      cm.extendSelectionsBy(function(range) {
var top = cm.charCoords(range.head, "div").top + 5;
return cm.coordsChar({left: 0, top: top}, "div");

      cm.extendSelectionsBy(function(range) {
var top = cm.charCoords(range.head, "div").top + 5;
return cm.coordsChar({left: 0, top: top}, "div");

 
      }, sel_move);
},
goLineLeftSmart: function(cm) {
cm.extendSelectionsBy(function(range) {
var top = cm.charCoords(range.head, "div").top + 5;
var pos = cm.coordsChar({left: 0, top: top}, "div");
if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head);
return pos;

      }, sel_move);
},
goLineUp: function(cm) {cm.moveV(-1, "line");},

      }, sel_move);
},
goLineUp: function(cm) {cm.moveV(-1, "line");},

Zeile 4678Zeile 4980
    },
toggleOverwrite: function(cm) {cm.toggleOverwrite();}
};

    },
toggleOverwrite: function(cm) {cm.toggleOverwrite();}
};

 



// STANDARD KEYMAPS


// STANDARD KEYMAPS





  var keyMap = CodeMirror.keyMap = {};

  var keyMap = CodeMirror.keyMap = {};

 


  keyMap.basic = {
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",

  keyMap.basic = {
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",

Zeile 4695Zeile 4999
  // are simply ignored.
keyMap.pcDefault = {
"Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",

  // are simply ignored.
keyMap.pcDefault = {
"Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",

    "Ctrl-Home": "goDocStart", "Ctrl-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",

    "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",

    "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
"Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
"Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
"Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
"Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
fallthrough: "basic"

    "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
"Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
"Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
"Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
"Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
fallthrough: "basic"

  };
keyMap.macDefault = {
"Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
"Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
"Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
"Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
"Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
"Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
"Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection",
fallthrough: ["basic", "emacsy"]

 
  };
// Very basic readline/emacs-style bindings, which are standard on Mac.
keyMap.emacsy = {

  };
// Very basic readline/emacs-style bindings, which are standard on Mac.
keyMap.emacsy = {

Zeile 4719Zeile 5013
    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
"Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
"Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"

    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
"Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
"Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"

 
  };
keyMap.macDefault = {
"Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
"Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
"Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
"Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
"Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
"Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
"Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
fallthrough: ["basic", "emacsy"]

  };
keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;

  };
keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;





  // KEYMAP DISPATCH

  // KEYMAP DISPATCH


function getKeyMap(val) {
if (typeof val == "string") return keyMap[val];
else return val;
}

// Given an array of keymaps and a key name, call handle on any
// bindings found, until that returns a truthy value, at which point
// we consider the key handled. Implements things like binding a key
// to false stopping further handling and keymap fallthrough.
var lookupKey = CodeMirror.lookupKey = function(name, maps, handle) {
function lookup(map) {
map = getKeyMap(map);
var found = map[name];
if (found === false) return "stop";
if (found != null && handle(found)) return true;
if (map.nofallthrough) return "stop";

var fallthrough = map.fallthrough;
if (fallthrough == null) return false;
if (Object.prototype.toString.call(fallthrough) != "[object Array]")
return lookup(fallthrough);
for (var i = 0; i < fallthrough.length; ++i) {
var done = lookup(fallthrough[i]);
if (done) return done;









































function normalizeKeyName(name) {
var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
var alt, ctrl, shift, cmd;
for (var i = 0; i < parts.length - 1; i++) {
var mod = parts[i];
if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
else if (/^a(lt)?$/i.test(mod)) alt = true;
else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
else if (/^s(hift)$/i.test(mod)) shift = true;
else throw new Error("Unrecognized modifier name: " + mod);
}
if (alt) name = "Alt-" + name;
if (ctrl) name = "Ctrl-" + name;
if (cmd) name = "Cmd-" + name;
if (shift) name = "Shift-" + name;
return name;
}

// This is a kludge to keep keymaps mostly working as raw objects
// (backwards compatibility) while at the same time support features
// like normalization and multi-stroke key bindings. It compiles a
// new normalized keymap, and then updates the old object to reflect
// this.
CodeMirror.normalizeKeyMap = function(keymap) {
var copy = {};
for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
var value = keymap[keyname];
if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
if (value == "...") { delete keymap[keyname]; continue; }

var keys = map(keyname.split(" "), normalizeKeyName);
for (var i = 0; i < keys.length; i++) {
var val, name;
if (i == keys.length - 1) {
name = keyname;
val = value;
} else {
name = keys.slice(0, i + 1).join(" ");
val = "...";
}
var prev = copy[name];
if (!prev) copy[name] = val;
else if (prev != val) throw new Error("Inconsistent bindings for " + name);
}
delete keymap[keyname];
}
for (var prop in copy) keymap[prop] = copy[prop];
return keymap;
};

var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {
map = getKeyMap(map);
var found = map.call ? map.call(key, context) : map[key];
if (found === false) return "nothing";
if (found === "...") return "multi";
if (found != null && handle(found)) return "handled";

if (map.fallthrough) {
if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
return lookupKey(key, map.fallthrough, handle, context);
for (var i = 0; i < map.fallthrough.length; i++) {
var result = lookupKey(key, map.fallthrough[i], handle, context);
if (result) return result;

      }

      }

      return false;

 
    }

    }


for (var i = 0; i < maps.length; ++i) {
var done = lookup(maps[i]);
if (done) return done != "stop";
}
};


  };







  // Modifier key presses don't count as 'real' key presses for the
// purpose of keymap fallthrough.

  // Modifier key presses don't count as 'real' key presses for the
// purpose of keymap fallthrough.

  var isModifierKey = CodeMirror.isModifierKey = function(event) {
var name = keyNames[event.keyCode];

  var isModifierKey = CodeMirror.isModifierKey = function(value) {
var name = typeof value == "string" ? value : keyNames[value.keyCode];

    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";

    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";

  };


  };


  // Look up the name of a key as indicated by an event object.
var keyName = CodeMirror.keyName = function(event, noShift) {
if (presto && event.keyCode == 34 && event["char"]) return false;

  // Look up the name of a key as indicated by an event object.
var keyName = CodeMirror.keyName = function(event, noShift) {
if (presto && event.keyCode == 34 && event["char"]) return false;

    var name = keyNames[event.keyCode];

    var base = keyNames[event.keyCode], name = base;

    if (name == null || event.altGraphKey) return false;

    if (name == null || event.altGraphKey) return false;

    if (event.altKey) name = "Alt-" + name;
if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
if (!noShift && event.shiftKey) name = "Shift-" + name;

    if (event.altKey && base != "Alt") name = "Alt-" + name;
if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;

    return name;
};

    return name;
};

 

function getKeyMap(val) {
return typeof val == "string" ? keyMap[val] : val;
}


// FROMTEXTAREA



// FROMTEXTAREA


Zeile 4818Zeile 5159
    cm.save = save;
cm.getTextArea = function() { return textarea; };
cm.toTextArea = function() {

    cm.save = save;
cm.getTextArea = function() { return textarea; };
cm.toTextArea = function() {

 
      cm.toTextArea = isNaN; // Prevent this from being ran twice

      save();
textarea.parentNode.removeChild(cm.getWrapperElement());
textarea.style.display = "";

      save();
textarea.parentNode.removeChild(cm.getWrapperElement());
textarea.style.display = "";

Zeile 5054Zeile 5396
      // Showing up as a widget implies collapsed (widget replaces text)
marker.collapsed = true;
marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");

      // Showing up as a widget implies collapsed (widget replaces text)
marker.collapsed = true;
marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");

      if (!options.handleMouseEvents) marker.widgetNode.ignoreEvents = true;

      if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");

      if (options.insertLeft) marker.widgetNode.insertLeft = true;
}
if (marker.collapsed) {

      if (options.insertLeft) marker.widgetNode.insertLeft = true;
}
if (marker.collapsed) {

Zeile 5098Zeile 5440
      if (updateMaxLine) cm.curOp.updateMaxLine = true;
if (marker.collapsed)
regChange(cm, from.line, to.line + 1);

      if (updateMaxLine) cm.curOp.updateMaxLine = true;
if (marker.collapsed)
regChange(cm, from.line, to.line + 1);

      else if (marker.className || marker.title || marker.startStyle || marker.endStyle)

      else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)

        for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
if (marker.atomic) reCheckSelection(cm.doc);
signalLater(cm, "markerAdded", cm, marker);

        for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
if (marker.atomic) reCheckSelection(cm.doc);
signalLater(cm, "markerAdded", cm, marker);

Zeile 5238Zeile 5580
  // spans partially within the change. Returns an array of span
// arrays with one element for each line in (after) the change.
function stretchSpansOverChange(doc, change) {

  // spans partially within the change. Returns an array of span
// arrays with one element for each line in (after) the change.
function stretchSpansOverChange(doc, change) {

 
    if (change.full) return null;

    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
if (!oldFirst && !oldLast) return null;

    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
if (!oldFirst && !oldLast) return null;

Zeile 5294Zeile 5637
      newMarkers.push(last);
}
return newMarkers;

      newMarkers.push(last);
}
return newMarkers;

  }

  }


// Remove spans that are empty and don't have a clearWhenEmpty
// option of false.


// Remove spans that are empty and don't have a clearWhenEmpty
// option of false.

Zeile 5361Zeile 5704
      }
}
return parts;

      }
}
return parts;

  }

  }


// Connect or disconnect spans from a line.
function detachMarkedSpans(line) {


// Connect or disconnect spans from a line.
function detachMarkedSpans(line) {

Zeile 5401Zeile 5744
  // so, return the marker for that span.
function collapsedSpanAtSide(line, start) {
var sps = sawCollapsedSpans && line.markedSpans, found;

  // so, return the marker for that span.
function collapsedSpanAtSide(line, start) {
var sps = sawCollapsedSpans && line.markedSpans, found;

    if (sps) for (var sp, i = 0; i < sps.length; ++i) {

    if (sps) for (var sp, i = 0; i < sps.length; ++i) {

      sp = sps[i];
if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
(!found || compareCollapsedMarkers(found, sp.marker) < 0))

      sp = sps[i];
if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
(!found || compareCollapsedMarkers(found, sp.marker) < 0))

Zeile 5547Zeile 5890
    if (!contains(document.body, widget.node)) {
var parentStyle = "position: relative;";
if (widget.coverGutter)

    if (!contains(document.body, widget.node)) {
var parentStyle = "position: relative;";
if (widget.coverGutter)

        parentStyle += "margin-left: -" + widget.cm.getGutterElement().offsetWidth + "px;";



        parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;";
if (widget.noHScroll)
parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;";

      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));
}
return widget.height = widget.node.offsetHeight;

      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));
}
return widget.height = widget.node.offsetHeight;

Zeile 5616Zeile 5961
        output[prop] += " " + lineClass[2];
}
return type;

        output[prop] += " " + lineClass[2];
}
return type;

  }

  }


function callBlankLine(mode, state) {
if (mode.blankLine) return mode.blankLine(state);


function callBlankLine(mode, state) {
if (mode.blankLine) return mode.blankLine(state);

Zeile 5625Zeile 5970
    if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
}


    if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
}


  function readToken(mode, stream, state) {

  function readToken(mode, stream, state, inner) {

    for (var i = 0; i < 10; i++) {

    for (var i = 0; i < 10; i++) {

 
      if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;

      var style = mode.token(stream, state);
if (stream.pos > stream.start) return style;
}
throw new Error("Mode " + mode.name + " failed to advance stream.");

      var style = mode.token(stream, state);
if (stream.pos > stream.start) return style;
}
throw new Error("Mode " + mode.name + " failed to advance stream.");

 
  }

// Utility for getTokenAt and getLineTokens
function takeToken(cm, pos, precise, asArray) {
function getObj(copy) {
return {start: stream.start, end: stream.pos,
string: stream.current(),
type: style || null,
state: copy ? copyState(doc.mode, state) : state};
}

var doc = cm.doc, mode = doc.mode, style;
pos = clipPos(doc, pos);
var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
var stream = new StringStream(line.text, cm.options.tabSize), tokens;
if (asArray) tokens = [];
while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
stream.start = stream.pos;
style = readToken(mode, stream, state);
if (asArray) tokens.push(getObj(true));
}
return asArray ? tokens : getObj();

  }

// Run the given mode's parser over a line, calling f for each token.

  }

// Run the given mode's parser over a line, calling f for each token.

Zeile 5639Zeile 6007
    if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
var curStart = 0, curStyle = null;
var stream = new StringStream(text, cm.options.tabSize), style;

    if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
var curStart = 0, curStyle = null;
var stream = new StringStream(text, cm.options.tabSize), style;

 
    var inner = cm.options.addModeClass && [null];

    if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
while (!stream.eol()) {
if (stream.pos > cm.options.maxHighlightLength) {

    if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
while (!stream.eol()) {
if (stream.pos > cm.options.maxHighlightLength) {

Zeile 5647Zeile 6016
        stream.pos = text.length;
style = null;
} else {

        stream.pos = text.length;
style = null;
} else {

        style = extractLineClasses(readToken(mode, stream, state), lineClasses);

        style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);

      }

      }

      if (cm.options.addModeClass) {
var mName = CodeMirror.innerMode(mode, state).mode.name;

      if (inner) {
var mName = inner[0].name;

        if (mName) style = "m-" + (style ? mName + " " + style : mName);
}
if (!flattenSpans || curStyle != style) {

        if (mName) style = "m-" + (style ? mName + " " + style : mName);
}
if (!flattenSpans || curStyle != style) {

        if (curStart < stream.start) f(stream.start, curStyle);
curStart = stream.start; curStyle = style;




        while (curStart < stream.start) {
curStart = Math.min(stream.start, curStart + 50000);
f(curStart, curStyle);
}
curStyle = style;

      }
stream.start = stream.pos;
}

      }
stream.start = stream.pos;
}

Zeile 5664Zeile 6036
      var pos = Math.min(stream.pos, curStart + 50000);
f(pos, curStyle);
curStart = pos;

      var pos = Math.min(stream.pos, curStart + 50000);
f(pos, curStyle);
curStart = pos;

    }
}

    }
}


// Compute a style array (an array starting with a mode generation
// -- for invalidation -- followed by pairs of end positions and


// Compute a style array (an array starting with a mode generation
// -- for invalidation -- followed by pairs of end positions and

Zeile 5692Zeile 6064
            st.splice(i, 1, end, st[i+1], i_end);
i += 2;
at = Math.min(end, i_end);

            st.splice(i, 1, end, st[i+1], i_end);
i += 2;
at = Math.min(end, i_end);

        }

        }

        if (!style) return;
if (overlay.opaque) {
st.splice(start, i - start, end, "cm-overlay " + style);

        if (!style) return;
if (overlay.opaque) {
st.splice(start, i - start, end, "cm-overlay " + style);

Zeile 5707Zeile 6079
    }

return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};

    }

return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};

  }

function getLineStyles(cm, line) {

  }

function getLineStyles(cm, line, updateFrontier) {

    if (!line.styles || line.styles[0] != cm.state.modeGen) {
var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
line.styles = result.styles;
if (result.classes) line.styleClasses = result.classes;
else if (line.styleClasses) line.styleClasses = null;

    if (!line.styles || line.styles[0] != cm.state.modeGen) {
var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
line.styles = result.styles;
if (result.classes) line.styleClasses = result.classes;
else if (line.styleClasses) line.styleClasses = null;

 
      if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;

    }
return line.styles;
}

    }
return line.styles;
}

Zeile 5769Zeile 6142
      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
builder.addToken = buildTokenBadBidi(builder.addToken, order);
builder.map = [];

      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
builder.addToken = buildTokenBadBidi(builder.addToken, order);
builder.map = [];

      insertLineContent(line, builder, getLineStyles(cm, line));


      var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));

      if (line.styleClasses) {
if (line.styleClasses.bgClass)
builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");

      if (line.styleClasses) {
if (line.styleClasses.bgClass)
builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");

Zeile 5790Zeile 6164
        (lineView.measure.caches || (lineView.measure.caches = [])).push({});
}
}

        (lineView.measure.caches || (lineView.measure.caches = [])).push({});
}
}

 

// See issue #2901
if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
builder.content.className = "cm-tab-wrap-hack";


signal(cm, "renderLine", cm, lineView.line, builder.pre);
if (builder.pre.className)
builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");


signal(cm, "renderLine", cm, lineView.line, builder.pre);
if (builder.pre.className)
builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");

    return builder;
}



return builder;
}


function defaultSpecialCharPlaceholder(ch) {
var token = elt("span", "\u2022", "cm-invalidchar");


function defaultSpecialCharPlaceholder(ch) {
var token = elt("span", "\u2022", "cm-invalidchar");

Zeile 5805Zeile 6184

// Build up the DOM representation for a single token, and add it to
// the line map. Takes care to render special characters separately.


// Build up the DOM representation for a single token, and add it to
// the line map. Takes care to render special characters separately.

  function buildToken(builder, text, style, startStyle, endStyle, title) {

  function buildToken(builder, text, style, startStyle, endStyle, title, css) {

    if (!text) return;
var special = builder.cm.options.specialChars, mustWrap = false;
if (!special.test(text)) {

    if (!text) return;
var special = builder.cm.options.specialChars, mustWrap = false;
if (!special.test(text)) {

Zeile 5844Zeile 6223
        builder.pos++;
}
}

        builder.pos++;
}
}

    if (style || startStyle || endStyle || mustWrap) {

    if (style || startStyle || endStyle || mustWrap || css) {

      var fullStyle = style || "";
if (startStyle) fullStyle += startStyle;
if (endStyle) fullStyle += endStyle;

      var fullStyle = style || "";
if (startStyle) fullStyle += startStyle;
if (endStyle) fullStyle += endStyle;

      var token = elt("span", [content], fullStyle);

      var token = elt("span", [content], fullStyle, css);

      if (title) token.title = title;
return builder.content.appendChild(token);
}

      if (title) token.title = title;
return builder.content.appendChild(token);
}

Zeile 5907Zeile 6286
      return;
}


      return;
}


    var len = allText.length, pos = 0, i = 1, text = "", style;

    var len = allText.length, pos = 0, i = 1, text = "", style, css;

    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
for (;;) {
if (nextChange == pos) { // Update current marker set

    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
for (;;) {
if (nextChange == pos) { // Update current marker set

        spanStyle = spanEndStyle = spanStartStyle = title = "";

        spanStyle = spanEndStyle = spanStartStyle = title = css = "";

        collapsed = null; nextChange = Infinity;
var foundBookmarks = [];
for (var j = 0; j < spans.length; ++j) {

        collapsed = null; nextChange = Infinity;
var foundBookmarks = [];
for (var j = 0; j < spans.length; ++j) {

Zeile 5919Zeile 6298
          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
if (m.className) spanStyle += " " + m.className;

          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
if (m.className) spanStyle += " " + m.className;

 
            if (m.css) css = m.css;

            if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
if (m.title && !title) title = m.title;

            if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
if (m.title && !title) title = m.title;

Zeile 5946Zeile 6326
          if (!collapsed) {
var tokenText = end > upto ? text.slice(0, upto - pos) : text;
builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,

          if (!collapsed) {
var tokenText = end > upto ? text.slice(0, upto - pos) : text;
builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,

                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);

                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);

          }
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
pos = end;

          }
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
pos = end;

Zeile 5974Zeile 6354
    function update(line, text, spans) {
updateLine(line, text, spans, estimateHeight);
signalLater(line, "change", line, change);

    function update(line, text, spans) {
updateLine(line, text, spans, estimateHeight);
signalLater(line, "change", line, change);

 
    }
function linesFor(start, end) {
for (var i = start, result = []; i < end; ++i)
result.push(new Line(text[i], spansFor(i), estimateHeight));
return result;

    }

var from = change.from, to = change.to, text = change.text;

    }

var from = change.from, to = change.to, text = change.text;

Zeile 5981Zeile 6366
    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;

// Adjust the line structure

    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;

// Adjust the line structure

    if (isWholeLineUpdate(doc, change)) {




    if (change.full) {
doc.insert(0, linesFor(0, text.length));
doc.remove(text.length, doc.size - text.length);
} else if (isWholeLineUpdate(doc, change)) {

      // This is a whole-line replace. Treated specially to make
// sure line objects move the way they are supposed to.

      // This is a whole-line replace. Treated specially to make
// sure line objects move the way they are supposed to.

      for (var i = 0, added = []; i < text.length - 1; ++i)
added.push(new Line(text[i], spansFor(i), estimateHeight));

      var added = linesFor(0, text.length - 1);


      update(lastLine, lastLine.text, lastSpans);
if (nlines) doc.remove(from.line, nlines);
if (added.length) doc.insert(from.line, added);

      update(lastLine, lastLine.text, lastSpans);
if (nlines) doc.remove(from.line, nlines);
if (added.length) doc.insert(from.line, added);

Zeile 5993Zeile 6380
      if (text.length == 1) {
update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
} else {

      if (text.length == 1) {
update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
} else {

        for (var added = [], i = 1; i < text.length - 1; ++i)
added.push(new Line(text[i], spansFor(i), estimateHeight));

        var added = linesFor(1, text.length - 1);


        added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
doc.insert(from.line + 1, added);

        added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
doc.insert(from.line + 1, added);

Zeile 6005Zeile 6391
    } else {
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);

    } else {
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);

      for (var i = 1, added = []; i < text.length - 1; ++i)
added.push(new Line(text[i], spansFor(i), estimateHeight));

      var added = linesFor(1, text.length - 1);


      if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
doc.insert(from.line + 1, added);
}

      if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
doc.insert(from.line + 1, added);
}

Zeile 6217Zeile 6602
    setValue: docMethodOp(function(code) {
var top = Pos(this.first, 0), last = this.first + this.size - 1;
makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),

    setValue: docMethodOp(function(code) {
var top = Pos(this.first, 0), last = this.first + this.size - 1;
makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),

                        text: splitLines(code), origin: "setValue"}, true);

                        text: splitLines(code), origin: "setValue", full: true}, true);

      setSelection(this, simpleSelection(top));
}),
replaceRange: function(code, from, to, origin) {

      setSelection(this, simpleSelection(top));
}),
replaceRange: function(code, from, to, origin) {

Zeile 6344Zeile 6729
    },
changeGeneration: function(forceSplit) {
if (forceSplit)

    },
changeGeneration: function(forceSplit) {
if (forceSplit)

        this.history.lastOp = this.history.lastOrigin = null;

        this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;

      return this.history.generation;
},
isClean: function (gen) {

      return this.history.generation;
},
isClean: function (gen) {

Zeile 6362Zeile 6747
    },

addLineClass: docMethodOp(function(handle, where, cls) {

    },

addLineClass: docMethodOp(function(handle, where, cls) {

      return changeLine(this, handle, "class", function(line) {
var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";



      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
var prop = where == "text" ? "textClass"
: where == "background" ? "bgClass"
: where == "gutter" ? "gutterClass" : "wrapClass";

        if (!line[prop]) line[prop] = cls;

        if (!line[prop]) line[prop] = cls;

        else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;

        else if (classTest(cls).test(line[prop])) return false;

        else line[prop] += " " + cls;
return true;
});
}),
removeLineClass: docMethodOp(function(handle, where, cls) {

        else line[prop] += " " + cls;
return true;
});
}),
removeLineClass: docMethodOp(function(handle, where, cls) {

      return changeLine(this, handle, "class", function(line) {
var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";



      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
var prop = where == "text" ? "textClass"
: where == "background" ? "bgClass"
: where == "gutter" ? "gutterClass" : "wrapClass";

        var cur = line[prop];
if (!cur) return false;
else if (cls == null) line[prop] = null;
else {

        var cur = line[prop];
if (!cur) return false;
else if (cls == null) line[prop] = null;
else {

          var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));

          var found = cur.match(classTest(cls));

          if (!found) return false;
var end = found.index + found[0].length;
line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;

          if (!found) return false;
var end = found.index + found[0].length;
line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;

Zeile 6661Zeile 7050
    // Used to track when changes can be merged into a single undo
// event
this.lastModTime = this.lastSelTime = 0;

    // Used to track when changes can be merged into a single undo
// event
this.lastModTime = this.lastSelTime = 0;

    this.lastOp = null;

    this.lastOp = this.lastSelOp = null;

    this.lastOrigin = this.lastSelOrigin = null;
// Used by the isClean() method
this.generation = this.maxGeneration = startGen || 1;

    this.lastOrigin = this.lastSelOrigin = null;
// Used by the isClean() method
this.generation = this.maxGeneration = startGen || 1;

Zeile 6739Zeile 7128
    hist.done.push(selAfter);
hist.generation = ++hist.maxGeneration;
hist.lastModTime = hist.lastSelTime = time;

    hist.done.push(selAfter);
hist.generation = ++hist.maxGeneration;
hist.lastModTime = hist.lastSelTime = time;

    hist.lastOp = opId;

    hist.lastOp = hist.lastSelOp = opId;

    hist.lastOrigin = hist.lastSelOrigin = change.origin;

if (!last) signal(doc, "historyAdded");

    hist.lastOrigin = hist.lastSelOrigin = change.origin;

if (!last) signal(doc, "historyAdded");

Zeile 6765Zeile 7154
    // the current, or the origins don't allow matching. Origins
// starting with * are always merged, those starting with + are
// merged when similar and close together in time.

    // the current, or the origins don't allow matching. Origins
// starting with * are always merged, those starting with + are
// merged when similar and close together in time.

    if (opId == hist.lastOp ||

    if (opId == hist.lastSelOp ||

        (origin && hist.lastSelOrigin == origin &&
(hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))

        (origin && hist.lastSelOrigin == origin &&
(hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))

Zeile 6775Zeile 7164

hist.lastSelTime = +new Date;
hist.lastSelOrigin = origin;


hist.lastSelTime = +new Date;
hist.lastSelOrigin = origin;

    hist.lastOp = opId;

    hist.lastSelOp = opId;

    if (options && options.clearRedo !== false)
clearSelectionEvents(hist.undone);
}

    if (options && options.clearRedo !== false)
clearSelectionEvents(hist.undone);
}

Zeile 6959Zeile 7348
    var args = Array.prototype.slice.call(arguments, 2);
for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
};

    var args = Array.prototype.slice.call(arguments, 2);
for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
};

 

var orphanDelayedCallbacks = null;


// Often, we want to signal events at a point where we are in the
// middle of some work, but don't want the handler to start calling


// Often, we want to signal events at a point where we are in the
// middle of some work, but don't want the handler to start calling

Zeile 6967Zeile 7358
  // signalLater looks whether there are any handlers, and schedules
// them to be executed when the last operation ends, or, if no
// operation is active, when a timeout fires.

  // signalLater looks whether there are any handlers, and schedules
// them to be executed when the last operation ends, or, if no
// operation is active, when a timeout fires.

  var delayedCallbacks, delayedCallbackDepth = 0;

 
  function signalLater(emitter, type /*, values...*/) {
var arr = emitter._handlers && emitter._handlers[type];
if (!arr) return;

  function signalLater(emitter, type /*, values...*/) {
var arr = emitter._handlers && emitter._handlers[type];
if (!arr) return;

    var args = Array.prototype.slice.call(arguments, 2);
if (!delayedCallbacks) {
++delayedCallbackDepth;
delayedCallbacks = [];
setTimeout(fireDelayed, 0);




    var args = Array.prototype.slice.call(arguments, 2), list;
if (operationGroup) {
list = operationGroup.delayedCallbacks;
} else if (orphanDelayedCallbacks) {
list = orphanDelayedCallbacks;
} else {
list = orphanDelayedCallbacks = [];
setTimeout(fireOrphanDelayed, 0);

    }
function bnd(f) {return function(){f.apply(null, args);};};
for (var i = 0; i < arr.length; ++i)

    }
function bnd(f) {return function(){f.apply(null, args);};};
for (var i = 0; i < arr.length; ++i)

      delayedCallbacks.push(bnd(arr[i]));

      list.push(bnd(arr[i]));

  }


  }


  function fireDelayed() {
--delayedCallbackDepth;
var delayed = delayedCallbacks;
delayedCallbacks = null;

  function fireOrphanDelayed() {
var delayed = orphanDelayedCallbacks;
orphanDelayedCallbacks = null;


    for (var i = 0; i < delayed.length; ++i) delayed[i]();
}


    for (var i = 0; i < delayed.length; ++i) delayed[i]();
}


Zeile 6993Zeile 7385
  // registering a (non-DOM) handler on the editor for the event name,
// and preventDefault-ing the event in that handler.
function signalDOMEvent(cm, e, override) {

  // registering a (non-DOM) handler on the editor for the event name,
// and preventDefault-ing the event in that handler.
function signalDOMEvent(cm, e, override) {

 
    if (typeof e == "string")
e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};

    signal(cm, override || e.type, cm, e);
return e_defaultPrevented(e) || e.codemirrorIgnore;

    signal(cm, override || e.type, cm, e);
return e_defaultPrevented(e) || e.codemirrorIgnore;

  }

  }


function signalCursorActivity(cm) {
var arr = cm._handlers && cm._handlers.cursorActivity;


function signalCursorActivity(cm) {
var arr = cm._handlers && cm._handlers.cursorActivity;

Zeile 7008Zeile 7402
  function hasHandler(emitter, type) {
var arr = emitter._handlers && emitter._handlers[type];
return arr && arr.length > 0;

  function hasHandler(emitter, type) {
var arr = emitter._handlers && emitter._handlers[type];
return arr && arr.length > 0;

  }

  }


// Add on and off methods to a constructor's prototype, to make
// registering events on such objects more convenient.


// Add on and off methods to a constructor's prototype, to make
// registering events on such objects more convenient.

Zeile 7020Zeile 7414
  // MISC UTILITIES

// Number of pixels added to scroller and sizer to hide scrollbar

  // MISC UTILITIES

// Number of pixels added to scroller and sizer to hide scrollbar

  var scrollerCutOff = 30;


  var scrollerGap = 30;


  // Returned or thrown by various protocols to signal 'I'm not
// handling this'.
var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};

  // Returned or thrown by various protocols to signal 'I'm not
// handling this'.
var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};

Zeile 7088Zeile 7482
      if (array[i] == elt) return i;
return -1;
}

      if (array[i] == elt) return i;
return -1;
}

  if ([].indexOf) indexOf = function(array, elt) { return array.indexOf(elt); };

 
  function map(array, f) {
var out = [];
for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
return out;
}

  function map(array, f) {
var out = [];
for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
return out;
}

  if ([].map) map = function(array, f) { return array.map(f); };

 

function createObj(base, props) {
var inst;


function createObj(base, props) {
var inst;

Zeile 7122Zeile 7514
    return function(){return f.apply(null, args);};
}


    return function(){return f.apply(null, args);};
}


  var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;

  var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;

  var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
return /\w/.test(ch) || ch > "\x80" &&
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));

  var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
return /\w/.test(ch) || ch > "\x80" &&
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));

Zeile 7166Zeile 7558
  };
else range = function(node, start, end) {
var r = document.body.createTextRange();

  };
else range = function(node, start, end) {
var r = document.body.createTextRange();

    r.moveToElementText(node.parentNode);


    try { r.moveToElementText(node.parentNode); }
catch(e) { return r; }

    r.collapse(true);
r.moveEnd("character", end);
r.moveStart("character", start);

    r.collapse(true);
r.moveEnd("character", end);
r.moveStart("character", start);

Zeile 7198Zeile 7591
    catch(e) { return document.body; }
};


    catch(e) { return document.body; }
};


  function classTest(cls) { return new RegExp("\\b" + cls + "\\b\\s*"); }
function rmClass(node, cls) {
var test = classTest(cls);
if (test.test(node.className)) node.className = node.className.replace(test, "");
}
function addClass(node, cls) {
if (!classTest(cls).test(node.className)) node.className += " " + cls;
}






  function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
var rmClass = CodeMirror.rmClass = function(node, cls) {
var current = node.className;
var match = classTest(cls).exec(current);
if (match) {
var after = current.slice(match.index + match[0].length);
node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
}
};
var addClass = CodeMirror.addClass = function(node, cls) {
var current = node.className;
if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
};

  function joinClasses(a, b) {
var as = a.split(" ");
for (var i = 0; i < as.length; i++)

  function joinClasses(a, b) {
var as = a.split(" ");
for (var i = 0; i < as.length; i++)

Zeile 7240Zeile 7638
    on(window, "resize", function() {
if (resizeTimer == null) resizeTimer = setTimeout(function() {
resizeTimer = null;

    on(window, "resize", function() {
if (resizeTimer == null) resizeTimer = setTimeout(function() {
resizeTimer = null;

        knownScrollbarWidth = null;

 
        forEachCodeMirror(onResize);
}, 100);
});

        forEachCodeMirror(onResize);
}, 100);
});

Zeile 7260Zeile 7657
    var div = elt('div');
return "draggable" in div || "dragDrop" in div;
}();

    var div = elt('div');
return "draggable" in div || "dragDrop" in div;
}();


var knownScrollbarWidth;
function scrollbarWidth(measure) {
if (knownScrollbarWidth != null) return knownScrollbarWidth;
var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
removeChildrenAndAdd(measure, test);
if (test.offsetWidth)
knownScrollbarWidth = test.offsetHeight - test.clientHeight;
return knownScrollbarWidth || 0;
}

 

var zwspSupported;
function zeroWidthElement(measure) {


var zwspSupported;
function zeroWidthElement(measure) {

Zeile 7289Zeile 7676
    if (badBidiRects != null) return badBidiRects;
var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
var r0 = range(txt, 0, 1).getBoundingClientRect();

    if (badBidiRects != null) return badBidiRects;
var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
var r0 = range(txt, 0, 1).getBoundingClientRect();

    if (r0.left == r0.right) return false;

    if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)

    var r1 = range(txt, 1, 2).getBoundingClientRect();
return badBidiRects = (r1.right - r0.right < 3);
}

    var r1 = range(txt, 1, 2).getBoundingClientRect();
return badBidiRects = (r1.right - r0.right < 3);
}

Zeile 7330Zeile 7717
    e.setAttribute("oncopy", "return;");
return typeof e.oncopy == "function";
})();

    e.setAttribute("oncopy", "return;");
return typeof e.oncopy == "function";
})();

 

var badZoomedRects = null;
function hasBadZoomedRects(measure) {
if (badZoomedRects != null) return badZoomedRects;
var node = removeChildrenAndAdd(measure, elt("span", "x"));
var normal = node.getBoundingClientRect();
var fromRange = range(node, 0, 1).getBoundingClientRect();
return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;
}


// KEY NAMES



// KEY NAMES


Zeile 7392Zeile 7788
    var order = getOrder(line);
var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
return Pos(lineN == null ? lineNo(line) : lineN, ch);

    var order = getOrder(line);
var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
return Pos(lineN == null ? lineNo(line) : lineN, ch);

 
  }
function lineStartSmart(cm, pos) {
var start = lineStart(cm, pos.line);
var line = getLine(cm.doc, start.line);
var order = getOrder(line);
if (!order || order[0].level == 0) {
var firstNonWS = Math.max(0, line.text.search(/\S/));
var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
return Pos(start.line, inWS ? 0 : firstNonWS);
}
return start;

  }

function compareBidiLevel(order, a, b) {

  }

function compareBidiLevel(order, a, b) {

Zeile 7632Zeile 8039

// THE END



// THE END


  CodeMirror.version = "4.3.0";

  CodeMirror.version = "4.12.0";


return CodeMirror;
});


return CodeMirror;
});