##// END OF EJS Templates
update codemirror to latest version
marcink -
r4042:af3c746b default
parent child Browse files
Show More
@@ -19,7 +19,7 b''
19 padding: 0 4px; /* Horizontal padding of content */
19 padding: 0 4px; /* Horizontal padding of content */
20 }
20 }
21
21
22 .CodeMirror-scrollbar-filler {
22 .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
23 background-color: white; /* The little square between H and V scrollbars */
23 background-color: white; /* The little square between H and V scrollbars */
24 }
24 }
25
25
@@ -28,6 +28,7 b''
28 .CodeMirror-gutters {
28 .CodeMirror-gutters {
29 border-right: 1px solid #ddd;
29 border-right: 1px solid #ddd;
30 background-color: #f7f7f7;
30 background-color: #f7f7f7;
31 white-space: nowrap;
31 }
32 }
32 .CodeMirror-linenumbers {}
33 .CodeMirror-linenumbers {}
33 .CodeMirror-linenumber {
34 .CodeMirror-linenumber {
@@ -124,7 +125,7 b' div.CodeMirror span.CodeMirror-nonmatchi'
124 /* The fake, visible scrollbars. Used to force redraw during scrolling
125 /* The fake, visible scrollbars. Used to force redraw during scrolling
125 before actuall scrolling happens, thus preventing shaking and
126 before actuall scrolling happens, thus preventing shaking and
126 flickering artifacts. */
127 flickering artifacts. */
127 .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
128 .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
128 position: absolute;
129 position: absolute;
129 z-index: 6;
130 z-index: 6;
130 display: none;
131 display: none;
@@ -141,16 +142,18 b' div.CodeMirror span.CodeMirror-nonmatchi'
141 }
142 }
142 .CodeMirror-scrollbar-filler {
143 .CodeMirror-scrollbar-filler {
143 right: 0; bottom: 0;
144 right: 0; bottom: 0;
144 z-index: 6;
145 }
146 .CodeMirror-gutter-filler {
147 left: 0; bottom: 0;
145 }
148 }
146
149
147 .CodeMirror-gutters {
150 .CodeMirror-gutters {
148 position: absolute; left: 0; top: 0;
151 position: absolute; left: 0; top: 0;
149 height: 100%;
150 padding-bottom: 30px;
152 padding-bottom: 30px;
151 z-index: 3;
153 z-index: 3;
152 }
154 }
153 .CodeMirror-gutter {
155 .CodeMirror-gutter {
156 white-space: normal;
154 height: 100%;
157 height: 100%;
155 padding-bottom: 30px;
158 padding-bottom: 30px;
156 margin-bottom: -32px;
159 margin-bottom: -32px;
@@ -202,7 +205,6 b' div.CodeMirror span.CodeMirror-nonmatchi'
202 }
205 }
203
206
204 .CodeMirror-widget {
207 .CodeMirror-widget {
205 display: inline-block;
206 }
208 }
207
209
208 .CodeMirror-wrap .CodeMirror-scroll {
210 .CodeMirror-wrap .CodeMirror-scroll {
This diff has been collapsed as it changes many lines, (870 lines changed) Show them Hide them
@@ -1,3 +1,5 b''
1 // CodeMirror version 3.14
2 //
1 // CodeMirror is the only global var we claim
3 // CodeMirror is the only global var we claim
2 window.CodeMirror = (function() {
4 window.CodeMirror = (function() {
3 "use strict";
5 "use strict";
@@ -97,7 +99,7 b' window.CodeMirror = (function() {'
97 else input.setAttribute("wrap", "off");
99 else input.setAttribute("wrap", "off");
98 // if border: 0; -- iOS fails to open keyboard (issue #1287)
100 // if border: 0; -- iOS fails to open keyboard (issue #1287)
99 if (ios) input.style.border = "1px solid black";
101 if (ios) input.style.border = "1px solid black";
100 input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off");
102 input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
101
103
102 // Wraps and hides input textarea
104 // Wraps and hides input textarea
103 d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
105 d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
@@ -105,8 +107,9 b' window.CodeMirror = (function() {'
105 d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
107 d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
106 d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
108 d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
107 d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
109 d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
110 d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
108 // DIVs containing the selection and the actual code
111 // DIVs containing the selection and the actual code
109 d.lineDiv = elt("div");
112 d.lineDiv = elt("div", null, "CodeMirror-code");
110 d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
113 d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
111 // Blinky cursor, and element used to ensure cursor fits at the end of a line
114 // Blinky cursor, and element used to ensure cursor fits at the end of a line
112 d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
115 d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
@@ -126,14 +129,12 b' window.CodeMirror = (function() {'
126 // Will contain the gutters, if any
129 // Will contain the gutters, if any
127 d.gutters = elt("div", null, "CodeMirror-gutters");
130 d.gutters = elt("div", null, "CodeMirror-gutters");
128 d.lineGutter = null;
131 d.lineGutter = null;
129 // Helper element to properly size the gutter backgrounds
130 var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%");
131 // Provides scrolling
132 // Provides scrolling
132 d.scroller = elt("div", [scrollerInner], "CodeMirror-scroll");
133 d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
133 d.scroller.setAttribute("tabIndex", "-1");
134 d.scroller.setAttribute("tabIndex", "-1");
134 // The element in which the editor lives.
135 // The element in which the editor lives.
135 d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
136 d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
136 d.scrollbarFiller, d.scroller], "CodeMirror");
137 d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
137 // Work around IE7 z-index bug
138 // Work around IE7 z-index bug
138 if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
139 if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
139 if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
140 if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
@@ -212,7 +213,7 b' window.CodeMirror = (function() {'
212 estimateLineHeights(cm);
213 estimateLineHeights(cm);
213 regChange(cm);
214 regChange(cm);
214 clearCaches(cm);
215 clearCaches(cm);
215 setTimeout(function(){updateScrollbars(cm.display, cm.doc.height);}, 100);
216 setTimeout(function(){updateScrollbars(cm);}, 100);
216 }
217 }
217
218
218 function estimateHeight(cm) {
219 function estimateHeight(cm) {
@@ -237,9 +238,10 b' window.CodeMirror = (function() {'
237 }
238 }
238
239
239 function keyMapChanged(cm) {
240 function keyMapChanged(cm) {
240 var style = keyMap[cm.options.keyMap].style;
241 var map = keyMap[cm.options.keyMap], style = map.style;
241 cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
242 cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
242 (style ? " cm-keymap-" + style : "");
243 (style ? " cm-keymap-" + style : "");
244 cm.state.disableInput = map.disableInput;
243 }
245 }
244
246
245 function themeChanged(cm) {
247 function themeChanged(cm) {
@@ -251,6 +253,7 b' window.CodeMirror = (function() {'
251 function guttersChanged(cm) {
253 function guttersChanged(cm) {
252 updateGutters(cm);
254 updateGutters(cm);
253 regChange(cm);
255 regChange(cm);
256 setTimeout(function(){alignHorizontally(cm);}, 20);
254 }
257 }
255
258
256 function updateGutters(cm) {
259 function updateGutters(cm) {
@@ -317,12 +320,14 b' window.CodeMirror = (function() {'
317
320
318 // Re-synchronize the fake scrollbars with the actual size of the
321 // Re-synchronize the fake scrollbars with the actual size of the
319 // content. Optionally force a scrollTop.
322 // content. Optionally force a scrollTop.
320 function updateScrollbars(d /* display */, docHeight) {
323 function updateScrollbars(cm) {
324 var d = cm.display, docHeight = cm.doc.height;
321 var totalHeight = docHeight + paddingVert(d);
325 var totalHeight = docHeight + paddingVert(d);
322 d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
326 d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
327 d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
323 var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
328 var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
324 var needsH = d.scroller.scrollWidth > d.scroller.clientWidth;
329 var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
325 var needsV = scrollHeight > d.scroller.clientHeight;
330 var needsV = scrollHeight > (d.scroller.clientHeight + 1);
326 if (needsV) {
331 if (needsV) {
327 d.scrollbarV.style.display = "block";
332 d.scrollbarV.style.display = "block";
328 d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
333 d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
@@ -339,6 +344,11 b' window.CodeMirror = (function() {'
339 d.scrollbarFiller.style.display = "block";
344 d.scrollbarFiller.style.display = "block";
340 d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
345 d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
341 } else d.scrollbarFiller.style.display = "";
346 } else d.scrollbarFiller.style.display = "";
347 if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
348 d.gutterFiller.style.display = "block";
349 d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
350 d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
351 } else d.gutterFiller.style.display = "";
342
352
343 if (mac_geLion && scrollbarWidth(d.measure) === 0)
353 if (mac_geLion && scrollbarWidth(d.measure) === 0)
344 d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
354 d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
@@ -397,14 +407,10 b' window.CodeMirror = (function() {'
397 var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
407 var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
398 var visible = visibleLines(cm.display, cm.doc, viewPort);
408 var visible = visibleLines(cm.display, cm.doc, viewPort);
399 for (;;) {
409 for (;;) {
400 if (updateDisplayInner(cm, changes, visible)) {
410 if (!updateDisplayInner(cm, changes, visible)) break;
401 updated = true;
411 updated = true;
402 signalLater(cm, "update", cm);
403 if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
404 signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
405 } else break;
406 updateSelection(cm);
412 updateSelection(cm);
407 updateScrollbars(cm.display, cm.doc.height);
413 updateScrollbars(cm);
408
414
409 // Clip forced viewport to actual scrollable area
415 // Clip forced viewport to actual scrollable area
410 if (viewPort)
416 if (viewPort)
@@ -416,6 +422,11 b' window.CodeMirror = (function() {'
416 changes = [];
422 changes = [];
417 }
423 }
418
424
425 if (updated) {
426 signalLater(cm, "update", cm);
427 if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
428 signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
429 }
419 return updated;
430 return updated;
420 }
431 }
421
432
@@ -503,9 +514,11 b' window.CodeMirror = (function() {'
503 display.lastSizeC != display.wrapper.clientHeight;
514 display.lastSizeC != display.wrapper.clientHeight;
504 // This is just a bogus formula that detects when the editor is
515 // This is just a bogus formula that detects when the editor is
505 // resized or the font size changes.
516 // resized or the font size changes.
506 if (different) display.lastSizeC = display.wrapper.clientHeight;
517 if (different) {
518 display.lastSizeC = display.wrapper.clientHeight;
519 startWorker(cm, 400);
520 }
507 display.showingFrom = from; display.showingTo = to;
521 display.showingFrom = from; display.showingTo = to;
508 startWorker(cm, 100);
509
522
510 var prevBottom = display.lineDiv.offsetTop;
523 var prevBottom = display.lineDiv.offsetTop;
511 for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
524 for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
@@ -594,8 +607,9 b' window.CodeMirror = (function() {'
594 if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
607 if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
595 if (lineIsHidden(cm.doc, line)) {
608 if (lineIsHidden(cm.doc, line)) {
596 if (line.height != 0) updateLineHeight(line, 0);
609 if (line.height != 0) updateLineHeight(line, 0);
597 if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i)
610 if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
598 if (line.widgets[i].showIfHidden) {
611 var w = line.widgets[i];
612 if (w.showIfHidden) {
599 var prev = cur.previousSibling;
613 var prev = cur.previousSibling;
600 if (/pre/i.test(prev.nodeName)) {
614 if (/pre/i.test(prev.nodeName)) {
601 var wrap = elt("div", null, null, "position: relative");
615 var wrap = elt("div", null, null, "position: relative");
@@ -603,9 +617,11 b' window.CodeMirror = (function() {'
603 wrap.appendChild(prev);
617 wrap.appendChild(prev);
604 prev = wrap;
618 prev = wrap;
605 }
619 }
606 var wnode = prev.appendChild(elt("div", [line.widgets[i].node], "CodeMirror-linewidget"));
620 var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
607 positionLineWidget(line.widgets[i], wnode, prev, dims);
621 if (!w.handleMouseEvents) wnode.ignoreEvents = true;
622 positionLineWidget(w, wnode, prev, dims);
608 }
623 }
624 }
609 } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
625 } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
610 // This line is intact. Skip to the actual node. Update its
626 // This line is intact. Skip to the actual node. Update its
611 // line number if needed.
627 // line number if needed.
@@ -648,25 +664,25 b' window.CodeMirror = (function() {'
648
664
649 if (reuse) {
665 if (reuse) {
650 reuse.alignable = null;
666 reuse.alignable = null;
651 var isOk = true, widgetsSeen = 0;
667 var isOk = true, widgetsSeen = 0, insertBefore = null;
652 for (var n = reuse.firstChild, next; n; n = next) {
668 for (var n = reuse.firstChild, next; n; n = next) {
653 next = n.nextSibling;
669 next = n.nextSibling;
654 if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
670 if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
655 reuse.removeChild(n);
671 reuse.removeChild(n);
656 } else {
672 } else {
657 for (var i = 0, first = true; i < line.widgets.length; ++i) {
673 for (var i = 0, first = true; i < line.widgets.length; ++i) {
658 var widget = line.widgets[i], isFirst = false;
674 var widget = line.widgets[i];
659 if (!widget.above) { isFirst = first; first = false; }
675 if (!widget.above) { insertBefore = n; first = false; }
660 if (widget.node == n.firstChild) {
676 if (widget.node == n.firstChild) {
661 positionLineWidget(widget, n, reuse, dims);
677 positionLineWidget(widget, n, reuse, dims);
662 ++widgetsSeen;
678 ++widgetsSeen;
663 if (isFirst) reuse.insertBefore(lineElement, n);
664 break;
679 break;
665 }
680 }
666 }
681 }
667 if (i == line.widgets.length) { isOk = false; break; }
682 if (i == line.widgets.length) { isOk = false; break; }
668 }
683 }
669 }
684 }
685 reuse.insertBefore(lineElement, insertBefore);
670 if (isOk && widgetsSeen == line.widgets.length) {
686 if (isOk && widgetsSeen == line.widgets.length) {
671 wrap = reuse;
687 wrap = reuse;
672 reuse.className = line.wrapClass || "";
688 reuse.className = line.wrapClass || "";
@@ -701,6 +717,7 b' window.CodeMirror = (function() {'
701 if (ie_lt8) wrap.style.zIndex = 2;
717 if (ie_lt8) wrap.style.zIndex = 2;
702 if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
718 if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
703 var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
719 var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
720 if (!widget.handleMouseEvents) node.ignoreEvents = true;
704 positionLineWidget(widget, node, wrap, dims);
721 positionLineWidget(widget, node, wrap, dims);
705 if (widget.above)
722 if (widget.above)
706 wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
723 wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
@@ -783,74 +800,59 b' window.CodeMirror = (function() {'
783 "px; height: " + (bottom - top) + "px"));
800 "px; height: " + (bottom - top) + "px"));
784 }
801 }
785
802
786 function drawForLine(line, fromArg, toArg, retTop) {
803 function drawForLine(line, fromArg, toArg) {
787 var lineObj = getLine(doc, line);
804 var lineObj = getLine(doc, line);
788 var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity;
805 var lineLen = lineObj.text.length;
789 function coords(ch) {
806 var start, end;
790 return charCoords(cm, Pos(line, ch), "div", lineObj);
807 function coords(ch, bias) {
808 return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
791 }
809 }
792
810
793 iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
811 iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
794 var leftPos = coords(from), rightPos, left, right;
812 var leftPos = coords(from, "left"), rightPos, left, right;
795 if (from == to) {
813 if (from == to) {
796 rightPos = leftPos;
814 rightPos = leftPos;
797 left = right = leftPos.left;
815 left = right = leftPos.left;
798 } else {
816 } else {
799 rightPos = coords(to - 1);
817 rightPos = coords(to - 1, "right");
800 if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
818 if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
801 left = leftPos.left;
819 left = leftPos.left;
802 right = rightPos.right;
820 right = rightPos.right;
803 }
821 }
822 if (fromArg == null && from == 0) left = pl;
804 if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
823 if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
805 add(left, leftPos.top, null, leftPos.bottom);
824 add(left, leftPos.top, null, leftPos.bottom);
806 left = pl;
825 left = pl;
807 if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
826 if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
808 }
827 }
809 if (toArg == null && to == lineLen) right = clientWidth;
828 if (toArg == null && to == lineLen) right = clientWidth;
810 if (fromArg == null && from == 0) left = pl;
829 if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
811 rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal);
830 start = leftPos;
831 if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
832 end = rightPos;
812 if (left < pl + 1) left = pl;
833 if (left < pl + 1) left = pl;
813 add(left, rightPos.top, right - left, rightPos.bottom);
834 add(left, rightPos.top, right - left, rightPos.bottom);
814 });
835 });
815 return rVal;
836 return {start: start, end: end};
816 }
837 }
817
838
818 if (sel.from.line == sel.to.line) {
839 if (sel.from.line == sel.to.line) {
819 drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
840 drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
820 } else {
841 } else {
821 var fromObj = getLine(doc, sel.from.line);
842 var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
822 var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine;
843 var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
823 while (merged = collapsedSpanAtEnd(cur)) {
844 var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
824 var found = merged.find();
845 var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
825 path.push(found.from.ch, found.to.line, found.to.ch);
846 if (singleVLine) {
826 if (found.to.line == sel.to.line) {
847 if (leftEnd.top < rightStart.top - 2) {
827 path.push(sel.to.ch);
848 add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
828 singleLine = true;
849 add(pl, rightStart.top, rightStart.left, rightStart.bottom);
829 break;
850 } else {
851 add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
830 }
852 }
831 cur = getLine(doc, found.to.line);
832 }
853 }
833
854 if (leftEnd.bottom < rightStart.top)
834 // This is a single, merged line
855 add(pl, leftEnd.bottom, null, rightStart.top);
835 if (singleLine) {
836 for (var i = 0; i < path.length; i += 3)
837 drawForLine(path[i], path[i+1], path[i+2]);
838 } else {
839 var middleTop, middleBot, toObj = getLine(doc, sel.to.line);
840 if (sel.from.ch)
841 // Draw the first line of selection.
842 middleTop = drawForLine(sel.from.line, sel.from.ch, null, false);
843 else
844 // Simply include it in the middle block.
845 middleTop = heightAtLine(cm, fromObj) - display.viewOffset;
846
847 if (!sel.to.ch)
848 middleBot = heightAtLine(cm, toObj) - display.viewOffset;
849 else
850 middleBot = drawForLine(sel.to.line, collapsedSpanAtStart(toObj) ? null : 0, sel.to.ch, true);
851
852 if (middleTop < middleBot) add(pl, middleTop, null, middleBot);
853 }
854 }
856 }
855
857
856 removeChildrenAndAdd(display.selectionDiv, fragment);
858 removeChildrenAndAdd(display.selectionDiv, fragment);
@@ -916,12 +918,12 b' window.CodeMirror = (function() {'
916 // valid state. If that fails, it returns the line with the
918 // valid state. If that fails, it returns the line with the
917 // smallest indentation, which tends to need the least context to
919 // smallest indentation, which tends to need the least context to
918 // parse correctly.
920 // parse correctly.
919 function findStartLine(cm, n) {
921 function findStartLine(cm, n, precise) {
920 var minindent, minline, doc = cm.doc;
922 var minindent, minline, doc = cm.doc;
921 for (var search = n, lim = n - 100; search > lim; --search) {
923 for (var search = n, lim = n - 100; search > lim; --search) {
922 if (search <= doc.first) return doc.first;
924 if (search <= doc.first) return doc.first;
923 var line = getLine(doc, search - 1);
925 var line = getLine(doc, search - 1);
924 if (line.stateAfter) return search;
926 if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
925 var indented = countColumn(line.text, null, cm.options.tabSize);
927 var indented = countColumn(line.text, null, cm.options.tabSize);
926 if (minline == null || minindent > indented) {
928 if (minline == null || minindent > indented) {
927 minline = search - 1;
929 minline = search - 1;
@@ -931,10 +933,10 b' window.CodeMirror = (function() {'
931 return minline;
933 return minline;
932 }
934 }
933
935
934 function getStateBefore(cm, n) {
936 function getStateBefore(cm, n, precise) {
935 var doc = cm.doc, display = cm.display;
937 var doc = cm.doc, display = cm.display;
936 if (!doc.mode.startState) return true;
938 if (!doc.mode.startState) return true;
937 var pos = findStartLine(cm, n), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
939 var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
938 if (!state) state = startState(doc.mode);
940 if (!state) state = startState(doc.mode);
939 else state = copyState(doc.mode, state);
941 else state = copyState(doc.mode, state);
940 doc.iter(pos, n, function(line) {
942 doc.iter(pos, n, function(line) {
@@ -955,7 +957,7 b' window.CodeMirror = (function() {'
955 return e.offsetLeft;
957 return e.offsetLeft;
956 }
958 }
957
959
958 function measureChar(cm, line, ch, data) {
960 function measureChar(cm, line, ch, data, bias) {
959 var dir = -1;
961 var dir = -1;
960 data = data || measureLine(cm, line);
962 data = data || measureLine(cm, line);
961
963
@@ -964,9 +966,11 b' window.CodeMirror = (function() {'
964 if (r) break;
966 if (r) break;
965 if (dir < 0 && pos == 0) dir = 1;
967 if (dir < 0 && pos == 0) dir = 1;
966 }
968 }
969 var rightV = (pos < ch || bias == "right") && r.topRight != null;
967 return {left: pos < ch ? r.right : r.left,
970 return {left: pos < ch ? r.right : r.left,
968 right: pos > ch ? r.left : r.right,
971 right: pos > ch ? r.left : r.right,
969 top: r.top, bottom: r.bottom};
972 top: rightV ? r.topRight : r.top,
973 bottom: rightV ? r.bottomRight : r.bottom};
970 }
974 }
971
975
972 function findCachedMeasurement(cm, line) {
976 function findCachedMeasurement(cm, line) {
@@ -976,23 +980,28 b' window.CodeMirror = (function() {'
976 if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
980 if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
977 cm.display.scroller.clientWidth == memo.width &&
981 cm.display.scroller.clientWidth == memo.width &&
978 memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
982 memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
979 return memo.measure;
983 return memo;
980 }
984 }
985 }
986
987 function clearCachedMeasurement(cm, line) {
988 var exists = findCachedMeasurement(cm, line);
989 if (exists) exists.text = exists.measure = exists.markedSpans = null;
981 }
990 }
982
991
983 function measureLine(cm, line) {
992 function measureLine(cm, line) {
984 // First look in the cache
993 // First look in the cache
985 var measure = findCachedMeasurement(cm, line);
994 var cached = findCachedMeasurement(cm, line);
986 if (!measure) {
995 if (cached) return cached.measure;
987 // Failing that, recompute and store result in cache
996
988 measure = measureLineInner(cm, line);
997 // Failing that, recompute and store result in cache
989 var cache = cm.display.measureLineCache;
998 var measure = measureLineInner(cm, line);
990 var memo = {text: line.text, width: cm.display.scroller.clientWidth,
999 var cache = cm.display.measureLineCache;
991 markedSpans: line.markedSpans, measure: measure,
1000 var memo = {text: line.text, width: cm.display.scroller.clientWidth,
992 classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
1001 markedSpans: line.markedSpans, measure: measure,
993 if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
1002 classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
994 else cache.push(memo);
1003 if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
995 }
1004 else cache.push(memo);
996 return measure;
1005 return measure;
997 }
1006 }
998
1007
@@ -1034,9 +1043,9 b' window.CodeMirror = (function() {'
1034 if (ie_lt9 && display.measure.first != pre)
1043 if (ie_lt9 && display.measure.first != pre)
1035 removeChildrenAndAdd(display.measure, pre);
1044 removeChildrenAndAdd(display.measure, pre);
1036
1045
1037 for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1046 function categorizeVSpan(top, bot) {
1038 var size = getRect(cur);
1047 if (bot > maxBot) bot = maxBot;
1039 var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
1048 if (top < 0) top = 0;
1040 for (var j = 0; j < vranges.length; j += 2) {
1049 for (var j = 0; j < vranges.length; j += 2) {
1041 var rtop = vranges[j], rbot = vranges[j+1];
1050 var rtop = vranges[j], rbot = vranges[j+1];
1042 if (rtop > bot || rbot < top) continue;
1051 if (rtop > bot || rbot < top) continue;
@@ -1045,19 +1054,38 b' window.CodeMirror = (function() {'
1045 Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1054 Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1046 vranges[j] = Math.min(top, rtop);
1055 vranges[j] = Math.min(top, rtop);
1047 vranges[j+1] = Math.max(bot, rbot);
1056 vranges[j+1] = Math.max(bot, rbot);
1048 break;
1057 return j;
1049 }
1058 }
1050 }
1059 }
1051 if (j == vranges.length) vranges.push(top, bot);
1060 vranges.push(top, bot);
1061 return j;
1062 }
1063
1064 for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1065 var size, node = cur;
1066 // A widget might wrap, needs special care
1067 if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1068 if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1069 var rects = node.getClientRects(), rLeft = rects[0], rRight = rects[rects.length - 1];
1070 if (rects.length > 1) {
1071 var vCatLeft = categorizeVSpan(rLeft.top - outer.top, rLeft.bottom - outer.top);
1072 var vCatRight = categorizeVSpan(rRight.top - outer.top, rRight.bottom - outer.top);
1073 data[i] = {left: rLeft.left - outer.left, right: rRight.right - outer.left,
1074 top: vCatLeft, topRight: vCatRight};
1075 continue;
1076 }
1077 }
1078 size = getRect(node);
1079 var vCat = categorizeVSpan(size.top - outer.top, size.bottom - outer.top);
1052 var right = size.right;
1080 var right = size.right;
1053 if (cur.measureRight) right = getRect(cur.measureRight).left;
1081 if (cur.measureRight) right = getRect(cur.measureRight).left;
1054 data[i] = {left: size.left - outer.left, right: right - outer.left, top: j};
1082 data[i] = {left: size.left - outer.left, right: right - outer.left, top: vCat};
1055 }
1083 }
1056 for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1084 for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1057 var vr = cur.top;
1085 var vr = cur.top, vrRight = cur.topRight;
1058 cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
1086 cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
1059 }
1087 if (vrRight != null) { cur.topRight = vranges[vrRight]; cur.bottomRight = vranges[vrRight+1]; }
1060
1088 }
1061 return data;
1089 return data;
1062 }
1090 }
1063
1091
@@ -1068,7 +1096,7 b' window.CodeMirror = (function() {'
1068 if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1096 if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1069 }
1097 }
1070 var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1098 var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1071 if (cached) return measureChar(cm, line, line.text.length, cached).right;
1099 if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
1072
1100
1073 var pre = lineContent(cm, line);
1101 var pre = lineContent(cm, line);
1074 var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1102 var end = pre.appendChild(zeroWidthElement(cm.display.measure));
@@ -1083,6 +1111,9 b' window.CodeMirror = (function() {'
1083 cm.display.lineNumChars = null;
1111 cm.display.lineNumChars = null;
1084 }
1112 }
1085
1113
1114 function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
1115 function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
1116
1086 // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1117 // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1087 function intoCoordSystem(cm, lineObj, rect, context) {
1118 function intoCoordSystem(cm, lineObj, rect, context) {
1088 if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
1119 if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
@@ -1092,11 +1123,12 b' window.CodeMirror = (function() {'
1092 if (context == "line") return rect;
1123 if (context == "line") return rect;
1093 if (!context) context = "local";
1124 if (!context) context = "local";
1094 var yOff = heightAtLine(cm, lineObj);
1125 var yOff = heightAtLine(cm, lineObj);
1095 if (context != "local") yOff -= cm.display.viewOffset;
1126 if (context == "local") yOff += paddingTop(cm.display);
1096 if (context == "page") {
1127 else yOff -= cm.display.viewOffset;
1128 if (context == "page" || context == "window") {
1097 var lOff = getRect(cm.display.lineSpace);
1129 var lOff = getRect(cm.display.lineSpace);
1098 yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop);
1130 yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
1099 var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft);
1131 var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
1100 rect.left += xOff; rect.right += xOff;
1132 rect.left += xOff; rect.right += xOff;
1101 }
1133 }
1102 rect.top += yOff; rect.bottom += yOff;
1134 rect.top += yOff; rect.bottom += yOff;
@@ -1108,64 +1140,58 b' window.CodeMirror = (function() {'
1108 function fromCoordSystem(cm, coords, context) {
1140 function fromCoordSystem(cm, coords, context) {
1109 if (context == "div") return coords;
1141 if (context == "div") return coords;
1110 var left = coords.left, top = coords.top;
1142 var left = coords.left, top = coords.top;
1143 // First move into "page" coordinate system
1111 if (context == "page") {
1144 if (context == "page") {
1112 left -= window.pageXOffset || (document.documentElement || document.body).scrollLeft;
1145 left -= pageScrollX();
1113 top -= window.pageYOffset || (document.documentElement || document.body).scrollTop;
1146 top -= pageScrollY();
1114 }
1147 } else if (context == "local" || !context) {
1148 var localBox = getRect(cm.display.sizer);
1149 left += localBox.left;
1150 top += localBox.top;
1151 }
1152
1115 var lineSpaceBox = getRect(cm.display.lineSpace);
1153 var lineSpaceBox = getRect(cm.display.lineSpace);
1116 left -= lineSpaceBox.left;
1154 return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1117 top -= lineSpaceBox.top;
1155 }
1118 if (context == "local" || !context) {
1156
1119 var editorBox = getRect(cm.display.wrapper);
1157 function charCoords(cm, pos, context, lineObj, bias) {
1120 left += editorBox.left;
1121 top += editorBox.top;
1122 }
1123 return {left: left, top: top};
1124 }
1125
1126 function charCoords(cm, pos, context, lineObj) {
1127 if (!lineObj) lineObj = getLine(cm.doc, pos.line);
1158 if (!lineObj) lineObj = getLine(cm.doc, pos.line);
1128 return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), context);
1159 return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
1129 }
1160 }
1130
1161
1131 function cursorCoords(cm, pos, context, lineObj, measurement) {
1162 function cursorCoords(cm, pos, context, lineObj, measurement) {
1132 lineObj = lineObj || getLine(cm.doc, pos.line);
1163 lineObj = lineObj || getLine(cm.doc, pos.line);
1133 if (!measurement) measurement = measureLine(cm, lineObj);
1164 if (!measurement) measurement = measureLine(cm, lineObj);
1134 function get(ch, right) {
1165 function get(ch, right) {
1135 var m = measureChar(cm, lineObj, ch, measurement);
1166 var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
1136 if (right) m.left = m.right; else m.right = m.left;
1167 if (right) m.left = m.right; else m.right = m.left;
1137 return intoCoordSystem(cm, lineObj, m, context);
1168 return intoCoordSystem(cm, lineObj, m, context);
1138 }
1169 }
1170 function getBidi(ch, partPos) {
1171 var part = order[partPos], right = part.level % 2;
1172 if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
1173 part = order[--partPos];
1174 ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
1175 right = true;
1176 } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
1177 part = order[++partPos];
1178 ch = bidiLeft(part) - part.level % 2;
1179 right = false;
1180 }
1181 if (right && ch == part.to && ch > part.from) return get(ch - 1);
1182 return get(ch, right);
1183 }
1139 var order = getOrder(lineObj), ch = pos.ch;
1184 var order = getOrder(lineObj), ch = pos.ch;
1140 if (!order) return get(ch);
1185 if (!order) return get(ch);
1141 var main, other, linedir = order[0].level;
1186 var partPos = getBidiPartAt(order, ch);
1142 for (var i = 0; i < order.length; ++i) {
1187 var val = getBidi(ch, partPos);
1143 var part = order[i], rtl = part.level % 2, nb, here;
1188 if (bidiOther != null) val.other = getBidi(ch, bidiOther);
1144 if (part.from < ch && part.to > ch) return get(ch, rtl);
1189 return val;
1145 var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to;
1190 }
1146 if (left == ch) {
1191
1147 // IE returns bogus offsets and widths for edges where the
1192 function PosWithInfo(line, ch, outside, xRel) {
1148 // direction flips, but only for the side with the lower
1149 // level. So we try to use the side with the higher level.
1150 if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true);
1151 else here = get(rtl && part.from != part.to ? ch - 1 : ch);
1152 if (rtl == linedir) main = here; else other = here;
1153 } else if (right == ch) {
1154 var nb = i < order.length - 1 && order[i+1];
1155 if (!rtl && nb && nb.from == nb.to) continue;
1156 if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from);
1157 else here = get(rtl ? ch : ch - 1, true);
1158 if (rtl == linedir) main = here; else other = here;
1159 }
1160 }
1161 if (linedir && !ch) other = get(order[0].to - 1);
1162 if (!main) return other;
1163 if (other) main.other = other;
1164 return main;
1165 }
1166
1167 function PosMaybeOutside(line, ch, outside) {
1168 var pos = new Pos(line, ch);
1193 var pos = new Pos(line, ch);
1194 pos.xRel = xRel;
1169 if (outside) pos.outside = true;
1195 if (outside) pos.outside = true;
1170 return pos;
1196 return pos;
1171 }
1197 }
@@ -1174,10 +1200,10 b' window.CodeMirror = (function() {'
1174 function coordsChar(cm, x, y) {
1200 function coordsChar(cm, x, y) {
1175 var doc = cm.doc;
1201 var doc = cm.doc;
1176 y += cm.display.viewOffset;
1202 y += cm.display.viewOffset;
1177 if (y < 0) return PosMaybeOutside(doc.first, 0, true);
1203 if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
1178 var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1204 var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1179 if (lineNo > last)
1205 if (lineNo > last)
1180 return PosMaybeOutside(doc.first + doc.size - 1, getLine(doc, last).text.length, true);
1206 return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
1181 if (x < 0) x = 0;
1207 if (x < 0) x = 0;
1182
1208
1183 for (;;) {
1209 for (;;) {
@@ -1185,7 +1211,7 b' window.CodeMirror = (function() {'
1185 var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1211 var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1186 var merged = collapsedSpanAtEnd(lineObj);
1212 var merged = collapsedSpanAtEnd(lineObj);
1187 var mergedPos = merged && merged.find();
1213 var mergedPos = merged && merged.find();
1188 if (merged && found.ch >= mergedPos.from.ch)
1214 if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
1189 lineNo = mergedPos.to.line;
1215 lineNo = mergedPos.to.line;
1190 else
1216 else
1191 return found;
1217 return found;
@@ -1211,14 +1237,15 b' window.CodeMirror = (function() {'
1211 var from = lineLeft(lineObj), to = lineRight(lineObj);
1237 var from = lineLeft(lineObj), to = lineRight(lineObj);
1212 var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1238 var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1213
1239
1214 if (x > toX) return PosMaybeOutside(lineNo, to, toOutside);
1240 if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
1215 // Do a binary search between these bounds.
1241 // Do a binary search between these bounds.
1216 for (;;) {
1242 for (;;) {
1217 if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1243 if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1218 var after = x - fromX < toX - x, ch = after ? from : to;
1244 var ch = x < fromX || x - fromX <= toX - x ? from : to;
1245 var xDiff = x - (ch == from ? fromX : toX);
1219 while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1246 while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1220 var pos = PosMaybeOutside(lineNo, ch, after ? fromOutside : toOutside);
1247 var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1221 pos.after = after;
1248 xDiff < 0 ? -1 : xDiff ? 1 : 0);
1222 return pos;
1249 return pos;
1223 }
1250 }
1224 var step = Math.ceil(dist / 2), middle = from + step;
1251 var step = Math.ceil(dist / 2), middle = from + step;
@@ -1404,7 +1431,7 b' window.CodeMirror = (function() {'
1404 // supported or compatible enough yet to rely on.)
1431 // supported or compatible enough yet to rely on.)
1405 function readInput(cm) {
1432 function readInput(cm) {
1406 var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1433 var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1407 if (!cm.state.focused || hasSelection(input) || isReadOnly(cm)) return false;
1434 if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1408 var text = input.value;
1435 var text = input.value;
1409 if (text == prevInput && posEq(sel.from, sel.to)) return false;
1436 if (text == prevInput && posEq(sel.from, sel.to)) return false;
1410 if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
1437 if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
@@ -1422,11 +1449,14 b' window.CodeMirror = (function() {'
1422 from = Pos(from.line, from.ch - (prevInput.length - same));
1449 from = Pos(from.line, from.ch - (prevInput.length - same));
1423 else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1450 else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1424 to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1451 to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1452
1425 var updateInput = cm.curOp.updateInput;
1453 var updateInput = cm.curOp.updateInput;
1426 makeChange(cm.doc, {from: from, to: to, text: splitLines(text.slice(same)),
1454 var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1427 origin: cm.state.pasteIncoming ? "paste" : "+input"}, "end");
1455 origin: cm.state.pasteIncoming ? "paste" : "+input"};
1428
1456 makeChange(cm.doc, changeEvent, "end");
1429 cm.curOp.updateInput = updateInput;
1457 cm.curOp.updateInput = updateInput;
1458 signalLater(cm, "inputRead", cm, changeEvent);
1459
1430 if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1460 if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1431 else cm.display.prevInput = text;
1461 else cm.display.prevInput = text;
1432 if (withOp) endOperation(cm);
1462 if (withOp) endOperation(cm);
@@ -1467,6 +1497,7 b' window.CodeMirror = (function() {'
1467 on(d.scroller, "mousedown", operation(cm, onMouseDown));
1497 on(d.scroller, "mousedown", operation(cm, onMouseDown));
1468 if (ie)
1498 if (ie)
1469 on(d.scroller, "dblclick", operation(cm, function(e) {
1499 on(d.scroller, "dblclick", operation(cm, function(e) {
1500 if (signalDOMEvent(cm, e)) return;
1470 var pos = posFromMouse(cm, e);
1501 var pos = posFromMouse(cm, e);
1471 if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1502 if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1472 e_preventDefault(e);
1503 e_preventDefault(e);
@@ -1474,7 +1505,7 b' window.CodeMirror = (function() {'
1474 extendSelection(cm.doc, word.from, word.to);
1505 extendSelection(cm.doc, word.from, word.to);
1475 }));
1506 }));
1476 else
1507 else
1477 on(d.scroller, "dblclick", e_preventDefault);
1508 on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
1478 on(d.lineSpace, "selectstart", function(e) {
1509 on(d.lineSpace, "selectstart", function(e) {
1479 if (!eventInWidget(d, e)) e_preventDefault(e);
1510 if (!eventInWidget(d, e)) e_preventDefault(e);
1480 });
1511 });
@@ -1506,11 +1537,15 b' window.CodeMirror = (function() {'
1506 // Prevent wrapper from ever scrolling
1537 // Prevent wrapper from ever scrolling
1507 on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1538 on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1508
1539
1540 var resizeTimer;
1509 function onResize() {
1541 function onResize() {
1510 // Might be a text scaling operation, clear size caches.
1542 if (resizeTimer == null) resizeTimer = setTimeout(function() {
1511 d.cachedCharWidth = d.cachedTextHeight = null;
1543 resizeTimer = null;
1512 clearCaches(cm);
1544 // Might be a text scaling operation, clear size caches.
1513 runInOp(cm, bind(regChange, cm));
1545 d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
1546 clearCaches(cm);
1547 runInOp(cm, bind(regChange, cm));
1548 }, 100);
1514 }
1549 }
1515 on(window, "resize", onResize);
1550 on(window, "resize", onResize);
1516 // Above handler holds on to the editor and its data structures.
1551 // Above handler holds on to the editor and its data structures.
@@ -1524,7 +1559,7 b' window.CodeMirror = (function() {'
1524 setTimeout(unregister, 5000);
1559 setTimeout(unregister, 5000);
1525
1560
1526 on(d.input, "keyup", operation(cm, function(e) {
1561 on(d.input, "keyup", operation(cm, function(e) {
1527 if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1562 if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1528 if (e.keyCode == 16) cm.doc.sel.shift = false;
1563 if (e.keyCode == 16) cm.doc.sel.shift = false;
1529 }));
1564 }));
1530 on(d.input, "input", bind(fastPoll, cm));
1565 on(d.input, "input", bind(fastPoll, cm));
@@ -1534,7 +1569,7 b' window.CodeMirror = (function() {'
1534 on(d.input, "blur", bind(onBlur, cm));
1569 on(d.input, "blur", bind(onBlur, cm));
1535
1570
1536 function drag_(e) {
1571 function drag_(e) {
1537 if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
1572 if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
1538 e_stop(e);
1573 e_stop(e);
1539 }
1574 }
1540 if (cm.options.dragDrop) {
1575 if (cm.options.dragDrop) {
@@ -1573,9 +1608,7 b' window.CodeMirror = (function() {'
1573
1608
1574 function eventInWidget(display, e) {
1609 function eventInWidget(display, e) {
1575 for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1610 for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1576 if (!n) return true;
1611 if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1577 if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) ||
1578 n.parentNode == display.sizer && n != display.mover) return true;
1579 }
1612 }
1580 }
1613 }
1581
1614
@@ -1585,7 +1618,7 b' window.CodeMirror = (function() {'
1585 var target = e_target(e);
1618 var target = e_target(e);
1586 if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1619 if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1587 target == display.scrollbarV || target == display.scrollbarV.firstChild ||
1620 target == display.scrollbarV || target == display.scrollbarV.firstChild ||
1588 target == display.scrollbarFiller) return null;
1621 target == display.scrollbarFiller || target == display.gutterFiller) return null;
1589 }
1622 }
1590 var x, y, space = getRect(display.lineSpace);
1623 var x, y, space = getRect(display.lineSpace);
1591 // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1624 // Fails unpredictably on IE[67] when mouse is dragged around quickly.
@@ -1595,6 +1628,7 b' window.CodeMirror = (function() {'
1595
1628
1596 var lastClick, lastDoubleClick;
1629 var lastClick, lastDoubleClick;
1597 function onMouseDown(e) {
1630 function onMouseDown(e) {
1631 if (signalDOMEvent(this, e)) return;
1598 var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1632 var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1599 sel.shift = e.shiftKey;
1633 sel.shift = e.shiftKey;
1600
1634
@@ -1718,8 +1752,6 b' window.CodeMirror = (function() {'
1718
1752
1719 function done(e) {
1753 function done(e) {
1720 counter = Infinity;
1754 counter = Infinity;
1721 var cur = posFromMouse(cm, e);
1722 if (cur) doSelect(cur);
1723 e_preventDefault(e);
1755 e_preventDefault(e);
1724 focusInput(cm);
1756 focusInput(cm);
1725 off(document, "mousemove", move);
1757 off(document, "mousemove", move);
@@ -1735,11 +1767,41 b' window.CodeMirror = (function() {'
1735 on(document, "mouseup", up);
1767 on(document, "mouseup", up);
1736 }
1768 }
1737
1769
1770 function clickInGutter(cm, e) {
1771 var display = cm.display;
1772 try { var mX = e.clientX, mY = e.clientY; }
1773 catch(e) { return false; }
1774
1775 if (mX >= Math.floor(getRect(display.gutters).right)) return false;
1776 e_preventDefault(e);
1777 if (!hasHandler(cm, "gutterClick")) return true;
1778
1779 var lineBox = getRect(display.lineDiv);
1780 if (mY > lineBox.bottom) return true;
1781 mY -= lineBox.top - display.viewOffset;
1782
1783 for (var i = 0; i < cm.options.gutters.length; ++i) {
1784 var g = display.gutters.childNodes[i];
1785 if (g && getRect(g).right >= mX) {
1786 var line = lineAtHeight(cm.doc, mY);
1787 var gutter = cm.options.gutters[i];
1788 signalLater(cm, "gutterClick", cm, line, gutter, e);
1789 break;
1790 }
1791 }
1792 return true;
1793 }
1794
1795 // Kludge to work around strange IE behavior where it'll sometimes
1796 // re-fire a series of drag-related events right after the drop (#1551)
1797 var lastDrop = 0;
1798
1738 function onDrop(e) {
1799 function onDrop(e) {
1739 var cm = this;
1800 var cm = this;
1740 if (eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1801 if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1741 return;
1802 return;
1742 e_preventDefault(e);
1803 e_preventDefault(e);
1804 if (ie) lastDrop = +new Date;
1743 var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1805 var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1744 if (!pos || isReadOnly(cm)) return;
1806 if (!pos || isReadOnly(cm)) return;
1745 if (files && files.length && window.FileReader && window.File) {
1807 if (files && files.length && window.FileReader && window.File) {
@@ -1779,41 +1841,16 b' window.CodeMirror = (function() {'
1779 }
1841 }
1780 }
1842 }
1781
1843
1782 function clickInGutter(cm, e) {
1783 var display = cm.display;
1784 try { var mX = e.clientX, mY = e.clientY; }
1785 catch(e) { return false; }
1786
1787 if (mX >= Math.floor(getRect(display.gutters).right)) return false;
1788 e_preventDefault(e);
1789 if (!hasHandler(cm, "gutterClick")) return true;
1790
1791 var lineBox = getRect(display.lineDiv);
1792 if (mY > lineBox.bottom) return true;
1793 mY -= lineBox.top - display.viewOffset;
1794
1795 for (var i = 0; i < cm.options.gutters.length; ++i) {
1796 var g = display.gutters.childNodes[i];
1797 if (g && getRect(g).right >= mX) {
1798 var line = lineAtHeight(cm.doc, mY);
1799 var gutter = cm.options.gutters[i];
1800 signalLater(cm, "gutterClick", cm, line, gutter, e);
1801 break;
1802 }
1803 }
1804 return true;
1805 }
1806
1807 function onDragStart(cm, e) {
1844 function onDragStart(cm, e) {
1808 if (ie && !cm.state.draggingText) { e_stop(e); return; }
1845 if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1809 if (eventInWidget(cm.display, e)) return;
1846 if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1810
1847
1811 var txt = cm.getSelection();
1848 var txt = cm.getSelection();
1812 e.dataTransfer.setData("Text", txt);
1849 e.dataTransfer.setData("Text", txt);
1813
1850
1814 // Use dummy image instead of default browsers image.
1851 // Use dummy image instead of default browsers image.
1815 // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
1852 // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
1816 if (e.dataTransfer.setDragImage) {
1853 if (e.dataTransfer.setDragImage && !safari) {
1817 var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1854 var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1818 if (opera) {
1855 if (opera) {
1819 img.width = img.height = 1;
1856 img.width = img.height = 1;
@@ -1821,15 +1858,6 b' window.CodeMirror = (function() {'
1821 // Force a relayout, or Opera won't use our image for some obscure reason
1858 // Force a relayout, or Opera won't use our image for some obscure reason
1822 img._top = img.offsetTop;
1859 img._top = img.offsetTop;
1823 }
1860 }
1824 if (safari) {
1825 if (cm.display.dragImg) {
1826 img = cm.display.dragImg;
1827 } else {
1828 cm.display.dragImg = img;
1829 img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
1830 cm.display.wrapper.appendChild(img);
1831 }
1832 }
1833 e.dataTransfer.setDragImage(img, 0, 0);
1861 e.dataTransfer.setDragImage(img, 0, 0);
1834 if (opera) img.parentNode.removeChild(img);
1862 if (opera) img.parentNode.removeChild(img);
1835 }
1863 }
@@ -1842,6 +1870,7 b' window.CodeMirror = (function() {'
1842 if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1870 if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1843 if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1871 if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1844 if (gecko) updateDisplay(cm, []);
1872 if (gecko) updateDisplay(cm, []);
1873 startWorker(cm, 100);
1845 }
1874 }
1846 function setScrollLeft(cm, val, isScroller) {
1875 function setScrollLeft(cm, val, isScroller) {
1847 if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
1876 if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
@@ -1974,8 +2003,10 b' window.CodeMirror = (function() {'
1974 var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
2003 var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
1975 clearTimeout(maybeTransition);
2004 clearTimeout(maybeTransition);
1976 if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
2005 if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
1977 if (getKeyMap(cm.options.keyMap) == startMap)
2006 if (getKeyMap(cm.options.keyMap) == startMap) {
1978 cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2007 cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2008 keyMapChanged(cm);
2009 }
1979 }, 50);
2010 }, 50);
1980
2011
1981 var name = keyName(e, true), handled = false;
2012 var name = keyName(e, true), handled = false;
@@ -1988,17 +2019,18 b' window.CodeMirror = (function() {'
1988 // 'go') bound to the keyname without 'Shift-'.
2019 // 'go') bound to the keyname without 'Shift-'.
1989 handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
2020 handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
1990 || lookupKey(name, keymaps, function(b) {
2021 || lookupKey(name, keymaps, function(b) {
1991 if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(cm, b);
2022 if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
2023 return doHandleBinding(cm, b);
1992 });
2024 });
1993 } else {
2025 } else {
1994 handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
2026 handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
1995 }
2027 }
1996 if (handled == "stop") handled = false;
1997
2028
1998 if (handled) {
2029 if (handled) {
1999 e_preventDefault(e);
2030 e_preventDefault(e);
2000 restartBlink(cm);
2031 restartBlink(cm);
2001 if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2032 if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2033 signalLater(cm, "keyHandled", cm, name, e);
2002 }
2034 }
2003 return handled;
2035 return handled;
2004 }
2036 }
@@ -2009,6 +2041,7 b' window.CodeMirror = (function() {'
2009 if (handled) {
2041 if (handled) {
2010 e_preventDefault(e);
2042 e_preventDefault(e);
2011 restartBlink(cm);
2043 restartBlink(cm);
2044 signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
2012 }
2045 }
2013 return handled;
2046 return handled;
2014 }
2047 }
@@ -2018,7 +2051,7 b' window.CodeMirror = (function() {'
2018 var cm = this;
2051 var cm = this;
2019 if (!cm.state.focused) onFocus(cm);
2052 if (!cm.state.focused) onFocus(cm);
2020 if (ie && e.keyCode == 27) { e.returnValue = false; }
2053 if (ie && e.keyCode == 27) { e.returnValue = false; }
2021 if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2054 if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2022 var code = e.keyCode;
2055 var code = e.keyCode;
2023 // IE does strange things with escape.
2056 // IE does strange things with escape.
2024 cm.doc.sel.shift = code == 16 || e.shiftKey;
2057 cm.doc.sel.shift = code == 16 || e.shiftKey;
@@ -2034,7 +2067,7 b' window.CodeMirror = (function() {'
2034
2067
2035 function onKeyPress(e) {
2068 function onKeyPress(e) {
2036 var cm = this;
2069 var cm = this;
2037 if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2070 if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2038 var keyCode = e.keyCode, charCode = e.charCode;
2071 var keyCode = e.keyCode, charCode = e.charCode;
2039 if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2072 if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2040 if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
2073 if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
@@ -2090,6 +2123,13 b' window.CodeMirror = (function() {'
2090 // Adds "Select all" to context menu in FF
2123 // Adds "Select all" to context menu in FF
2091 if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
2124 if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
2092
2125
2126 function prepareSelectAllHack() {
2127 if (display.input.selectionStart != null) {
2128 var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
2129 display.prevInput = " ";
2130 display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2131 }
2132 }
2093 function rehide() {
2133 function rehide() {
2094 display.inputDiv.style.position = "relative";
2134 display.inputDiv.style.position = "relative";
2095 display.input.style.cssText = oldCSS;
2135 display.input.style.cssText = oldCSS;
@@ -2097,12 +2137,10 b' window.CodeMirror = (function() {'
2097 slowPoll(cm);
2137 slowPoll(cm);
2098
2138
2099 // Try to detect the user choosing select-all
2139 // Try to detect the user choosing select-all
2100 if (display.input.selectionStart != null && (!ie || ie_lt9)) {
2140 if (display.input.selectionStart != null) {
2141 if (!ie || ie_lt9) prepareSelectAllHack();
2101 clearTimeout(detectingSelectAll);
2142 clearTimeout(detectingSelectAll);
2102 var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0;
2143 var i = 0, poll = function(){
2103 display.prevInput = " ";
2104 display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2105 var poll = function(){
2106 if (display.prevInput == " " && display.input.selectionStart == 0)
2144 if (display.prevInput == " " && display.input.selectionStart == 0)
2107 operation(cm, commands.selectAll)(cm);
2145 operation(cm, commands.selectAll)(cm);
2108 else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
2146 else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
@@ -2112,6 +2150,7 b' window.CodeMirror = (function() {'
2112 }
2150 }
2113 }
2151 }
2114
2152
2153 if (ie && !ie_lt9) prepareSelectAllHack();
2115 if (captureMiddleClick) {
2154 if (captureMiddleClick) {
2116 e_stop(e);
2155 e_stop(e);
2117 var mouseup = function() {
2156 var mouseup = function() {
@@ -2126,11 +2165,11 b' window.CodeMirror = (function() {'
2126
2165
2127 // UPDATING
2166 // UPDATING
2128
2167
2129 function changeEnd(change) {
2168 var changeEnd = CodeMirror.changeEnd = function(change) {
2130 if (!change.text) return change.to;
2169 if (!change.text) return change.to;
2131 return Pos(change.from.line + change.text.length - 1,
2170 return Pos(change.from.line + change.text.length - 1,
2132 lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2171 lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2133 }
2172 };
2134
2173
2135 // Make sure a position will be valid after the given change.
2174 // Make sure a position will be valid after the given change.
2136 function clipPostChange(doc, change, pos) {
2175 function clipPostChange(doc, change, pos) {
@@ -2172,21 +2211,21 b' window.CodeMirror = (function() {'
2172 return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2211 return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2173 }
2212 }
2174
2213
2175 function filterChange(doc, change) {
2214 function filterChange(doc, change, update) {
2176 var obj = {
2215 var obj = {
2177 canceled: false,
2216 canceled: false,
2178 from: change.from,
2217 from: change.from,
2179 to: change.to,
2218 to: change.to,
2180 text: change.text,
2219 text: change.text,
2181 origin: change.origin,
2220 origin: change.origin,
2182 update: function(from, to, text, origin) {
2183 if (from) this.from = clipPos(doc, from);
2184 if (to) this.to = clipPos(doc, to);
2185 if (text) this.text = text;
2186 if (origin !== undefined) this.origin = origin;
2187 },
2188 cancel: function() { this.canceled = true; }
2221 cancel: function() { this.canceled = true; }
2189 };
2222 };
2223 if (update) obj.update = function(from, to, text, origin) {
2224 if (from) this.from = clipPos(doc, from);
2225 if (to) this.to = clipPos(doc, to);
2226 if (text) this.text = text;
2227 if (origin !== undefined) this.origin = origin;
2228 };
2190 signal(doc, "beforeChange", doc, obj);
2229 signal(doc, "beforeChange", doc, obj);
2191 if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2230 if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2192
2231
@@ -2203,7 +2242,7 b' window.CodeMirror = (function() {'
2203 }
2242 }
2204
2243
2205 if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2244 if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2206 change = filterChange(doc, change);
2245 change = filterChange(doc, change, true);
2207 if (!change) return;
2246 if (!change) return;
2208 }
2247 }
2209
2248
@@ -2242,15 +2281,23 b' window.CodeMirror = (function() {'
2242 var hist = doc.history;
2281 var hist = doc.history;
2243 var event = (type == "undo" ? hist.done : hist.undone).pop();
2282 var event = (type == "undo" ? hist.done : hist.undone).pop();
2244 if (!event) return;
2283 if (!event) return;
2245 hist.dirtyCounter += type == "undo" ? -1 : 1;
2246
2284
2247 var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
2285 var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
2248 anchorAfter: event.anchorBefore, headAfter: event.headBefore};
2286 anchorAfter: event.anchorBefore, headAfter: event.headBefore,
2287 generation: hist.generation};
2249 (type == "undo" ? hist.undone : hist.done).push(anti);
2288 (type == "undo" ? hist.undone : hist.done).push(anti);
2289 hist.generation = event.generation || ++hist.maxGeneration;
2290
2291 var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
2250
2292
2251 for (var i = event.changes.length - 1; i >= 0; --i) {
2293 for (var i = event.changes.length - 1; i >= 0; --i) {
2252 var change = event.changes[i];
2294 var change = event.changes[i];
2253 change.origin = type;
2295 change.origin = type;
2296 if (filter && !filterChange(doc, change, false)) {
2297 (type == "undo" ? hist.done : hist.undone).length = 0;
2298 return;
2299 }
2300
2254 anti.changes.push(historyChangeFromChange(doc, change));
2301 anti.changes.push(historyChangeFromChange(doc, change));
2255
2302
2256 var after = i ? computeSelAfterChange(doc, change, null)
2303 var after = i ? computeSelAfterChange(doc, change, null)
@@ -2512,11 +2559,11 b' window.CodeMirror = (function() {'
2512 // SCROLLING
2559 // SCROLLING
2513
2560
2514 function scrollCursorIntoView(cm) {
2561 function scrollCursorIntoView(cm) {
2515 var coords = scrollPosIntoView(cm, cm.doc.sel.head);
2562 var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
2516 if (!cm.state.focused) return;
2563 if (!cm.state.focused) return;
2517 var display = cm.display, box = getRect(display.sizer), doScroll = null, pTop = paddingTop(cm.display);
2564 var display = cm.display, box = getRect(display.sizer), doScroll = null;
2518 if (coords.top + pTop + box.top < 0) doScroll = true;
2565 if (coords.top + box.top < 0) doScroll = true;
2519 else if (coords.bottom + pTop + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2566 else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2520 if (doScroll != null && !phantom) {
2567 if (doScroll != null && !phantom) {
2521 var hidden = display.cursor.style.display == "none";
2568 var hidden = display.cursor.style.display == "none";
2522 if (hidden) {
2569 if (hidden) {
@@ -2554,12 +2601,11 b' window.CodeMirror = (function() {'
2554 }
2601 }
2555
2602
2556 function calculateScrollPos(cm, x1, y1, x2, y2) {
2603 function calculateScrollPos(cm, x1, y1, x2, y2) {
2557 var display = cm.display, pt = paddingTop(display);
2604 var display = cm.display, snapMargin = textHeight(cm.display);
2558 y1 += pt; y2 += pt;
2559 if (y1 < 0) y1 = 0;
2605 if (y1 < 0) y1 = 0;
2560 var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2606 var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2561 var docBottom = cm.doc.height + paddingVert(display);
2607 var docBottom = cm.doc.height + paddingVert(display);
2562 var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
2608 var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
2563 if (y1 < screentop) {
2609 if (y1 < screentop) {
2564 result.scrollTop = atTop ? 0 : y1;
2610 result.scrollTop = atTop ? 0 : y1;
2565 } else if (y2 > screentop + screen) {
2611 } else if (y2 > screentop + screen) {
@@ -2596,7 +2642,7 b' window.CodeMirror = (function() {'
2596
2642
2597 function indentLine(cm, n, how, aggressive) {
2643 function indentLine(cm, n, how, aggressive) {
2598 var doc = cm.doc;
2644 var doc = cm.doc;
2599 if (!how) how = "add";
2645 if (how == null) how = "add";
2600 if (how == "smart") {
2646 if (how == "smart") {
2601 if (!cm.doc.mode.indent) how = "prev";
2647 if (!cm.doc.mode.indent) how = "prev";
2602 else var state = getStateBefore(cm, n);
2648 else var state = getStateBefore(cm, n);
@@ -2619,6 +2665,8 b' window.CodeMirror = (function() {'
2619 indentation = curSpace + cm.options.indentUnit;
2665 indentation = curSpace + cm.options.indentUnit;
2620 } else if (how == "subtract") {
2666 } else if (how == "subtract") {
2621 indentation = curSpace - cm.options.indentUnit;
2667 indentation = curSpace - cm.options.indentUnit;
2668 } else if (typeof how == "number") {
2669 indentation = curSpace + how;
2622 }
2670 }
2623 indentation = Math.max(0, indentation);
2671 indentation = Math.max(0, indentation);
2624
2672
@@ -2643,7 +2691,7 b' window.CodeMirror = (function() {'
2643 }
2691 }
2644
2692
2645 function findPosH(doc, pos, dir, unit, visually) {
2693 function findPosH(doc, pos, dir, unit, visually) {
2646 var line = pos.line, ch = pos.ch;
2694 var line = pos.line, ch = pos.ch, origDir = dir;
2647 var lineObj = getLine(doc, line);
2695 var lineObj = getLine(doc, line);
2648 var possible = true;
2696 var possible = true;
2649 function findNextLine() {
2697 function findNextLine() {
@@ -2682,7 +2730,7 b' window.CodeMirror = (function() {'
2682 if (dir > 0 && !moveOnce(!first)) break;
2730 if (dir > 0 && !moveOnce(!first)) break;
2683 }
2731 }
2684 }
2732 }
2685 var result = skipAtomic(doc, Pos(line, ch), dir, true);
2733 var result = skipAtomic(doc, Pos(line, ch), origDir, true);
2686 if (!possible) result.hitSide = true;
2734 if (!possible) result.hitSide = true;
2687 return result;
2735 return result;
2688 }
2736 }
@@ -2707,7 +2755,7 b' window.CodeMirror = (function() {'
2707 function findWordAt(line, pos) {
2755 function findWordAt(line, pos) {
2708 var start = pos.ch, end = pos.ch;
2756 var start = pos.ch, end = pos.ch;
2709 if (line) {
2757 if (line) {
2710 if (pos.after === false || end == line.length) --start; else ++end;
2758 if (pos.xRel < 0 || end == line.length) --start; else ++end;
2711 var startChar = line.charAt(start);
2759 var startChar = line.charAt(start);
2712 var check = isWordChar(startChar) ? isWordChar
2760 var check = isWordChar(startChar) ? isWordChar
2713 : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
2761 : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
@@ -2728,6 +2776,7 b' window.CodeMirror = (function() {'
2728 // 'wrap f in an operation, performed on its `this` parameter'
2776 // 'wrap f in an operation, performed on its `this` parameter'
2729
2777
2730 CodeMirror.prototype = {
2778 CodeMirror.prototype = {
2779 constructor: CodeMirror,
2731 focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2780 focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2732
2781
2733 setOption: function(option, value) {
2782 setOption: function(option, value) {
@@ -2763,7 +2812,8 b' window.CodeMirror = (function() {'
2763 removeOverlay: operation(null, function(spec) {
2812 removeOverlay: operation(null, function(spec) {
2764 var overlays = this.state.overlays;
2813 var overlays = this.state.overlays;
2765 for (var i = 0; i < overlays.length; ++i) {
2814 for (var i = 0; i < overlays.length; ++i) {
2766 if (overlays[i].modeSpec == spec) {
2815 var cur = overlays[i].modeSpec;
2816 if (cur == spec || typeof spec == "string" && cur.name == spec) {
2767 overlays.splice(i, 1);
2817 overlays.splice(i, 1);
2768 this.state.modeGen++;
2818 this.state.modeGen++;
2769 regChange(this);
2819 regChange(this);
@@ -2773,7 +2823,7 b' window.CodeMirror = (function() {'
2773 }),
2823 }),
2774
2824
2775 indentLine: operation(null, function(n, dir, aggressive) {
2825 indentLine: operation(null, function(n, dir, aggressive) {
2776 if (typeof dir != "string") {
2826 if (typeof dir != "string" && typeof dir != "number") {
2777 if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2827 if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2778 else dir = dir ? "add" : "subtract";
2828 else dir = dir ? "add" : "subtract";
2779 }
2829 }
@@ -2788,10 +2838,10 b' window.CodeMirror = (function() {'
2788
2838
2789 // Fetch the parser token for a given character. Useful for hacks
2839 // Fetch the parser token for a given character. Useful for hacks
2790 // that want to inspect the mode state (say, for completion).
2840 // that want to inspect the mode state (say, for completion).
2791 getTokenAt: function(pos) {
2841 getTokenAt: function(pos, precise) {
2792 var doc = this.doc;
2842 var doc = this.doc;
2793 pos = clipPos(doc, pos);
2843 pos = clipPos(doc, pos);
2794 var state = getStateBefore(this, pos.line), mode = this.doc.mode;
2844 var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
2795 var line = getLine(doc, pos.line);
2845 var line = getLine(doc, pos.line);
2796 var stream = new StringStream(line.text, this.options.tabSize);
2846 var stream = new StringStream(line.text, this.options.tabSize);
2797 while (stream.pos < pos.ch && !stream.eol()) {
2847 while (stream.pos < pos.ch && !stream.eol()) {
@@ -2806,10 +2856,22 b' window.CodeMirror = (function() {'
2806 state: state};
2856 state: state};
2807 },
2857 },
2808
2858
2809 getStateAfter: function(line) {
2859 getTokenTypeAt: function(pos) {
2860 pos = clipPos(this.doc, pos);
2861 var styles = getLineStyles(this, getLine(this.doc, pos.line));
2862 var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2863 for (;;) {
2864 var mid = (before + after) >> 1;
2865 if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
2866 else if (styles[mid * 2 + 1] < ch) before = mid + 1;
2867 else return styles[mid * 2 + 2];
2868 }
2869 },
2870
2871 getStateAfter: function(line, precise) {
2810 var doc = this.doc;
2872 var doc = this.doc;
2811 line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2873 line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2812 return getStateBefore(this, line + 1);
2874 return getStateBefore(this, line + 1, precise);
2813 },
2875 },
2814
2876
2815 cursorCoords: function(start, mode) {
2877 cursorCoords: function(start, mode) {
@@ -2829,6 +2891,19 b' window.CodeMirror = (function() {'
2829 return coordsChar(this, coords.left, coords.top);
2891 return coordsChar(this, coords.left, coords.top);
2830 },
2892 },
2831
2893
2894 lineAtHeight: function(height, mode) {
2895 height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
2896 return lineAtHeight(this.doc, height + this.display.viewOffset);
2897 },
2898 heightAtLine: function(line, mode) {
2899 var end = false, last = this.doc.first + this.doc.size - 1;
2900 if (line < this.doc.first) line = this.doc.first;
2901 else if (line > last) { line = last; end = true; }
2902 var lineObj = getLine(this.doc, line);
2903 return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
2904 (end ? lineObj.height : 0);
2905 },
2906
2832 defaultTextHeight: function() { return textHeight(this.display); },
2907 defaultTextHeight: function() { return textHeight(this.display); },
2833 defaultCharWidth: function() { return charWidth(this.display); },
2908 defaultCharWidth: function() { return charWidth(this.display); },
2834
2909
@@ -2857,7 +2932,7 b' window.CodeMirror = (function() {'
2857 return changeLine(this, handle, function(line) {
2932 return changeLine(this, handle, function(line) {
2858 var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2933 var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2859 if (!line[prop]) line[prop] = cls;
2934 if (!line[prop]) line[prop] = cls;
2860 else if (new RegExp("\\b" + cls + "\\b").test(line[prop])) return false;
2935 else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
2861 else line[prop] += " " + cls;
2936 else line[prop] += " " + cls;
2862 return true;
2937 return true;
2863 });
2938 });
@@ -2870,9 +2945,10 b' window.CodeMirror = (function() {'
2870 if (!cur) return false;
2945 if (!cur) return false;
2871 else if (cls == null) line[prop] = null;
2946 else if (cls == null) line[prop] = null;
2872 else {
2947 else {
2873 var upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), "");
2948 var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
2874 if (upd == cur) return false;
2949 if (!found) return false;
2875 line[prop] = upd || null;
2950 var end = found.index + found[0].length;
2951 line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
2876 }
2952 }
2877 return true;
2953 return true;
2878 });
2954 });
@@ -2920,7 +2996,7 b' window.CodeMirror = (function() {'
2920 if (left + node.offsetWidth > hspace)
2996 if (left + node.offsetWidth > hspace)
2921 left = hspace - node.offsetWidth;
2997 left = hspace - node.offsetWidth;
2922 }
2998 }
2923 node.style.top = (top + paddingTop(display)) + "px";
2999 node.style.top = top + "px";
2924 node.style.left = node.style.right = "";
3000 node.style.left = node.style.right = "";
2925 if (horiz == "right") {
3001 if (horiz == "right") {
2926 left = display.sizer.clientWidth - node.offsetWidth;
3002 left = display.sizer.clientWidth - node.offsetWidth;
@@ -2988,7 +3064,8 b' window.CodeMirror = (function() {'
2988 sel.goalColumn = pos.left;
3064 sel.goalColumn = pos.left;
2989 }),
3065 }),
2990
3066
2991 toggleOverwrite: function() {
3067 toggleOverwrite: function(value) {
3068 if (value != null && value == this.state.overwrite) return;
2992 if (this.state.overwrite = !this.state.overwrite)
3069 if (this.state.overwrite = !this.state.overwrite)
2993 this.display.cursor.className += " CodeMirror-overwrite";
3070 this.display.cursor.className += " CodeMirror-overwrite";
2994 else
3071 else
@@ -3111,6 +3188,7 b' window.CodeMirror = (function() {'
3111 cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3188 cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3112 cm.refresh();
3189 cm.refresh();
3113 }, true);
3190 }, true);
3191 option("coverGutterNextToScrollbar", false, updateScrollbars, true);
3114 option("lineNumbers", false, function(cm) {
3192 option("lineNumbers", false, function(cm) {
3115 setGuttersForLineNumbers(cm.options);
3193 setGuttersForLineNumbers(cm.options);
3116 guttersChanged(cm);
3194 guttersChanged(cm);
@@ -3126,6 +3204,7 b' window.CodeMirror = (function() {'
3126 option("dragDrop", true);
3204 option("dragDrop", true);
3127
3205
3128 option("cursorBlinkRate", 530);
3206 option("cursorBlinkRate", 530);
3207 option("cursorScrollMargin", 0);
3129 option("cursorHeight", 1);
3208 option("cursorHeight", 1);
3130 option("workTime", 100);
3209 option("workTime", 100);
3131 option("workDelay", 100);
3210 option("workDelay", 100);
@@ -3163,10 +3242,15 b' window.CodeMirror = (function() {'
3163 };
3242 };
3164
3243
3165 CodeMirror.resolveMode = function(spec) {
3244 CodeMirror.resolveMode = function(spec) {
3166 if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
3245 if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
3167 spec = mimeModes[spec];
3246 spec = mimeModes[spec];
3168 else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
3247 } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
3248 var found = mimeModes[spec.name];
3249 spec = createObj(found, spec);
3250 spec.name = found.name;
3251 } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
3169 return CodeMirror.resolveMode("application/xml");
3252 return CodeMirror.resolveMode("application/xml");
3253 }
3170 if (typeof spec == "string") return {name: spec};
3254 if (typeof spec == "string") return {name: spec};
3171 else return spec || {name: "null"};
3255 else return spec || {name: "null"};
3172 };
3256 };
@@ -3257,6 +3341,10 b' window.CodeMirror = (function() {'
3257 var l = cm.getCursor().line;
3341 var l = cm.getCursor().line;
3258 cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
3342 cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
3259 },
3343 },
3344 delLineLeft: function(cm) {
3345 var cur = cm.getCursor();
3346 cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
3347 },
3260 undo: function(cm) {cm.undo();},
3348 undo: function(cm) {cm.undo();},
3261 redo: function(cm) {cm.redo();},
3349 redo: function(cm) {cm.redo();},
3262 goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
3350 goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
@@ -3352,7 +3440,7 b' window.CodeMirror = (function() {'
3352 "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3440 "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3353 "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3441 "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3354 "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3442 "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3355 "Cmd-[": "indentLess", "Cmd-]": "indentMore",
3443 "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
3356 fallthrough: ["basic", "emacsy"]
3444 fallthrough: ["basic", "emacsy"]
3357 };
3445 };
3358 keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
3446 keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
@@ -3391,7 +3479,7 b' window.CodeMirror = (function() {'
3391
3479
3392 for (var i = 0; i < maps.length; ++i) {
3480 for (var i = 0; i < maps.length; ++i) {
3393 var done = lookup(maps[i]);
3481 var done = lookup(maps[i]);
3394 if (done) return done;
3482 if (done) return done != "stop";
3395 }
3483 }
3396 }
3484 }
3397 function isModifierKey(event) {
3485 function isModifierKey(event) {
@@ -3573,7 +3661,7 b' window.CodeMirror = (function() {'
3573 if (min != null && cm) regChange(cm, min, max + 1);
3661 if (min != null && cm) regChange(cm, min, max + 1);
3574 this.lines.length = 0;
3662 this.lines.length = 0;
3575 this.explicitlyCleared = true;
3663 this.explicitlyCleared = true;
3576 if (this.collapsed && this.doc.cantEdit) {
3664 if (this.atomic && this.doc.cantEdit) {
3577 this.doc.cantEdit = false;
3665 this.doc.cantEdit = false;
3578 if (cm) reCheckSelection(cm);
3666 if (cm) reCheckSelection(cm);
3579 }
3667 }
@@ -3596,15 +3684,18 b' window.CodeMirror = (function() {'
3596 return from && {from: from, to: to};
3684 return from && {from: from, to: to};
3597 };
3685 };
3598
3686
3599 TextMarker.prototype.getOptions = function(copyWidget) {
3687 TextMarker.prototype.changed = function() {
3600 var repl = this.replacedWith;
3688 var pos = this.find(), cm = this.doc.cm;
3601 return {className: this.className,
3689 if (!pos || !cm) return;
3602 inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight,
3690 var line = getLine(this.doc, pos.from.line);
3603 atomic: this.atomic,
3691 clearCachedMeasurement(cm, line);
3604 collapsed: this.collapsed,
3692 if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
3605 replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl,
3693 for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
3606 readOnly: this.readOnly,
3694 if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3607 startStyle: this.startStyle, endStyle: this.endStyle};
3695 break;
3696 }
3697 runInOp(cm, function() { cm.curOp.selectionChanged = true; });
3698 }
3608 };
3699 };
3609
3700
3610 TextMarker.prototype.attachLine = function(line) {
3701 TextMarker.prototype.attachLine = function(line) {
@@ -3633,6 +3724,7 b' window.CodeMirror = (function() {'
3633 if (marker.replacedWith) {
3724 if (marker.replacedWith) {
3634 marker.collapsed = true;
3725 marker.collapsed = true;
3635 marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3726 marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3727 if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3636 }
3728 }
3637 if (marker.collapsed) sawCollapsedSpans = true;
3729 if (marker.collapsed) sawCollapsedSpans = true;
3638
3730
@@ -3704,11 +3796,6 b' window.CodeMirror = (function() {'
3704 SharedTextMarker.prototype.find = function() {
3796 SharedTextMarker.prototype.find = function() {
3705 return this.primary.find();
3797 return this.primary.find();
3706 };
3798 };
3707 SharedTextMarker.prototype.getOptions = function(copyWidget) {
3708 var inner = this.primary.getOptions(copyWidget);
3709 inner.shared = true;
3710 return inner;
3711 };
3712
3799
3713 function markTextShared(doc, from, to, options, type) {
3800 function markTextShared(doc, from, to, options, type) {
3714 options = copyObj(options);
3801 options = copyObj(options);
@@ -3811,6 +3898,13 b' window.CodeMirror = (function() {'
3811 }
3898 }
3812 }
3899 }
3813 }
3900 }
3901 if (sameLine && first) {
3902 // Make sure we didn't create any zero-length spans
3903 for (var i = 0; i < first.length; ++i)
3904 if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
3905 first.splice(i--, 1);
3906 if (!first.length) first = null;
3907 }
3814
3908
3815 var newMarkers = [first];
3909 var newMarkers = [first];
3816 if (!sameLine) {
3910 if (!sameLine) {
@@ -3905,6 +3999,7 b' window.CodeMirror = (function() {'
3905 sp = sps[i];
3999 sp = sps[i];
3906 if (!sp.marker.collapsed) continue;
4000 if (!sp.marker.collapsed) continue;
3907 if (sp.from == null) return true;
4001 if (sp.from == null) return true;
4002 if (sp.marker.replacedWith) continue;
3908 if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
4003 if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
3909 return true;
4004 return true;
3910 }
4005 }
@@ -3918,7 +4013,7 b' window.CodeMirror = (function() {'
3918 return true;
4013 return true;
3919 for (var sp, i = 0; i < line.markedSpans.length; ++i) {
4014 for (var sp, i = 0; i < line.markedSpans.length; ++i) {
3920 sp = line.markedSpans[i];
4015 sp = line.markedSpans[i];
3921 if (sp.marker.collapsed && sp.from == span.to &&
4016 if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
3922 (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4017 (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
3923 lineIsHiddenInner(doc, line, sp)) return true;
4018 lineIsHiddenInner(doc, line, sp)) return true;
3924 }
4019 }
@@ -4030,7 +4125,7 b' window.CodeMirror = (function() {'
4030 function runMode(cm, text, mode, state, f) {
4125 function runMode(cm, text, mode, state, f) {
4031 var flattenSpans = mode.flattenSpans;
4126 var flattenSpans = mode.flattenSpans;
4032 if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4127 if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4033 var curText = "", curStyle = null;
4128 var curStart = 0, curStyle = null;
4034 var stream = new StringStream(text, cm.options.tabSize), style;
4129 var stream = new StringStream(text, cm.options.tabSize), style;
4035 if (text == "" && mode.blankLine) mode.blankLine(state);
4130 if (text == "" && mode.blankLine) mode.blankLine(state);
4036 while (!stream.eol()) {
4131 while (!stream.eol()) {
@@ -4042,14 +4137,13 b' window.CodeMirror = (function() {'
4042 } else {
4137 } else {
4043 style = mode.token(stream, state);
4138 style = mode.token(stream, state);
4044 }
4139 }
4045 var substr = stream.current();
4140 if (!flattenSpans || curStyle != style) {
4141 if (curStart < stream.start) f(stream.start, curStyle);
4142 curStart = stream.start; curStyle = style;
4143 }
4046 stream.start = stream.pos;
4144 stream.start = stream.pos;
4047 if (!flattenSpans || curStyle != style) {
4145 }
4048 if (curText) f(curText, curStyle);
4146 if (curStart < stream.pos) f(stream.pos, curStyle);
4049 curText = substr; curStyle = style;
4050 } else curText = curText + substr;
4051 }
4052 if (curText) f(curText, curStyle);
4053 }
4147 }
4054
4148
4055 function highlightLine(cm, line, state) {
4149 function highlightLine(cm, line, state) {
@@ -4057,27 +4151,24 b' window.CodeMirror = (function() {'
4057 // mode/overlays that it is based on (for easy invalidation).
4151 // mode/overlays that it is based on (for easy invalidation).
4058 var st = [cm.state.modeGen];
4152 var st = [cm.state.modeGen];
4059 // Compute the base array of styles
4153 // Compute the base array of styles
4060 runMode(cm, line.text, cm.doc.mode, state, function(txt, style) {st.push(txt, style);});
4154 runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
4061
4155
4062 // Run overlays, adjust style array.
4156 // Run overlays, adjust style array.
4063 for (var o = 0; o < cm.state.overlays.length; ++o) {
4157 for (var o = 0; o < cm.state.overlays.length; ++o) {
4064 var overlay = cm.state.overlays[o], i = 1;
4158 var overlay = cm.state.overlays[o], i = 1, at = 0;
4065 runMode(cm, line.text, overlay.mode, true, function(txt, style) {
4159 runMode(cm, line.text, overlay.mode, true, function(end, style) {
4066 var start = i, len = txt.length;
4160 var start = i;
4067 // Ensure there's a token end at the current position, and that i points at it
4161 // Ensure there's a token end at the current position, and that i points at it
4068 while (len) {
4162 while (at < end) {
4069 var cur = st[i], len_ = cur.length;
4163 var i_end = st[i];
4070 if (len_ <= len) {
4164 if (i_end > end)
4071 len -= len_;
4165 st.splice(i, 1, end, st[i+1], i_end);
4072 } else {
4073 st.splice(i, 1, cur.slice(0, len), st[i+1], cur.slice(len));
4074 len = 0;
4075 }
4076 i += 2;
4166 i += 2;
4167 at = Math.min(end, i_end);
4077 }
4168 }
4078 if (!style) return;
4169 if (!style) return;
4079 if (overlay.opaque) {
4170 if (overlay.opaque) {
4080 st.splice(start, i - start, txt, style);
4171 st.splice(start, i - start, end, style);
4081 i = start + 2;
4172 i = start + 2;
4082 } else {
4173 } else {
4083 for (; start < i; start += 2) {
4174 for (; start < i; start += 2) {
@@ -4117,37 +4208,31 b' window.CodeMirror = (function() {'
4117 }
4208 }
4118
4209
4119 function lineContent(cm, realLine, measure) {
4210 function lineContent(cm, realLine, measure) {
4120 var merged, line = realLine, lineBefore, sawBefore, simple = true;
4211 var merged, line = realLine, empty = true;
4121 while (merged = collapsedSpanAtStart(line)) {
4212 while (merged = collapsedSpanAtStart(line))
4122 simple = false;
4123 line = getLine(cm.doc, merged.find().from.line);
4213 line = getLine(cm.doc, merged.find().from.line);
4124 if (!lineBefore) lineBefore = line;
4125 }
4126
4214
4127 var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
4215 var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
4128 measure: null, addedOne: false, cm: cm};
4216 measure: null, measuredSomething: false, cm: cm};
4129 if (line.textClass) builder.pre.className = line.textClass;
4217 if (line.textClass) builder.pre.className = line.textClass;
4130
4218
4131 do {
4219 do {
4220 if (line.text) empty = false;
4132 builder.measure = line == realLine && measure;
4221 builder.measure = line == realLine && measure;
4133 builder.pos = 0;
4222 builder.pos = 0;
4134 builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4223 builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4135 if ((ie || webkit) && cm.getOption("lineWrapping"))
4224 if ((ie || webkit) && cm.getOption("lineWrapping"))
4136 builder.addToken = buildTokenSplitSpaces(builder.addToken);
4225 builder.addToken = buildTokenSplitSpaces(builder.addToken);
4137 if (measure && sawBefore && line != realLine && !builder.addedOne) {
4226 var next = insertLineContent(line, builder, getLineStyles(cm, line));
4227 if (measure && line == realLine && !builder.measuredSomething) {
4138 measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4228 measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4139 builder.addedOne = true;
4229 builder.measuredSomething = true;
4140 }
4230 }
4141 var next = insertLineContent(line, builder, getLineStyles(cm, line));
4231 if (next) line = getLine(cm.doc, next.to.line);
4142 sawBefore = line == lineBefore;
4143 if (next) {
4144 line = getLine(cm.doc, next.to.line);
4145 simple = false;
4146 }
4147 } while (next);
4232 } while (next);
4148
4233
4149 if (measure && !builder.addedOne)
4234 if (measure && !builder.measuredSomething && !measure[0])
4150 measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4235 measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4151 if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4236 if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4152 builder.pre.appendChild(document.createTextNode("\u00a0"));
4237 builder.pre.appendChild(document.createTextNode("\u00a0"));
4153
4238
@@ -4216,8 +4301,7 b' window.CodeMirror = (function() {'
4216 if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4301 if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4217 ch = text.slice(i, i + 2);
4302 ch = text.slice(i, i + 2);
4218 ++i;
4303 ++i;
4219 } else if (i && wrapping &&
4304 } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4220 spanAffectsWrapping.test(text.slice(i - 1, i + 1))) {
4221 builder.pre.appendChild(elt("wbr"));
4305 builder.pre.appendChild(elt("wbr"));
4222 }
4306 }
4223 var span = builder.measure[builder.pos] =
4307 var span = builder.measure[builder.pos] =
@@ -4231,7 +4315,7 b' window.CodeMirror = (function() {'
4231 span.style.whiteSpace = "normal";
4315 span.style.whiteSpace = "normal";
4232 builder.pos += ch.length;
4316 builder.pos += ch.length;
4233 }
4317 }
4234 if (text.length) builder.addedOne = true;
4318 if (text.length) builder.measuredSomething = true;
4235 }
4319 }
4236
4320
4237 function buildTokenSplitSpaces(inner) {
4321 function buildTokenSplitSpaces(inner) {
@@ -4249,11 +4333,12 b' window.CodeMirror = (function() {'
4249 function buildCollapsedSpan(builder, size, widget) {
4333 function buildCollapsedSpan(builder, size, widget) {
4250 if (widget) {
4334 if (widget) {
4251 if (!builder.display) widget = widget.cloneNode(true);
4335 if (!builder.display) widget = widget.cloneNode(true);
4336 if (builder.measure) {
4337 builder.measure[builder.pos] = size ? widget
4338 : builder.pre.appendChild(zeroWidthElement(builder.cm.display.measure));
4339 builder.measuredSomething = true;
4340 }
4252 builder.pre.appendChild(widget);
4341 builder.pre.appendChild(widget);
4253 if (builder.measure && size) {
4254 builder.measure[builder.pos] = widget;
4255 builder.addedOne = true;
4256 }
4257 }
4342 }
4258 builder.pos += size;
4343 builder.pos += size;
4259 }
4344 }
@@ -4261,15 +4346,14 b' window.CodeMirror = (function() {'
4261 // Outputs a number of spans to make up a line, taking highlighting
4346 // Outputs a number of spans to make up a line, taking highlighting
4262 // and marked text into account.
4347 // and marked text into account.
4263 function insertLineContent(line, builder, styles) {
4348 function insertLineContent(line, builder, styles) {
4264 var spans = line.markedSpans;
4349 var spans = line.markedSpans, allText = line.text, at = 0;
4265 if (!spans) {
4350 if (!spans) {
4266 for (var i = 1; i < styles.length; i+=2)
4351 for (var i = 1; i < styles.length; i+=2)
4267 builder.addToken(builder, styles[i], styleToClass(styles[i+1]));
4352 builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
4268 return;
4353 return;
4269 }
4354 }
4270
4355
4271 var allText = line.text, len = allText.length;
4356 var len = allText.length, pos = 0, i = 1, text = "", style;
4272 var pos = 0, i = 1, text = "", style;
4273 var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
4357 var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
4274 for (;;) {
4358 for (;;) {
4275 if (nextChange == pos) { // Update current marker set
4359 if (nextChange == pos) { // Update current marker set
@@ -4283,7 +4367,7 b' window.CodeMirror = (function() {'
4283 if (m.className) spanStyle += " " + m.className;
4367 if (m.className) spanStyle += " " + m.className;
4284 if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4368 if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4285 if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4369 if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4286 if (m.collapsed && (!collapsed || collapsed.marker.width < m.width))
4370 if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4287 collapsed = sp;
4371 collapsed = sp;
4288 } else if (sp.from > pos && nextChange > sp.from) {
4372 } else if (sp.from > pos && nextChange > sp.from) {
4289 nextChange = sp.from;
4373 nextChange = sp.from;
@@ -4313,7 +4397,8 b' window.CodeMirror = (function() {'
4313 pos = end;
4397 pos = end;
4314 spanStartStyle = "";
4398 spanStartStyle = "";
4315 }
4399 }
4316 text = styles[i++]; style = styleToClass(styles[i++]);
4400 text = allText.slice(at, at = styles[i++]);
4401 style = styleToClass(styles[i++]);
4317 }
4402 }
4318 }
4403 }
4319 }
4404 }
@@ -4505,6 +4590,7 b' window.CodeMirror = (function() {'
4505 this.scrollTop = this.scrollLeft = 0;
4590 this.scrollTop = this.scrollLeft = 0;
4506 this.cantEdit = false;
4591 this.cantEdit = false;
4507 this.history = makeHistory();
4592 this.history = makeHistory();
4593 this.cleanGeneration = 1;
4508 this.frontier = firstLine;
4594 this.frontier = firstLine;
4509 var start = Pos(firstLine, 0);
4595 var start = Pos(firstLine, 0);
4510 this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
4596 this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
@@ -4516,6 +4602,7 b' window.CodeMirror = (function() {'
4516 };
4602 };
4517
4603
4518 Doc.prototype = createObj(BranchChunk.prototype, {
4604 Doc.prototype = createObj(BranchChunk.prototype, {
4605 constructor: Doc,
4519 iter: function(from, to, op) {
4606 iter: function(from, to, op) {
4520 if (op) this.iterN(from - this.first, to - from, op);
4607 if (op) this.iterN(from - this.first, to - from, op);
4521 else this.iterN(this.first, this.first + this.size, from);
4608 else this.iterN(this.first, this.first + this.size, from);
@@ -4604,20 +4691,25 b' window.CodeMirror = (function() {'
4604 var hist = this.history;
4691 var hist = this.history;
4605 return {undo: hist.done.length, redo: hist.undone.length};
4692 return {undo: hist.done.length, redo: hist.undone.length};
4606 },
4693 },
4607 clearHistory: function() {this.history = makeHistory();},
4694 clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4608
4695
4609 markClean: function() {
4696 markClean: function() {
4610 this.history.dirtyCounter = 0;
4697 this.cleanGeneration = this.changeGeneration();
4698 },
4699 changeGeneration: function() {
4611 this.history.lastOp = this.history.lastOrigin = null;
4700 this.history.lastOp = this.history.lastOrigin = null;
4701 return this.history.generation;
4612 },
4702 },
4613 isClean: function () {return this.history.dirtyCounter == 0;},
4703 isClean: function (gen) {
4704 return this.history.generation == (gen || this.cleanGeneration);
4705 },
4614
4706
4615 getHistory: function() {
4707 getHistory: function() {
4616 return {done: copyHistoryArray(this.history.done),
4708 return {done: copyHistoryArray(this.history.done),
4617 undone: copyHistoryArray(this.history.undone)};
4709 undone: copyHistoryArray(this.history.undone)};
4618 },
4710 },
4619 setHistory: function(histData) {
4711 setHistory: function(histData) {
4620 var hist = this.history = makeHistory();
4712 var hist = this.history = makeHistory(this.history.maxGeneration);
4621 hist.done = histData.done.slice(0);
4713 hist.done = histData.done.slice(0);
4622 hist.undone = histData.undone.slice(0);
4714 hist.undone = histData.undone.slice(0);
4623 },
4715 },
@@ -4847,7 +4939,7 b' window.CodeMirror = (function() {'
4847
4939
4848 // HISTORY
4940 // HISTORY
4849
4941
4850 function makeHistory() {
4942 function makeHistory(startGen) {
4851 return {
4943 return {
4852 // Arrays of history events. Doing something adds an event to
4944 // Arrays of history events. Doing something adds an event to
4853 // done and clears undo. Undoing moves events from done to
4945 // done and clears undo. Undoing moves events from done to
@@ -4857,7 +4949,7 b' window.CodeMirror = (function() {'
4857 // event
4949 // event
4858 lastTime: 0, lastOp: null, lastOrigin: null,
4950 lastTime: 0, lastOp: null, lastOrigin: null,
4859 // Used by the isClean() method
4951 // Used by the isClean() method
4860 dirtyCounter: 0
4952 generation: startGen || 1, maxGeneration: startGen || 1
4861 };
4953 };
4862 }
4954 }
4863
4955
@@ -4901,17 +4993,13 b' window.CodeMirror = (function() {'
4901 } else {
4993 } else {
4902 // Can not be merged, start a new event.
4994 // Can not be merged, start a new event.
4903 cur = {changes: [historyChangeFromChange(doc, change)],
4995 cur = {changes: [historyChangeFromChange(doc, change)],
4996 generation: hist.generation,
4904 anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
4997 anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
4905 anchorAfter: selAfter.anchor, headAfter: selAfter.head};
4998 anchorAfter: selAfter.anchor, headAfter: selAfter.head};
4906 hist.done.push(cur);
4999 hist.done.push(cur);
5000 hist.generation = ++hist.maxGeneration;
4907 while (hist.done.length > hist.undoDepth)
5001 while (hist.done.length > hist.undoDepth)
4908 hist.done.shift();
5002 hist.done.shift();
4909 if (hist.dirtyCounter < 0)
4910 // The user has made a change after undoing past the last clean state.
4911 // We can never get back to a clean state now until markClean() is called.
4912 hist.dirtyCounter = NaN;
4913 else
4914 hist.dirtyCounter++;
4915 }
5003 }
4916 hist.lastTime = time;
5004 hist.lastTime = time;
4917 hist.lastOp = opId;
5005 hist.lastOp = opId;
@@ -5026,6 +5114,9 b' window.CodeMirror = (function() {'
5026 if (e.stopPropagation) e.stopPropagation();
5114 if (e.stopPropagation) e.stopPropagation();
5027 else e.cancelBubble = true;
5115 else e.cancelBubble = true;
5028 }
5116 }
5117 function e_defaultPrevented(e) {
5118 return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5119 }
5029 function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5120 function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5030 CodeMirror.e_stop = e_stop;
5121 CodeMirror.e_stop = e_stop;
5031 CodeMirror.e_preventDefault = e_preventDefault;
5122 CodeMirror.e_preventDefault = e_preventDefault;
@@ -5092,6 +5183,11 b' window.CodeMirror = (function() {'
5092 delayedCallbacks.push(bnd(arr[i]));
5183 delayedCallbacks.push(bnd(arr[i]));
5093 }
5184 }
5094
5185
5186 function signalDOMEvent(cm, e) {
5187 signal(cm, e.type, cm, e);
5188 return e_defaultPrevented(e);
5189 }
5190
5095 function fireDelayed() {
5191 function fireDelayed() {
5096 --delayedCallbackDepth;
5192 --delayedCallbackDepth;
5097 var delayed = delayedCallbacks;
5193 var delayed = delayedCallbacks;
@@ -5146,7 +5242,11 b' window.CodeMirror = (function() {'
5146 if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5242 if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5147 node.selectionStart = 0;
5243 node.selectionStart = 0;
5148 node.selectionEnd = node.value.length;
5244 node.selectionEnd = node.value.length;
5149 } else node.select();
5245 } else {
5246 // Suppress mysterious IE10 errors
5247 try { node.select(); }
5248 catch(_e) {}
5249 }
5150 }
5250 }
5151
5251
5152 function indexOf(collection, elt) {
5252 function indexOf(collection, elt) {
@@ -5180,7 +5280,7 b' window.CodeMirror = (function() {'
5180 return function(){return f.apply(null, args);};
5280 return function(){return f.apply(null, args);};
5181 }
5281 }
5182
5282
5183 var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;
5283 var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
5184 function isWordChar(ch) {
5284 function isWordChar(ch) {
5185 return /\w/.test(ch) || ch > "\x80" &&
5285 return /\w/.test(ch) || ch > "\x80" &&
5186 (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
5286 (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
@@ -5241,13 +5341,24 b' window.CodeMirror = (function() {'
5241 // word wrapping between certain characters *only* if a new inline
5341 // word wrapping between certain characters *only* if a new inline
5242 // element is started between them. This makes it hard to reliably
5342 // element is started between them. This makes it hard to reliably
5243 // measure the position of things, since that requires inserting an
5343 // measure the position of things, since that requires inserting an
5244 // extra span. This terribly fragile set of regexps matches the
5344 // extra span. This terribly fragile set of tests matches the
5245 // character combinations that suffer from this phenomenon on the
5345 // character combinations that suffer from this phenomenon on the
5246 // various browsers.
5346 // various browsers.
5247 var spanAffectsWrapping = /^$/; // Won't match any two-character string
5347 function spanAffectsWrapping() { return false; }
5248 if (gecko) spanAffectsWrapping = /$'/;
5348 if (gecko) // Only for "$'"
5249 else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
5349 spanAffectsWrapping = function(str, i) {
5250 else if (webkit) spanAffectsWrapping = /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.]|\?[\w~`@#$%\^&*(_=+{[|><]/;
5350 return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;
5351 };
5352 else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
5353 spanAffectsWrapping = function(str, i) {
5354 return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
5355 };
5356 else if (webkit)
5357 spanAffectsWrapping = function(str, i) {
5358 if (i > 1 && str.charCodeAt(i - 1) == 45 && /\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i)))
5359 return true;
5360 return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5361 };
5251
5362
5252 var knownScrollbarWidth;
5363 var knownScrollbarWidth;
5253 function scrollbarWidth(measure) {
5364 function scrollbarWidth(measure) {
@@ -5366,6 +5477,40 b' window.CodeMirror = (function() {'
5366 return Pos(lineN, ch);
5477 return Pos(lineN, ch);
5367 }
5478 }
5368
5479
5480 function compareBidiLevel(order, a, b) {
5481 var linedir = order[0].level;
5482 if (a == linedir) return true;
5483 if (b == linedir) return false;
5484 return a < b;
5485 }
5486 var bidiOther;
5487 function getBidiPartAt(order, pos) {
5488 for (var i = 0, found; i < order.length; ++i) {
5489 var cur = order[i];
5490 if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
5491 if (cur.from == pos || cur.to == pos) {
5492 if (found == null) {
5493 found = i;
5494 } else if (compareBidiLevel(order, cur.level, order[found].level)) {
5495 bidiOther = found;
5496 return i;
5497 } else {
5498 bidiOther = i;
5499 return found;
5500 }
5501 }
5502 }
5503 bidiOther = null;
5504 return found;
5505 }
5506
5507 function moveInLine(line, pos, dir, byUnit) {
5508 if (!byUnit) return pos + dir;
5509 do pos += dir;
5510 while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5511 return pos;
5512 }
5513
5369 // This is somewhat involved. It is needed in order to move
5514 // This is somewhat involved. It is needed in order to move
5370 // 'visually' through bi-directional text -- i.e., pressing left
5515 // 'visually' through bi-directional text -- i.e., pressing left
5371 // should make the cursor go left, even when in RTL text. The
5516 // should make the cursor go left, even when in RTL text. The
@@ -5375,37 +5520,24 b' window.CodeMirror = (function() {'
5375 function moveVisually(line, start, dir, byUnit) {
5520 function moveVisually(line, start, dir, byUnit) {
5376 var bidi = getOrder(line);
5521 var bidi = getOrder(line);
5377 if (!bidi) return moveLogically(line, start, dir, byUnit);
5522 if (!bidi) return moveLogically(line, start, dir, byUnit);
5378 var moveOneUnit = byUnit ? function(pos, dir) {
5523 var pos = getBidiPartAt(bidi, start), part = bidi[pos];
5379 do pos += dir;
5524 var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
5380 while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5525
5381 return pos;
5526 for (;;) {
5382 } : function(pos, dir) { return pos + dir; };
5527 if (target > part.from && target < part.to) return target;
5383 var linedir = bidi[0].level;
5528 if (target == part.from || target == part.to) {
5384 for (var i = 0; i < bidi.length; ++i) {
5529 if (getBidiPartAt(bidi, target) == pos) return target;
5385 var part = bidi[i], sticky = part.level % 2 == linedir;
5530 part = bidi[pos += dir];
5386 if ((part.from < start && part.to > start) ||
5531 return (dir > 0) == part.level % 2 ? part.to : part.from;
5387 (sticky && (part.from == start || part.to == start))) break;
5388 }
5389 var target = moveOneUnit(start, part.level % 2 ? -dir : dir);
5390
5391 while (target != null) {
5392 if (part.level % 2 == linedir) {
5393 if (target < part.from || target > part.to) {
5394 part = bidi[i += dir];
5395 target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1));
5396 } else break;
5397 } else {
5532 } else {
5398 if (target == bidiLeft(part)) {
5533 part = bidi[pos += dir];
5399 part = bidi[--i];
5534 if (!part) return null;
5400 target = part && bidiRight(part);
5535 if ((dir > 0) == part.level % 2)
5401 } else if (target == bidiRight(part)) {
5536 target = moveInLine(line, part.to, -1, byUnit);
5402 part = bidi[++i];
5537 else
5403 target = part && bidiLeft(part);
5538 target = moveInLine(line, part.from, 1, byUnit);
5404 } else break;
5405 }
5539 }
5406 }
5540 }
5407
5408 return target < 0 || target > line.text.length ? null : target;
5409 }
5541 }
5410
5542
5411 function moveLogically(line, start, dir, byUnit) {
5543 function moveLogically(line, start, dir, byUnit) {
@@ -5577,7 +5709,7 b' window.CodeMirror = (function() {'
5577
5709
5578 // THE END
5710 // THE END
5579
5711
5580 CodeMirror.version = "3.12";
5712 CodeMirror.version = "3.14.0";
5581
5713
5582 return CodeMirror;
5714 return CodeMirror;
5583 })();
5715 })();
@@ -7,7 +7,7 b''
7 <link rel="stylesheet" href="../../lib/codemirror.css">
7 <link rel="stylesheet" href="../../lib/codemirror.css">
8 <script src="../../lib/codemirror.js"></script>
8 <script src="../../lib/codemirror.js"></script>
9 <script src="../../addon/edit/matchbrackets.js"></script>
9 <script src="../../addon/edit/matchbrackets.js"></script>
10 <script src="apl.js"></script>
10 <script src="./apl.js"></script>
11 <style>
11 <style>
12 .CodeMirror { border: 2px inset #dee; }
12 .CodeMirror { border: 2px inset #dee; }
13 </style>
13 </style>
@@ -16,6 +16,7 b' CodeMirror.modeInfo = ['
16 {name: 'ECL', mime: 'text/x-ecl', mode: 'ecl'},
16 {name: 'ECL', mime: 'text/x-ecl', mode: 'ecl'},
17 {name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'},
17 {name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'},
18 {name: 'Gas', mime: 'text/x-gas', mode: 'gas'},
18 {name: 'Gas', mime: 'text/x-gas', mode: 'gas'},
19 {name: 'GitHub Flavored Markdown', mode: 'gfm'},
19 {name: 'GO', mime: 'text/x-go', mode: 'go'},
20 {name: 'GO', mime: 'text/x-go', mode: 'go'},
20 {name: 'Groovy', mime: 'text/x-groovy', mode: 'groovy'},
21 {name: 'Groovy', mime: 'text/x-groovy', mode: 'groovy'},
21 {name: 'Haskell', mime: 'text/x-haskell', mode: 'haskell'},
22 {name: 'Haskell', mime: 'text/x-haskell', mode: 'haskell'},
@@ -74,232 +75,3 b' CodeMirror.modeInfo = ['
74 {name: 'YAML', mime: 'text/x-yaml', mode: 'yaml'},
75 {name: 'YAML', mime: 'text/x-yaml', mode: 'yaml'},
75 {name: 'Z80', mime: 'text/x-z80', mode: 'z80'}
76 {name: 'Z80', mime: 'text/x-z80', mode: 'z80'}
76 ];
77 ];
77
78
79 MIME_TO_EXT = {
80 'application/javascript': ['*.js'],
81 'text/javascript': ['*.js'],
82 'application/json': ['*.json'],
83 'application/postscript': ['*.ps', '*.eps'],
84 'application/x-actionscript': ['*.as'],
85 'application/x-actionscript3': ['*.as'],
86 'application/x-awk': ['*.awk'],
87 'application/x-befunge': ['*.befunge'],
88 'application/x-brainfuck': ['*.bf', '*.b'],
89 'application/x-cheetah': ['*.tmpl', '*.spt'],
90 'application/x-coldfusion': ['*.cfm', '*.cfml', '*.cfc'],
91 'application/x-csh': ['*.tcsh', '*.csh'],
92 'application/x-dos-batch': ['*.bat', '*.cmd'],
93 'application/x-ecl': ['*.ecl'],
94 'application/x-evoque': ['*.evoque'],
95 'application/x-fantom': ['*.fan'],
96 'application/x-genshi': ['*.kid'],
97 'application/x-gettext': ['*.pot', '*.po'],
98 'application/x-jsp': ['*.jsp'],
99 'application/x-mako': ['*.mao'],
100 'application/x-mason': ['*.m', '*.mhtml', '*.mc', '*.mi', 'autohandler', 'dhandler'],
101 'application/x-myghty': ['*.myt', 'autodelegate'],
102 'application/x-php': ['*.phtml'],
103 'application/x-pypylog': ['*.pypylog'],
104 'application/x-qml': ['*.qml'],
105 'application/x-sh': ['*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass', '.bashrc', 'bashrc', '.bash_*', 'bash_*'],
106 'application/x-sh-session': ['*.shell-session'],
107 'application/x-shell-session': ['*.sh-session'],
108 'application/x-smarty': ['*.tpl'],
109 'application/x-ssp': ['*.ssp'],
110 'application/x-troff': ['*.[1234567]', '*.man'],
111 'application/x-urbiscript': ['*.u'],
112 'application/xml+evoque': ['*.xml'],
113 'application/xml-dtd': ['*.dtd'],
114 'application/xsl+xml': ['*.xsl', '*.xslt', '*.xpl'],
115 'text/S-plus': ['*.S', '*.R', '.Rhistory', '.Rprofile'],
116 'text/coffeescript': ['*.coffee'],
117 'text/css': ['*.css'],
118 'text/haxe': ['*.hx'],
119 'text/html': ['*.html', '*.htm', '*.xhtml', '*.xslt'],
120 'text/html+evoque': ['*.html'],
121 'text/html+ruby': ['*.rhtml'],
122 'text/idl': ['*.pro'],
123 'text/livescript': ['*.ls'],
124 'text/matlab': ['*.m'],
125 'text/octave': ['*.m'],
126 'text/plain': ['*.txt'],
127 'text/scilab': ['*.sci', '*.sce', '*.tst'],
128 'text/smali': ['*.smali'],
129 'text/x-abap': ['*.abap'],
130 'text/x-ada': ['*.adb', '*.ads', '*.ada'],
131 'text/x-apacheconf': ['.htaccess', 'apache.conf', 'apache2.conf'],
132 'text/x-aspectj': ['*.aj'],
133 'text/x-asymptote': ['*.asy'],
134 'text/x-autohotkey': ['*.ahk', '*.ahkl'],
135 'text/x-autoit': ['*.au3'],
136 'text/x-bmx': ['*.bmx'],
137 'text/x-boo': ['*.boo'],
138 'text/x-c++hdr': ['*.cpp', '*.hpp', '*.c++', '*.h++', '*.cc', '*.hh', '*.cxx', '*.hxx', '*.C', '*.H', '*.cp','*.CPP'],
139 'text/x-c-objdump': ['*.c-objdump'],
140 'text/x-ceylon': ['*.ceylon'],
141 'text/x-chdr': ['*.c', '*.h', '*.idc'],
142 'text/x-clojure': ['*.clj'],
143 'text/x-cmake': ['*.cmake', 'CMakeLists.txt'],
144 'text/x-cobol': ['*.cob', '*.COB', '*.cpy', '*.CPY'],
145 'text/x-common-lisp': ['*.cl', '*.lisp', '*.el'],
146 'text/x-coq': ['*.v'],
147 'text/x-cpp-objdump': ['*.cpp-objdump', '*.c++-objdump', '*.cxx-objdump'],
148 'text/x-crocsrc': ['*.croc'],
149 'text/x-csharp': ['*.cs'],
150 'text/x-cuda': ['*.cu', '*.cuh'],
151 'text/x-cython': ['*.pyx', '*.pxd', '*.pxi'],
152 'text/x-d-objdump': ['*.d-objdump'],
153 'text/x-dart': ['*.dart'],
154 'text/x-dg': ['*.dg'],
155 'text/x-diff': ['*.diff', '*.patch'],
156 'text/x-dsrc': ['*.d', '*.di'],
157 'text/x-duel': ['*.duel', '*.jbst'],
158 'text/x-dylan': ['*.dylan', '*.dyl', '*.intr'],
159 'text/x-dylan-console': ['*.dylan-console'],
160 'text/x-dylan-lid': ['*.lid', '*.hdp'],
161 'text/x-echdr': ['*.ec', '*.eh'],
162 'text/x-elixir': ['*.ex', '*.exs'],
163 'text/x-erl-shellsession': ['*.erl-sh'],
164 'text/x-erlang': ['*.erl', '*.hrl', '*.es', '*.escript'],
165 'text/x-factor': ['*.factor'],
166 'text/x-fancysrc': ['*.fy', '*.fancypack'],
167 'text/x-felix': ['*.flx', '*.flxh'],
168 'text/x-fortran': ['*.f', '*.f90', '*.F', '*.F90'],
169 'text/x-fsharp': ['*.fs', '*.fsi'],
170 'text/x-gas': ['*.s', '*.S'],
171 'text/x-gherkin': ['*.feature'],
172 'text/x-glslsrc': ['*.vert', '*.frag', '*.geo'],
173 'text/x-gnuplot': ['*.plot', '*.plt'],
174 'text/x-gooddata-cl': ['*.gdc'],
175 'text/x-gooddata-maql': ['*.maql'],
176 'text/x-gosrc': ['*.go'],
177 'text/x-gosu': ['*.gs', '*.gsx', '*.gsp', '*.vark'],
178 'text/x-gosu-template': ['*.gst'],
179 'text/x-groovy': ['*.groovy'],
180 'text/x-haml': ['*.haml'],
181 'text/x-haskell': ['*.hs'],
182 'text/x-hybris': ['*.hy', '*.hyb'],
183 'text/x-ini': ['*.ini', '*.cfg'],
184 'text/x-iokesrc': ['*.ik'],
185 'text/x-iosrc': ['*.io'],
186 'text/x-irclog': ['*.weechatlog'],
187 'text/x-jade': ['*.jade'],
188 'text/x-java': ['*.java'],
189 'text/x-java-properties': ['*.properties'],
190 'text/x-julia': ['*.jl'],
191 'text/x-kconfig': ['Kconfig', '*Config.in*', 'external.in*', 'standard-modules.in'],
192 'text/x-koka': ['*.kk', '*.kki'],
193 'text/x-kotlin': ['*.kt'],
194 'text/x-lasso': ['*.lasso', '*.lasso[89]'],
195 'text/x-literate-haskell': ['*.lhs'],
196 'text/x-llvm': ['*.ll'],
197 'text/x-logos': ['*.x', '*.xi', '*.xm', '*.xmi'],
198 'text/x-logtalk': ['*.lgt'],
199 'text/x-lua': ['*.lua', '*.wlua'],
200 'text/x-makefile': ['*.mak', 'Makefile', 'makefile', 'Makefile.*', 'GNUmakefile'],
201 'text/x-minidsrc': ['*.md'],
202 'text/x-markdown': ['*.md'],
203 'text/x-modelica': ['*.mo'],
204 'text/x-modula2': ['*.def', '*.mod'],
205 'text/x-monkey': ['*.monkey'],
206 'text/x-moocode': ['*.moo'],
207 'text/x-moonscript': ['*.moon'],
208 'text/x-nasm': ['*.asm', '*.ASM'],
209 'text/x-nemerle': ['*.n'],
210 'text/x-newlisp': ['*.lsp', '*.nl'],
211 'text/x-newspeak': ['*.ns2'],
212 'text/x-nimrod': ['*.nim', '*.nimrod'],
213 'text/x-nsis': ['*.nsi', '*.nsh'],
214 'text/x-objdump': ['*.objdump'],
215 'text/x-objective-c': ['*.m', '*.h'],
216 'text/x-objective-c++': ['*.mm', '*.hh'],
217 'text/x-objective-j': ['*.j'],
218 'text/x-ocaml': ['*.ml', '*.mli', '*.mll', '*.mly'],
219 'text/x-ooc': ['*.ooc'],
220 'text/x-opa': ['*.opa'],
221 'text/x-openedge': ['*.p', '*.cls'],
222 'text/x-pascal': ['*.pas'],
223 'text/x-perl': ['*.pl', '*.pm'],
224 'text/x-php': ['*.php', '*.php[345]', '*.inc'],
225 'text/x-povray': ['*.pov', '*.inc'],
226 'text/x-powershell': ['*.ps1'],
227 'text/x-prolog': ['*.prolog', '*.pro', '*.pl'],
228 'text/x-python': ['*.py', '*.pyw', '*.sc', 'SConstruct', 'SConscript', '*.tac', '*.sage'],
229 'text/x-python-traceback': ['*.pytb'],
230 'text/x-python3-traceback': ['*.py3tb'],
231 'text/x-r-doc': ['*.Rd'],
232 'text/x-racket': ['*.rkt', '*.rktl'],
233 'text/x-rebol': ['*.r', '*.r3'],
234 'text/x-robotframework': ['*.txt', '*.robot'],
235 'text/x-rpm-spec': ['*.spec'],
236 'text/x-rst': ['*.rst', '*.rest'],
237 'text/x-ruby': ['*.rb', '*.rbw', 'Rakefile', '*.rake', '*.gemspec', '*.rbx', '*.duby'],
238 'text/x-rustsrc': ['*.rs', '*.rc'],
239 'text/x-sass': ['*.sass'],
240 'text/x-scala': ['*.scala'],
241 'text/x-scaml': ['*.scaml'],
242 'text/x-scheme': ['*.scm', '*.ss'],
243 'text/x-scss': ['*.scss'],
244 'text/x-smalltalk': ['*.st'],
245 'text/x-snobol': ['*.snobol'],
246 'text/x-sourcepawn': ['*.sp'],
247 'text/x-sql': ['*.sql'],
248 'text/x-sqlite3-console': ['*.sqlite3-console'],
249 'text/x-squidconf': ['squid.conf'],
250 'text/x-standardml': ['*.sml', '*.sig', '*.fun'],
251 'text/x-systemverilog': ['*.sv', '*.svh'],
252 'text/x-tcl': ['*.tcl'],
253 'text/x-tea': ['*.tea'],
254 'text/x-tex': ['*.tex', '*.aux', '*.toc'],
255 'text/x-typescript': ['*.ts'],
256 'text/x-vala': ['*.vala', '*.vapi'],
257 'text/x-vbnet': ['*.vb', '*.bas'],
258 'text/x-verilog': ['*.v'],
259 'text/x-vhdl': ['*.vhdl', '*.vhd'],
260 'text/x-vim': ['*.vim', '.vimrc', '.exrc', '.gvimrc', '_vimrc', '_exrc', '_gvimrc', 'vimrc', 'gvimrc'],
261 'text/x-windows-registry': ['*.reg'],
262 'text/x-xtend': ['*.xtend'],
263 'text/x-yaml': ['*.yaml', '*.yml'],
264 'text/xml': ['*.xml', '*.xsl', '*.rss', '*.xslt', '*.xsd', '*.wsdl'],
265 'text/xquery': ['*.xqy', '*.xquery', '*.xq', '*.xql', '*.xqm'],
266 'text/apl': [],
267 'text/x-asterisk': [],
268 'text/x-csrc': [],
269 'text/x-c++src': ['*.cpp'],
270 'text/x-coffeescript': ['*.coffee'],
271 'text/x-d': ["*.d"],
272 'text/x-ecl': ['*.ecl'],
273 'text/x-go': ['*.go'],
274 'text/x-haxe': ['*.hx'],
275 'application/x-aspx': ['*.aspx'],
276 'application/x-ejs': [],
277 'message/http': [],
278 'application/x-json': ['*.json'],
279 'application/typescript': ['*.ts'],
280 'jinja2': ['.jinja2'],
281 'text/x-less': ['*.less'],
282 'text/x-livescript': ['*.ls'],
283 'text/mirc': [],
284 'text/n-triples': [],
285 'application/x-httpd-php': ['*.php'],
286 'text/x-pig': [],
287 'text/x-properties': ['*.properties'],
288 'text/x-rsrc': [],
289 'text/x-sh': ['*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass', '.bashrc', 'bashrc', '.bash_*', 'bash_*'],
290 'application/sieve': [],
291 'text/x-stsrc': ['*.rs', '*.rc'],
292 'text/x-smarty': ['*.tpl'],
293 'application/x-sparql-query': [],
294 'text/x-mariadb': ['*.sql'],
295 'text/x-stex': [],
296 'text/x-latex': ["*.ltx"],
297 'text/x-tiddlywiki': [],
298 'text/tiki': [],
299 'text/x-vb': ['*.vb'],
300 'text/vbscript': ['*.vb'],
301 'text/velocity': [],
302 'application/xml': ['*.xml', '*.xsl', '*.rss', '*.xslt', '*.xsd', '*.wsdl'],
303 'application/xquery': ['*.xqy', '*.xquery', '*.xq', '*.xql', '*.xqm'],
304 'text/x-z80': [],
305 }
@@ -43,7 +43,7 b' function hello($who) {'
43 </script>
43 </script>
44
44
45 <p>Simple HTML/PHP mode based on
45 <p>Simple HTML/PHP mode based on
46 the <a href="../clike">C-like</a> mode. Depends on XML,
46 the <a href="../clike/">C-like</a> mode. Depends on XML,
47 JavaScript, CSS, HTMLMixed, and C-like modes.</p>
47 JavaScript, CSS, HTMLMixed, and C-like modes.</p>
48
48
49 <p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>
49 <p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>
General Comments 0
You need to be logged in to leave comments. Login now