##// 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 19 padding: 0 4px; /* Horizontal padding of content */
20 20 }
21 21
22 .CodeMirror-scrollbar-filler {
22 .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
23 23 background-color: white; /* The little square between H and V scrollbars */
24 24 }
25 25
@@ -28,6 +28,7 b''
28 28 .CodeMirror-gutters {
29 29 border-right: 1px solid #ddd;
30 30 background-color: #f7f7f7;
31 white-space: nowrap;
31 32 }
32 33 .CodeMirror-linenumbers {}
33 34 .CodeMirror-linenumber {
@@ -124,7 +125,7 b' div.CodeMirror span.CodeMirror-nonmatchi'
124 125 /* The fake, visible scrollbars. Used to force redraw during scrolling
125 126 before actuall scrolling happens, thus preventing shaking and
126 127 flickering artifacts. */
127 .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
128 .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
128 129 position: absolute;
129 130 z-index: 6;
130 131 display: none;
@@ -141,16 +142,18 b' div.CodeMirror span.CodeMirror-nonmatchi'
141 142 }
142 143 .CodeMirror-scrollbar-filler {
143 144 right: 0; bottom: 0;
144 z-index: 6;
145 }
146 .CodeMirror-gutter-filler {
147 left: 0; bottom: 0;
145 148 }
146 149
147 150 .CodeMirror-gutters {
148 151 position: absolute; left: 0; top: 0;
149 height: 100%;
150 152 padding-bottom: 30px;
151 153 z-index: 3;
152 154 }
153 155 .CodeMirror-gutter {
156 white-space: normal;
154 157 height: 100%;
155 158 padding-bottom: 30px;
156 159 margin-bottom: -32px;
@@ -202,7 +205,6 b' div.CodeMirror span.CodeMirror-nonmatchi'
202 205 }
203 206
204 207 .CodeMirror-widget {
205 display: inline-block;
206 208 }
207 209
208 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 3 // CodeMirror is the only global var we claim
2 4 window.CodeMirror = (function() {
3 5 "use strict";
@@ -97,7 +99,7 b' window.CodeMirror = (function() {'
97 99 else input.setAttribute("wrap", "off");
98 100 // if border: 0; -- iOS fails to open keyboard (issue #1287)
99 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 104 // Wraps and hides input textarea
103 105 d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
@@ -105,8 +107,9 b' window.CodeMirror = (function() {'
105 107 d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
106 108 d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
107 109 d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
110 d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
108 111 // DIVs containing the selection and the actual code
109 d.lineDiv = elt("div");
112 d.lineDiv = elt("div", null, "CodeMirror-code");
110 113 d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
111 114 // Blinky cursor, and element used to ensure cursor fits at the end of a line
112 115 d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
@@ -126,14 +129,12 b' window.CodeMirror = (function() {'
126 129 // Will contain the gutters, if any
127 130 d.gutters = elt("div", null, "CodeMirror-gutters");
128 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 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 134 d.scroller.setAttribute("tabIndex", "-1");
134 135 // The element in which the editor lives.
135 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 138 // Work around IE7 z-index bug
138 139 if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
139 140 if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
@@ -212,7 +213,7 b' window.CodeMirror = (function() {'
212 213 estimateLineHeights(cm);
213 214 regChange(cm);
214 215 clearCaches(cm);
215 setTimeout(function(){updateScrollbars(cm.display, cm.doc.height);}, 100);
216 setTimeout(function(){updateScrollbars(cm);}, 100);
216 217 }
217 218
218 219 function estimateHeight(cm) {
@@ -237,9 +238,10 b' window.CodeMirror = (function() {'
237 238 }
238 239
239 240 function keyMapChanged(cm) {
240 var style = keyMap[cm.options.keyMap].style;
241 var map = keyMap[cm.options.keyMap], style = map.style;
241 242 cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
242 243 (style ? " cm-keymap-" + style : "");
244 cm.state.disableInput = map.disableInput;
243 245 }
244 246
245 247 function themeChanged(cm) {
@@ -251,6 +253,7 b' window.CodeMirror = (function() {'
251 253 function guttersChanged(cm) {
252 254 updateGutters(cm);
253 255 regChange(cm);
256 setTimeout(function(){alignHorizontally(cm);}, 20);
254 257 }
255 258
256 259 function updateGutters(cm) {
@@ -317,12 +320,14 b' window.CodeMirror = (function() {'
317 320
318 321 // Re-synchronize the fake scrollbars with the actual size of the
319 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 325 var totalHeight = docHeight + paddingVert(d);
322 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 328 var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
324 var needsH = d.scroller.scrollWidth > d.scroller.clientWidth;
325 var needsV = scrollHeight > d.scroller.clientHeight;
329 var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
330 var needsV = scrollHeight > (d.scroller.clientHeight + 1);
326 331 if (needsV) {
327 332 d.scrollbarV.style.display = "block";
328 333 d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
@@ -339,6 +344,11 b' window.CodeMirror = (function() {'
339 344 d.scrollbarFiller.style.display = "block";
340 345 d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
341 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 353 if (mac_geLion && scrollbarWidth(d.measure) === 0)
344 354 d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
@@ -397,14 +407,10 b' window.CodeMirror = (function() {'
397 407 var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
398 408 var visible = visibleLines(cm.display, cm.doc, viewPort);
399 409 for (;;) {
400 if (updateDisplayInner(cm, changes, visible)) {
401 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;
410 if (!updateDisplayInner(cm, changes, visible)) break;
411 updated = true;
406 412 updateSelection(cm);
407 updateScrollbars(cm.display, cm.doc.height);
413 updateScrollbars(cm);
408 414
409 415 // Clip forced viewport to actual scrollable area
410 416 if (viewPort)
@@ -416,6 +422,11 b' window.CodeMirror = (function() {'
416 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 430 return updated;
420 431 }
421 432
@@ -503,9 +514,11 b' window.CodeMirror = (function() {'
503 514 display.lastSizeC != display.wrapper.clientHeight;
504 515 // This is just a bogus formula that detects when the editor is
505 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 521 display.showingFrom = from; display.showingTo = to;
508 startWorker(cm, 100);
509 522
510 523 var prevBottom = display.lineDiv.offsetTop;
511 524 for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
@@ -594,8 +607,9 b' window.CodeMirror = (function() {'
594 607 if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
595 608 if (lineIsHidden(cm.doc, line)) {
596 609 if (line.height != 0) updateLineHeight(line, 0);
597 if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i)
598 if (line.widgets[i].showIfHidden) {
610 if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
611 var w = line.widgets[i];
612 if (w.showIfHidden) {
599 613 var prev = cur.previousSibling;
600 614 if (/pre/i.test(prev.nodeName)) {
601 615 var wrap = elt("div", null, null, "position: relative");
@@ -603,9 +617,11 b' window.CodeMirror = (function() {'
603 617 wrap.appendChild(prev);
604 618 prev = wrap;
605 619 }
606 var wnode = prev.appendChild(elt("div", [line.widgets[i].node], "CodeMirror-linewidget"));
607 positionLineWidget(line.widgets[i], wnode, prev, dims);
620 var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
621 if (!w.handleMouseEvents) wnode.ignoreEvents = true;
622 positionLineWidget(w, wnode, prev, dims);
608 623 }
624 }
609 625 } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
610 626 // This line is intact. Skip to the actual node. Update its
611 627 // line number if needed.
@@ -648,25 +664,25 b' window.CodeMirror = (function() {'
648 664
649 665 if (reuse) {
650 666 reuse.alignable = null;
651 var isOk = true, widgetsSeen = 0;
667 var isOk = true, widgetsSeen = 0, insertBefore = null;
652 668 for (var n = reuse.firstChild, next; n; n = next) {
653 669 next = n.nextSibling;
654 670 if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
655 671 reuse.removeChild(n);
656 672 } else {
657 673 for (var i = 0, first = true; i < line.widgets.length; ++i) {
658 var widget = line.widgets[i], isFirst = false;
659 if (!widget.above) { isFirst = first; first = false; }
674 var widget = line.widgets[i];
675 if (!widget.above) { insertBefore = n; first = false; }
660 676 if (widget.node == n.firstChild) {
661 677 positionLineWidget(widget, n, reuse, dims);
662 678 ++widgetsSeen;
663 if (isFirst) reuse.insertBefore(lineElement, n);
664 679 break;
665 680 }
666 681 }
667 682 if (i == line.widgets.length) { isOk = false; break; }
668 683 }
669 684 }
685 reuse.insertBefore(lineElement, insertBefore);
670 686 if (isOk && widgetsSeen == line.widgets.length) {
671 687 wrap = reuse;
672 688 reuse.className = line.wrapClass || "";
@@ -701,6 +717,7 b' window.CodeMirror = (function() {'
701 717 if (ie_lt8) wrap.style.zIndex = 2;
702 718 if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
703 719 var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
720 if (!widget.handleMouseEvents) node.ignoreEvents = true;
704 721 positionLineWidget(widget, node, wrap, dims);
705 722 if (widget.above)
706 723 wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
@@ -783,74 +800,59 b' window.CodeMirror = (function() {'
783 800 "px; height: " + (bottom - top) + "px"));
784 801 }
785 802
786 function drawForLine(line, fromArg, toArg, retTop) {
803 function drawForLine(line, fromArg, toArg) {
787 804 var lineObj = getLine(doc, line);
788 var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity;
789 function coords(ch) {
790 return charCoords(cm, Pos(line, ch), "div", lineObj);
805 var lineLen = lineObj.text.length;
806 var start, end;
807 function coords(ch, bias) {
808 return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
791 809 }
792 810
793 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 813 if (from == to) {
796 814 rightPos = leftPos;
797 815 left = right = leftPos.left;
798 816 } else {
799 rightPos = coords(to - 1);
817 rightPos = coords(to - 1, "right");
800 818 if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
801 819 left = leftPos.left;
802 820 right = rightPos.right;
803 821 }
822 if (fromArg == null && from == 0) left = pl;
804 823 if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
805 824 add(left, leftPos.top, null, leftPos.bottom);
806 825 left = pl;
807 826 if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
808 827 }
809 828 if (toArg == null && to == lineLen) right = clientWidth;
810 if (fromArg == null && from == 0) left = pl;
811 rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal);
829 if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
830 start = leftPos;
831 if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
832 end = rightPos;
812 833 if (left < pl + 1) left = pl;
813 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 839 if (sel.from.line == sel.to.line) {
819 840 drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
820 841 } else {
821 var fromObj = getLine(doc, sel.from.line);
822 var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine;
823 while (merged = collapsedSpanAtEnd(cur)) {
824 var found = merged.find();
825 path.push(found.from.ch, found.to.line, found.to.ch);
826 if (found.to.line == sel.to.line) {
827 path.push(sel.to.ch);
828 singleLine = true;
829 break;
842 var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
843 var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
844 var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
845 var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
846 if (singleVLine) {
847 if (leftEnd.top < rightStart.top - 2) {
848 add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
849 add(pl, rightStart.top, rightStart.left, rightStart.bottom);
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
834 // This is a single, merged line
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 if (leftEnd.bottom < rightStart.top)
855 add(pl, leftEnd.bottom, null, rightStart.top);
854 856 }
855 857
856 858 removeChildrenAndAdd(display.selectionDiv, fragment);
@@ -916,12 +918,12 b' window.CodeMirror = (function() {'
916 918 // valid state. If that fails, it returns the line with the
917 919 // smallest indentation, which tends to need the least context to
918 920 // parse correctly.
919 function findStartLine(cm, n) {
921 function findStartLine(cm, n, precise) {
920 922 var minindent, minline, doc = cm.doc;
921 923 for (var search = n, lim = n - 100; search > lim; --search) {
922 924 if (search <= doc.first) return doc.first;
923 925 var line = getLine(doc, search - 1);
924 if (line.stateAfter) return search;
926 if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
925 927 var indented = countColumn(line.text, null, cm.options.tabSize);
926 928 if (minline == null || minindent > indented) {
927 929 minline = search - 1;
@@ -931,10 +933,10 b' window.CodeMirror = (function() {'
931 933 return minline;
932 934 }
933 935
934 function getStateBefore(cm, n) {
936 function getStateBefore(cm, n, precise) {
935 937 var doc = cm.doc, display = cm.display;
936 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 940 if (!state) state = startState(doc.mode);
939 941 else state = copyState(doc.mode, state);
940 942 doc.iter(pos, n, function(line) {
@@ -955,7 +957,7 b' window.CodeMirror = (function() {'
955 957 return e.offsetLeft;
956 958 }
957 959
958 function measureChar(cm, line, ch, data) {
960 function measureChar(cm, line, ch, data, bias) {
959 961 var dir = -1;
960 962 data = data || measureLine(cm, line);
961 963
@@ -964,9 +966,11 b' window.CodeMirror = (function() {'
964 966 if (r) break;
965 967 if (dir < 0 && pos == 0) dir = 1;
966 968 }
969 var rightV = (pos < ch || bias == "right") && r.topRight != null;
967 970 return {left: pos < ch ? r.right : r.left,
968 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 976 function findCachedMeasurement(cm, line) {
@@ -976,23 +980,28 b' window.CodeMirror = (function() {'
976 980 if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
977 981 cm.display.scroller.clientWidth == memo.width &&
978 982 memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
979 return memo.measure;
980 }
983 return memo;
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 992 function measureLine(cm, line) {
984 993 // First look in the cache
985 var measure = findCachedMeasurement(cm, line);
986 if (!measure) {
987 // Failing that, recompute and store result in cache
988 measure = measureLineInner(cm, line);
989 var cache = cm.display.measureLineCache;
990 var memo = {text: line.text, width: cm.display.scroller.clientWidth,
991 markedSpans: line.markedSpans, measure: measure,
992 classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
993 if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
994 else cache.push(memo);
995 }
994 var cached = findCachedMeasurement(cm, line);
995 if (cached) return cached.measure;
996
997 // Failing that, recompute and store result in cache
998 var measure = measureLineInner(cm, line);
999 var cache = cm.display.measureLineCache;
1000 var memo = {text: line.text, width: cm.display.scroller.clientWidth,
1001 markedSpans: line.markedSpans, measure: measure,
1002 classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
1003 if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
1004 else cache.push(memo);
996 1005 return measure;
997 1006 }
998 1007
@@ -1034,9 +1043,9 b' window.CodeMirror = (function() {'
1034 1043 if (ie_lt9 && display.measure.first != pre)
1035 1044 removeChildrenAndAdd(display.measure, pre);
1036 1045
1037 for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1038 var size = getRect(cur);
1039 var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
1046 function categorizeVSpan(top, bot) {
1047 if (bot > maxBot) bot = maxBot;
1048 if (top < 0) top = 0;
1040 1049 for (var j = 0; j < vranges.length; j += 2) {
1041 1050 var rtop = vranges[j], rbot = vranges[j+1];
1042 1051 if (rtop > bot || rbot < top) continue;
@@ -1045,19 +1054,38 b' window.CodeMirror = (function() {'
1045 1054 Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1046 1055 vranges[j] = Math.min(top, rtop);
1047 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 1080 var right = size.right;
1053 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 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 1086 cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
1059 }
1060
1087 if (vrRight != null) { cur.topRight = vranges[vrRight]; cur.bottomRight = vranges[vrRight+1]; }
1088 }
1061 1089 return data;
1062 1090 }
1063 1091
@@ -1068,7 +1096,7 b' window.CodeMirror = (function() {'
1068 1096 if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1069 1097 }
1070 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 1101 var pre = lineContent(cm, line);
1074 1102 var end = pre.appendChild(zeroWidthElement(cm.display.measure));
@@ -1083,6 +1111,9 b' window.CodeMirror = (function() {'
1083 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 1117 // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1087 1118 function intoCoordSystem(cm, lineObj, rect, context) {
1088 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 1123 if (context == "line") return rect;
1093 1124 if (!context) context = "local";
1094 1125 var yOff = heightAtLine(cm, lineObj);
1095 if (context != "local") yOff -= cm.display.viewOffset;
1096 if (context == "page") {
1126 if (context == "local") yOff += paddingTop(cm.display);
1127 else yOff -= cm.display.viewOffset;
1128 if (context == "page" || context == "window") {
1097 1129 var lOff = getRect(cm.display.lineSpace);
1098 yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop);
1099 var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft);
1130 yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
1131 var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
1100 1132 rect.left += xOff; rect.right += xOff;
1101 1133 }
1102 1134 rect.top += yOff; rect.bottom += yOff;
@@ -1108,64 +1140,58 b' window.CodeMirror = (function() {'
1108 1140 function fromCoordSystem(cm, coords, context) {
1109 1141 if (context == "div") return coords;
1110 1142 var left = coords.left, top = coords.top;
1143 // First move into "page" coordinate system
1111 1144 if (context == "page") {
1112 left -= window.pageXOffset || (document.documentElement || document.body).scrollLeft;
1113 top -= window.pageYOffset || (document.documentElement || document.body).scrollTop;
1114 }
1145 left -= pageScrollX();
1146 top -= pageScrollY();
1147 } else if (context == "local" || !context) {
1148 var localBox = getRect(cm.display.sizer);
1149 left += localBox.left;
1150 top += localBox.top;
1151 }
1152
1115 1153 var lineSpaceBox = getRect(cm.display.lineSpace);
1116 left -= lineSpaceBox.left;
1117 top -= lineSpaceBox.top;
1118 if (context == "local" || !context) {
1119 var editorBox = getRect(cm.display.wrapper);
1120 left += editorBox.left;
1121 top += editorBox.top;
1122 }
1123 return {left: left, top: top};
1124 }
1125
1126 function charCoords(cm, pos, context, lineObj) {
1154 return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1155 }
1156
1157 function charCoords(cm, pos, context, lineObj, bias) {
1127 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 1162 function cursorCoords(cm, pos, context, lineObj, measurement) {
1132 1163 lineObj = lineObj || getLine(cm.doc, pos.line);
1133 1164 if (!measurement) measurement = measureLine(cm, lineObj);
1134 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 1167 if (right) m.left = m.right; else m.right = m.left;
1137 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 1184 var order = getOrder(lineObj), ch = pos.ch;
1140 1185 if (!order) return get(ch);
1141 var main, other, linedir = order[0].level;
1142 for (var i = 0; i < order.length; ++i) {
1143 var part = order[i], rtl = part.level % 2, nb, here;
1144 if (part.from < ch && part.to > ch) return get(ch, rtl);
1145 var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to;
1146 if (left == ch) {
1147 // IE returns bogus offsets and widths for edges where the
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) {
1186 var partPos = getBidiPartAt(order, ch);
1187 var val = getBidi(ch, partPos);
1188 if (bidiOther != null) val.other = getBidi(ch, bidiOther);
1189 return val;
1190 }
1191
1192 function PosWithInfo(line, ch, outside, xRel) {
1168 1193 var pos = new Pos(line, ch);
1194 pos.xRel = xRel;
1169 1195 if (outside) pos.outside = true;
1170 1196 return pos;
1171 1197 }
@@ -1174,10 +1200,10 b' window.CodeMirror = (function() {'
1174 1200 function coordsChar(cm, x, y) {
1175 1201 var doc = cm.doc;
1176 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 1204 var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1179 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 1207 if (x < 0) x = 0;
1182 1208
1183 1209 for (;;) {
@@ -1185,7 +1211,7 b' window.CodeMirror = (function() {'
1185 1211 var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1186 1212 var merged = collapsedSpanAtEnd(lineObj);
1187 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 1215 lineNo = mergedPos.to.line;
1190 1216 else
1191 1217 return found;
@@ -1211,14 +1237,15 b' window.CodeMirror = (function() {'
1211 1237 var from = lineLeft(lineObj), to = lineRight(lineObj);
1212 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 1241 // Do a binary search between these bounds.
1216 1242 for (;;) {
1217 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 1246 while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1220 var pos = PosMaybeOutside(lineNo, ch, after ? fromOutside : toOutside);
1221 pos.after = after;
1247 var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1248 xDiff < 0 ? -1 : xDiff ? 1 : 0);
1222 1249 return pos;
1223 1250 }
1224 1251 var step = Math.ceil(dist / 2), middle = from + step;
@@ -1404,7 +1431,7 b' window.CodeMirror = (function() {'
1404 1431 // supported or compatible enough yet to rely on.)
1405 1432 function readInput(cm) {
1406 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 1435 var text = input.value;
1409 1436 if (text == prevInput && posEq(sel.from, sel.to)) return false;
1410 1437 if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
@@ -1422,11 +1449,14 b' window.CodeMirror = (function() {'
1422 1449 from = Pos(from.line, from.ch - (prevInput.length - same));
1423 1450 else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1424 1451 to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1452
1425 1453 var updateInput = cm.curOp.updateInput;
1426 makeChange(cm.doc, {from: from, to: to, text: splitLines(text.slice(same)),
1427 origin: cm.state.pasteIncoming ? "paste" : "+input"}, "end");
1428
1454 var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1455 origin: cm.state.pasteIncoming ? "paste" : "+input"};
1456 makeChange(cm.doc, changeEvent, "end");
1429 1457 cm.curOp.updateInput = updateInput;
1458 signalLater(cm, "inputRead", cm, changeEvent);
1459
1430 1460 if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1431 1461 else cm.display.prevInput = text;
1432 1462 if (withOp) endOperation(cm);
@@ -1467,6 +1497,7 b' window.CodeMirror = (function() {'
1467 1497 on(d.scroller, "mousedown", operation(cm, onMouseDown));
1468 1498 if (ie)
1469 1499 on(d.scroller, "dblclick", operation(cm, function(e) {
1500 if (signalDOMEvent(cm, e)) return;
1470 1501 var pos = posFromMouse(cm, e);
1471 1502 if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1472 1503 e_preventDefault(e);
@@ -1474,7 +1505,7 b' window.CodeMirror = (function() {'
1474 1505 extendSelection(cm.doc, word.from, word.to);
1475 1506 }));
1476 1507 else
1477 on(d.scroller, "dblclick", e_preventDefault);
1508 on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
1478 1509 on(d.lineSpace, "selectstart", function(e) {
1479 1510 if (!eventInWidget(d, e)) e_preventDefault(e);
1480 1511 });
@@ -1506,11 +1537,15 b' window.CodeMirror = (function() {'
1506 1537 // Prevent wrapper from ever scrolling
1507 1538 on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1508 1539
1540 var resizeTimer;
1509 1541 function onResize() {
1510 // Might be a text scaling operation, clear size caches.
1511 d.cachedCharWidth = d.cachedTextHeight = null;
1512 clearCaches(cm);
1513 runInOp(cm, bind(regChange, cm));
1542 if (resizeTimer == null) resizeTimer = setTimeout(function() {
1543 resizeTimer = null;
1544 // Might be a text scaling operation, clear size caches.
1545 d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
1546 clearCaches(cm);
1547 runInOp(cm, bind(regChange, cm));
1548 }, 100);
1514 1549 }
1515 1550 on(window, "resize", onResize);
1516 1551 // Above handler holds on to the editor and its data structures.
@@ -1524,7 +1559,7 b' window.CodeMirror = (function() {'
1524 1559 setTimeout(unregister, 5000);
1525 1560
1526 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 1563 if (e.keyCode == 16) cm.doc.sel.shift = false;
1529 1564 }));
1530 1565 on(d.input, "input", bind(fastPoll, cm));
@@ -1534,7 +1569,7 b' window.CodeMirror = (function() {'
1534 1569 on(d.input, "blur", bind(onBlur, cm));
1535 1570
1536 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 1573 e_stop(e);
1539 1574 }
1540 1575 if (cm.options.dragDrop) {
@@ -1573,9 +1608,7 b' window.CodeMirror = (function() {'
1573 1608
1574 1609 function eventInWidget(display, e) {
1575 1610 for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1576 if (!n) return true;
1577 if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) ||
1578 n.parentNode == display.sizer && n != display.mover) return true;
1611 if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1579 1612 }
1580 1613 }
1581 1614
@@ -1585,7 +1618,7 b' window.CodeMirror = (function() {'
1585 1618 var target = e_target(e);
1586 1619 if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1587 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 1623 var x, y, space = getRect(display.lineSpace);
1591 1624 // Fails unpredictably on IE[67] when mouse is dragged around quickly.
@@ -1595,6 +1628,7 b' window.CodeMirror = (function() {'
1595 1628
1596 1629 var lastClick, lastDoubleClick;
1597 1630 function onMouseDown(e) {
1631 if (signalDOMEvent(this, e)) return;
1598 1632 var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1599 1633 sel.shift = e.shiftKey;
1600 1634
@@ -1718,8 +1752,6 b' window.CodeMirror = (function() {'
1718 1752
1719 1753 function done(e) {
1720 1754 counter = Infinity;
1721 var cur = posFromMouse(cm, e);
1722 if (cur) doSelect(cur);
1723 1755 e_preventDefault(e);
1724 1756 focusInput(cm);
1725 1757 off(document, "mousemove", move);
@@ -1735,11 +1767,41 b' window.CodeMirror = (function() {'
1735 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 1799 function onDrop(e) {
1739 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 1802 return;
1742 1803 e_preventDefault(e);
1804 if (ie) lastDrop = +new Date;
1743 1805 var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1744 1806 if (!pos || isReadOnly(cm)) return;
1745 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 1844 function onDragStart(cm, e) {
1808 if (ie && !cm.state.draggingText) { e_stop(e); return; }
1809 if (eventInWidget(cm.display, e)) return;
1845 if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1846 if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1810 1847
1811 1848 var txt = cm.getSelection();
1812 1849 e.dataTransfer.setData("Text", txt);
1813 1850
1814 1851 // Use dummy image instead of default browsers image.
1815 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 1854 var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1818 1855 if (opera) {
1819 1856 img.width = img.height = 1;
@@ -1821,15 +1858,6 b' window.CodeMirror = (function() {'
1821 1858 // Force a relayout, or Opera won't use our image for some obscure reason
1822 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 1861 e.dataTransfer.setDragImage(img, 0, 0);
1834 1862 if (opera) img.parentNode.removeChild(img);
1835 1863 }
@@ -1842,6 +1870,7 b' window.CodeMirror = (function() {'
1842 1870 if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1843 1871 if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1844 1872 if (gecko) updateDisplay(cm, []);
1873 startWorker(cm, 100);
1845 1874 }
1846 1875 function setScrollLeft(cm, val, isScroller) {
1847 1876 if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
@@ -1974,8 +2003,10 b' window.CodeMirror = (function() {'
1974 2003 var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
1975 2004 clearTimeout(maybeTransition);
1976 2005 if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
1977 if (getKeyMap(cm.options.keyMap) == startMap)
2006 if (getKeyMap(cm.options.keyMap) == startMap) {
1978 2007 cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2008 keyMapChanged(cm);
2009 }
1979 2010 }, 50);
1980 2011
1981 2012 var name = keyName(e, true), handled = false;
@@ -1988,17 +2019,18 b' window.CodeMirror = (function() {'
1988 2019 // 'go') bound to the keyname without 'Shift-'.
1989 2020 handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
1990 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 2025 } else {
1994 2026 handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
1995 2027 }
1996 if (handled == "stop") handled = false;
1997 2028
1998 2029 if (handled) {
1999 2030 e_preventDefault(e);
2000 2031 restartBlink(cm);
2001 2032 if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2033 signalLater(cm, "keyHandled", cm, name, e);
2002 2034 }
2003 2035 return handled;
2004 2036 }
@@ -2009,6 +2041,7 b' window.CodeMirror = (function() {'
2009 2041 if (handled) {
2010 2042 e_preventDefault(e);
2011 2043 restartBlink(cm);
2044 signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
2012 2045 }
2013 2046 return handled;
2014 2047 }
@@ -2018,7 +2051,7 b' window.CodeMirror = (function() {'
2018 2051 var cm = this;
2019 2052 if (!cm.state.focused) onFocus(cm);
2020 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 2055 var code = e.keyCode;
2023 2056 // IE does strange things with escape.
2024 2057 cm.doc.sel.shift = code == 16 || e.shiftKey;
@@ -2034,7 +2067,7 b' window.CodeMirror = (function() {'
2034 2067
2035 2068 function onKeyPress(e) {
2036 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 2071 var keyCode = e.keyCode, charCode = e.charCode;
2039 2072 if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2040 2073 if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
@@ -2090,6 +2123,13 b' window.CodeMirror = (function() {'
2090 2123 // Adds "Select all" to context menu in FF
2091 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 2133 function rehide() {
2094 2134 display.inputDiv.style.position = "relative";
2095 2135 display.input.style.cssText = oldCSS;
@@ -2097,12 +2137,10 b' window.CodeMirror = (function() {'
2097 2137 slowPoll(cm);
2098 2138
2099 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 2142 clearTimeout(detectingSelectAll);
2102 var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0;
2103 display.prevInput = " ";
2104 display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2105 var poll = function(){
2143 var i = 0, poll = function(){
2106 2144 if (display.prevInput == " " && display.input.selectionStart == 0)
2107 2145 operation(cm, commands.selectAll)(cm);
2108 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 2154 if (captureMiddleClick) {
2116 2155 e_stop(e);
2117 2156 var mouseup = function() {
@@ -2126,11 +2165,11 b' window.CodeMirror = (function() {'
2126 2165
2127 2166 // UPDATING
2128 2167
2129 function changeEnd(change) {
2168 var changeEnd = CodeMirror.changeEnd = function(change) {
2130 2169 if (!change.text) return change.to;
2131 2170 return Pos(change.from.line + change.text.length - 1,
2132 2171 lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2133 }
2172 };
2134 2173
2135 2174 // Make sure a position will be valid after the given change.
2136 2175 function clipPostChange(doc, change, pos) {
@@ -2172,21 +2211,21 b' window.CodeMirror = (function() {'
2172 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 2215 var obj = {
2177 2216 canceled: false,
2178 2217 from: change.from,
2179 2218 to: change.to,
2180 2219 text: change.text,
2181 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 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 2229 signal(doc, "beforeChange", doc, obj);
2191 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 2244 if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2206 change = filterChange(doc, change);
2245 change = filterChange(doc, change, true);
2207 2246 if (!change) return;
2208 2247 }
2209 2248
@@ -2242,15 +2281,23 b' window.CodeMirror = (function() {'
2242 2281 var hist = doc.history;
2243 2282 var event = (type == "undo" ? hist.done : hist.undone).pop();
2244 2283 if (!event) return;
2245 hist.dirtyCounter += type == "undo" ? -1 : 1;
2246 2284
2247 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 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 2293 for (var i = event.changes.length - 1; i >= 0; --i) {
2252 2294 var change = event.changes[i];
2253 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 2301 anti.changes.push(historyChangeFromChange(doc, change));
2255 2302
2256 2303 var after = i ? computeSelAfterChange(doc, change, null)
@@ -2512,11 +2559,11 b' window.CodeMirror = (function() {'
2512 2559 // SCROLLING
2513 2560
2514 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 2563 if (!cm.state.focused) return;
2517 var display = cm.display, box = getRect(display.sizer), doScroll = null, pTop = paddingTop(cm.display);
2518 if (coords.top + pTop + box.top < 0) doScroll = true;
2519 else if (coords.bottom + pTop + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2564 var display = cm.display, box = getRect(display.sizer), doScroll = null;
2565 if (coords.top + box.top < 0) doScroll = true;
2566 else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2520 2567 if (doScroll != null && !phantom) {
2521 2568 var hidden = display.cursor.style.display == "none";
2522 2569 if (hidden) {
@@ -2554,12 +2601,11 b' window.CodeMirror = (function() {'
2554 2601 }
2555 2602
2556 2603 function calculateScrollPos(cm, x1, y1, x2, y2) {
2557 var display = cm.display, pt = paddingTop(display);
2558 y1 += pt; y2 += pt;
2604 var display = cm.display, snapMargin = textHeight(cm.display);
2559 2605 if (y1 < 0) y1 = 0;
2560 2606 var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2561 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 2609 if (y1 < screentop) {
2564 2610 result.scrollTop = atTop ? 0 : y1;
2565 2611 } else if (y2 > screentop + screen) {
@@ -2596,7 +2642,7 b' window.CodeMirror = (function() {'
2596 2642
2597 2643 function indentLine(cm, n, how, aggressive) {
2598 2644 var doc = cm.doc;
2599 if (!how) how = "add";
2645 if (how == null) how = "add";
2600 2646 if (how == "smart") {
2601 2647 if (!cm.doc.mode.indent) how = "prev";
2602 2648 else var state = getStateBefore(cm, n);
@@ -2619,6 +2665,8 b' window.CodeMirror = (function() {'
2619 2665 indentation = curSpace + cm.options.indentUnit;
2620 2666 } else if (how == "subtract") {
2621 2667 indentation = curSpace - cm.options.indentUnit;
2668 } else if (typeof how == "number") {
2669 indentation = curSpace + how;
2622 2670 }
2623 2671 indentation = Math.max(0, indentation);
2624 2672
@@ -2643,7 +2691,7 b' window.CodeMirror = (function() {'
2643 2691 }
2644 2692
2645 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 2695 var lineObj = getLine(doc, line);
2648 2696 var possible = true;
2649 2697 function findNextLine() {
@@ -2682,7 +2730,7 b' window.CodeMirror = (function() {'
2682 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 2734 if (!possible) result.hitSide = true;
2687 2735 return result;
2688 2736 }
@@ -2707,7 +2755,7 b' window.CodeMirror = (function() {'
2707 2755 function findWordAt(line, pos) {
2708 2756 var start = pos.ch, end = pos.ch;
2709 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 2759 var startChar = line.charAt(start);
2712 2760 var check = isWordChar(startChar) ? isWordChar
2713 2761 : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
@@ -2728,6 +2776,7 b' window.CodeMirror = (function() {'
2728 2776 // 'wrap f in an operation, performed on its `this` parameter'
2729 2777
2730 2778 CodeMirror.prototype = {
2779 constructor: CodeMirror,
2731 2780 focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2732 2781
2733 2782 setOption: function(option, value) {
@@ -2763,7 +2812,8 b' window.CodeMirror = (function() {'
2763 2812 removeOverlay: operation(null, function(spec) {
2764 2813 var overlays = this.state.overlays;
2765 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 2817 overlays.splice(i, 1);
2768 2818 this.state.modeGen++;
2769 2819 regChange(this);
@@ -2773,7 +2823,7 b' window.CodeMirror = (function() {'
2773 2823 }),
2774 2824
2775 2825 indentLine: operation(null, function(n, dir, aggressive) {
2776 if (typeof dir != "string") {
2826 if (typeof dir != "string" && typeof dir != "number") {
2777 2827 if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2778 2828 else dir = dir ? "add" : "subtract";
2779 2829 }
@@ -2788,10 +2838,10 b' window.CodeMirror = (function() {'
2788 2838
2789 2839 // Fetch the parser token for a given character. Useful for hacks
2790 2840 // that want to inspect the mode state (say, for completion).
2791 getTokenAt: function(pos) {
2841 getTokenAt: function(pos, precise) {
2792 2842 var doc = this.doc;
2793 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 2845 var line = getLine(doc, pos.line);
2796 2846 var stream = new StringStream(line.text, this.options.tabSize);
2797 2847 while (stream.pos < pos.ch && !stream.eol()) {
@@ -2806,10 +2856,22 b' window.CodeMirror = (function() {'
2806 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 2872 var doc = this.doc;
2811 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 2877 cursorCoords: function(start, mode) {
@@ -2829,6 +2891,19 b' window.CodeMirror = (function() {'
2829 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 2907 defaultTextHeight: function() { return textHeight(this.display); },
2833 2908 defaultCharWidth: function() { return charWidth(this.display); },
2834 2909
@@ -2857,7 +2932,7 b' window.CodeMirror = (function() {'
2857 2932 return changeLine(this, handle, function(line) {
2858 2933 var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2859 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 2936 else line[prop] += " " + cls;
2862 2937 return true;
2863 2938 });
@@ -2870,9 +2945,10 b' window.CodeMirror = (function() {'
2870 2945 if (!cur) return false;
2871 2946 else if (cls == null) line[prop] = null;
2872 2947 else {
2873 var upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), "");
2874 if (upd == cur) return false;
2875 line[prop] = upd || null;
2948 var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
2949 if (!found) return false;
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 2953 return true;
2878 2954 });
@@ -2920,7 +2996,7 b' window.CodeMirror = (function() {'
2920 2996 if (left + node.offsetWidth > hspace)
2921 2997 left = hspace - node.offsetWidth;
2922 2998 }
2923 node.style.top = (top + paddingTop(display)) + "px";
2999 node.style.top = top + "px";
2924 3000 node.style.left = node.style.right = "";
2925 3001 if (horiz == "right") {
2926 3002 left = display.sizer.clientWidth - node.offsetWidth;
@@ -2988,7 +3064,8 b' window.CodeMirror = (function() {'
2988 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 3069 if (this.state.overwrite = !this.state.overwrite)
2993 3070 this.display.cursor.className += " CodeMirror-overwrite";
2994 3071 else
@@ -3111,6 +3188,7 b' window.CodeMirror = (function() {'
3111 3188 cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3112 3189 cm.refresh();
3113 3190 }, true);
3191 option("coverGutterNextToScrollbar", false, updateScrollbars, true);
3114 3192 option("lineNumbers", false, function(cm) {
3115 3193 setGuttersForLineNumbers(cm.options);
3116 3194 guttersChanged(cm);
@@ -3126,6 +3204,7 b' window.CodeMirror = (function() {'
3126 3204 option("dragDrop", true);
3127 3205
3128 3206 option("cursorBlinkRate", 530);
3207 option("cursorScrollMargin", 0);
3129 3208 option("cursorHeight", 1);
3130 3209 option("workTime", 100);
3131 3210 option("workDelay", 100);
@@ -3163,10 +3242,15 b' window.CodeMirror = (function() {'
3163 3242 };
3164 3243
3165 3244 CodeMirror.resolveMode = function(spec) {
3166 if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
3245 if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
3167 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 3252 return CodeMirror.resolveMode("application/xml");
3253 }
3170 3254 if (typeof spec == "string") return {name: spec};
3171 3255 else return spec || {name: "null"};
3172 3256 };
@@ -3257,6 +3341,10 b' window.CodeMirror = (function() {'
3257 3341 var l = cm.getCursor().line;
3258 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 3348 undo: function(cm) {cm.undo();},
3261 3349 redo: function(cm) {cm.redo();},
3262 3350 goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
@@ -3352,7 +3440,7 b' window.CodeMirror = (function() {'
3352 3440 "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3353 3441 "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3354 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 3444 fallthrough: ["basic", "emacsy"]
3357 3445 };
3358 3446 keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
@@ -3391,7 +3479,7 b' window.CodeMirror = (function() {'
3391 3479
3392 3480 for (var i = 0; i < maps.length; ++i) {
3393 3481 var done = lookup(maps[i]);
3394 if (done) return done;
3482 if (done) return done != "stop";
3395 3483 }
3396 3484 }
3397 3485 function isModifierKey(event) {
@@ -3573,7 +3661,7 b' window.CodeMirror = (function() {'
3573 3661 if (min != null && cm) regChange(cm, min, max + 1);
3574 3662 this.lines.length = 0;
3575 3663 this.explicitlyCleared = true;
3576 if (this.collapsed && this.doc.cantEdit) {
3664 if (this.atomic && this.doc.cantEdit) {
3577 3665 this.doc.cantEdit = false;
3578 3666 if (cm) reCheckSelection(cm);
3579 3667 }
@@ -3596,15 +3684,18 b' window.CodeMirror = (function() {'
3596 3684 return from && {from: from, to: to};
3597 3685 };
3598 3686
3599 TextMarker.prototype.getOptions = function(copyWidget) {
3600 var repl = this.replacedWith;
3601 return {className: this.className,
3602 inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight,
3603 atomic: this.atomic,
3604 collapsed: this.collapsed,
3605 replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl,
3606 readOnly: this.readOnly,
3607 startStyle: this.startStyle, endStyle: this.endStyle};
3687 TextMarker.prototype.changed = function() {
3688 var pos = this.find(), cm = this.doc.cm;
3689 if (!pos || !cm) return;
3690 var line = getLine(this.doc, pos.from.line);
3691 clearCachedMeasurement(cm, line);
3692 if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
3693 for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
3694 if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3695 break;
3696 }
3697 runInOp(cm, function() { cm.curOp.selectionChanged = true; });
3698 }
3608 3699 };
3609 3700
3610 3701 TextMarker.prototype.attachLine = function(line) {
@@ -3633,6 +3724,7 b' window.CodeMirror = (function() {'
3633 3724 if (marker.replacedWith) {
3634 3725 marker.collapsed = true;
3635 3726 marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3727 if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3636 3728 }
3637 3729 if (marker.collapsed) sawCollapsedSpans = true;
3638 3730
@@ -3704,11 +3796,6 b' window.CodeMirror = (function() {'
3704 3796 SharedTextMarker.prototype.find = function() {
3705 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 3800 function markTextShared(doc, from, to, options, type) {
3714 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 3909 var newMarkers = [first];
3816 3910 if (!sameLine) {
@@ -3905,6 +3999,7 b' window.CodeMirror = (function() {'
3905 3999 sp = sps[i];
3906 4000 if (!sp.marker.collapsed) continue;
3907 4001 if (sp.from == null) return true;
4002 if (sp.marker.replacedWith) continue;
3908 4003 if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
3909 4004 return true;
3910 4005 }
@@ -3918,7 +4013,7 b' window.CodeMirror = (function() {'
3918 4013 return true;
3919 4014 for (var sp, i = 0; i < line.markedSpans.length; ++i) {
3920 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 4017 (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
3923 4018 lineIsHiddenInner(doc, line, sp)) return true;
3924 4019 }
@@ -4030,7 +4125,7 b' window.CodeMirror = (function() {'
4030 4125 function runMode(cm, text, mode, state, f) {
4031 4126 var flattenSpans = mode.flattenSpans;
4032 4127 if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4033 var curText = "", curStyle = null;
4128 var curStart = 0, curStyle = null;
4034 4129 var stream = new StringStream(text, cm.options.tabSize), style;
4035 4130 if (text == "" && mode.blankLine) mode.blankLine(state);
4036 4131 while (!stream.eol()) {
@@ -4042,14 +4137,13 b' window.CodeMirror = (function() {'
4042 4137 } else {
4043 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 4144 stream.start = stream.pos;
4047 if (!flattenSpans || curStyle != style) {
4048 if (curText) f(curText, curStyle);
4049 curText = substr; curStyle = style;
4050 } else curText = curText + substr;
4051 }
4052 if (curText) f(curText, curStyle);
4145 }
4146 if (curStart < stream.pos) f(stream.pos, curStyle);
4053 4147 }
4054 4148
4055 4149 function highlightLine(cm, line, state) {
@@ -4057,27 +4151,24 b' window.CodeMirror = (function() {'
4057 4151 // mode/overlays that it is based on (for easy invalidation).
4058 4152 var st = [cm.state.modeGen];
4059 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 4156 // Run overlays, adjust style array.
4063 4157 for (var o = 0; o < cm.state.overlays.length; ++o) {
4064 var overlay = cm.state.overlays[o], i = 1;
4065 runMode(cm, line.text, overlay.mode, true, function(txt, style) {
4066 var start = i, len = txt.length;
4158 var overlay = cm.state.overlays[o], i = 1, at = 0;
4159 runMode(cm, line.text, overlay.mode, true, function(end, style) {
4160 var start = i;
4067 4161 // Ensure there's a token end at the current position, and that i points at it
4068 while (len) {
4069 var cur = st[i], len_ = cur.length;
4070 if (len_ <= len) {
4071 len -= len_;
4072 } else {
4073 st.splice(i, 1, cur.slice(0, len), st[i+1], cur.slice(len));
4074 len = 0;
4075 }
4162 while (at < end) {
4163 var i_end = st[i];
4164 if (i_end > end)
4165 st.splice(i, 1, end, st[i+1], i_end);
4076 4166 i += 2;
4167 at = Math.min(end, i_end);
4077 4168 }
4078 4169 if (!style) return;
4079 4170 if (overlay.opaque) {
4080 st.splice(start, i - start, txt, style);
4171 st.splice(start, i - start, end, style);
4081 4172 i = start + 2;
4082 4173 } else {
4083 4174 for (; start < i; start += 2) {
@@ -4117,37 +4208,31 b' window.CodeMirror = (function() {'
4117 4208 }
4118 4209
4119 4210 function lineContent(cm, realLine, measure) {
4120 var merged, line = realLine, lineBefore, sawBefore, simple = true;
4121 while (merged = collapsedSpanAtStart(line)) {
4122 simple = false;
4211 var merged, line = realLine, empty = true;
4212 while (merged = collapsedSpanAtStart(line))
4123 4213 line = getLine(cm.doc, merged.find().from.line);
4124 if (!lineBefore) lineBefore = line;
4125 }
4126 4214
4127 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 4217 if (line.textClass) builder.pre.className = line.textClass;
4130 4218
4131 4219 do {
4220 if (line.text) empty = false;
4132 4221 builder.measure = line == realLine && measure;
4133 4222 builder.pos = 0;
4134 4223 builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4135 4224 if ((ie || webkit) && cm.getOption("lineWrapping"))
4136 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 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));
4142 sawBefore = line == lineBefore;
4143 if (next) {
4144 line = getLine(cm.doc, next.to.line);
4145 simple = false;
4146 }
4231 if (next) line = getLine(cm.doc, next.to.line);
4147 4232 } while (next);
4148 4233
4149 if (measure && !builder.addedOne)
4150 measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4234 if (measure && !builder.measuredSomething && !measure[0])
4235 measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4151 4236 if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4152 4237 builder.pre.appendChild(document.createTextNode("\u00a0"));
4153 4238
@@ -4216,8 +4301,7 b' window.CodeMirror = (function() {'
4216 4301 if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4217 4302 ch = text.slice(i, i + 2);
4218 4303 ++i;
4219 } else if (i && wrapping &&
4220 spanAffectsWrapping.test(text.slice(i - 1, i + 1))) {
4304 } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4221 4305 builder.pre.appendChild(elt("wbr"));
4222 4306 }
4223 4307 var span = builder.measure[builder.pos] =
@@ -4231,7 +4315,7 b' window.CodeMirror = (function() {'
4231 4315 span.style.whiteSpace = "normal";
4232 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 4321 function buildTokenSplitSpaces(inner) {
@@ -4249,11 +4333,12 b' window.CodeMirror = (function() {'
4249 4333 function buildCollapsedSpan(builder, size, widget) {
4250 4334 if (widget) {
4251 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 4341 builder.pre.appendChild(widget);
4253 if (builder.measure && size) {
4254 builder.measure[builder.pos] = widget;
4255 builder.addedOne = true;
4256 }
4257 4342 }
4258 4343 builder.pos += size;
4259 4344 }
@@ -4261,15 +4346,14 b' window.CodeMirror = (function() {'
4261 4346 // Outputs a number of spans to make up a line, taking highlighting
4262 4347 // and marked text into account.
4263 4348 function insertLineContent(line, builder, styles) {
4264 var spans = line.markedSpans;
4349 var spans = line.markedSpans, allText = line.text, at = 0;
4265 4350 if (!spans) {
4266 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 4353 return;
4269 4354 }
4270 4355
4271 var allText = line.text, len = allText.length;
4272 var pos = 0, i = 1, text = "", style;
4356 var len = allText.length, pos = 0, i = 1, text = "", style;
4273 4357 var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
4274 4358 for (;;) {
4275 4359 if (nextChange == pos) { // Update current marker set
@@ -4283,7 +4367,7 b' window.CodeMirror = (function() {'
4283 4367 if (m.className) spanStyle += " " + m.className;
4284 4368 if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4285 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 4371 collapsed = sp;
4288 4372 } else if (sp.from > pos && nextChange > sp.from) {
4289 4373 nextChange = sp.from;
@@ -4313,7 +4397,8 b' window.CodeMirror = (function() {'
4313 4397 pos = end;
4314 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 4590 this.scrollTop = this.scrollLeft = 0;
4506 4591 this.cantEdit = false;
4507 4592 this.history = makeHistory();
4593 this.cleanGeneration = 1;
4508 4594 this.frontier = firstLine;
4509 4595 var start = Pos(firstLine, 0);
4510 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 4604 Doc.prototype = createObj(BranchChunk.prototype, {
4605 constructor: Doc,
4519 4606 iter: function(from, to, op) {
4520 4607 if (op) this.iterN(from - this.first, to - from, op);
4521 4608 else this.iterN(this.first, this.first + this.size, from);
@@ -4604,20 +4691,25 b' window.CodeMirror = (function() {'
4604 4691 var hist = this.history;
4605 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 4696 markClean: function() {
4610 this.history.dirtyCounter = 0;
4697 this.cleanGeneration = this.changeGeneration();
4698 },
4699 changeGeneration: function() {
4611 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 4707 getHistory: function() {
4616 4708 return {done: copyHistoryArray(this.history.done),
4617 4709 undone: copyHistoryArray(this.history.undone)};
4618 4710 },
4619 4711 setHistory: function(histData) {
4620 var hist = this.history = makeHistory();
4712 var hist = this.history = makeHistory(this.history.maxGeneration);
4621 4713 hist.done = histData.done.slice(0);
4622 4714 hist.undone = histData.undone.slice(0);
4623 4715 },
@@ -4847,7 +4939,7 b' window.CodeMirror = (function() {'
4847 4939
4848 4940 // HISTORY
4849 4941
4850 function makeHistory() {
4942 function makeHistory(startGen) {
4851 4943 return {
4852 4944 // Arrays of history events. Doing something adds an event to
4853 4945 // done and clears undo. Undoing moves events from done to
@@ -4857,7 +4949,7 b' window.CodeMirror = (function() {'
4857 4949 // event
4858 4950 lastTime: 0, lastOp: null, lastOrigin: null,
4859 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 4993 } else {
4902 4994 // Can not be merged, start a new event.
4903 4995 cur = {changes: [historyChangeFromChange(doc, change)],
4996 generation: hist.generation,
4904 4997 anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
4905 4998 anchorAfter: selAfter.anchor, headAfter: selAfter.head};
4906 4999 hist.done.push(cur);
5000 hist.generation = ++hist.maxGeneration;
4907 5001 while (hist.done.length > hist.undoDepth)
4908 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 5004 hist.lastTime = time;
4917 5005 hist.lastOp = opId;
@@ -5026,6 +5114,9 b' window.CodeMirror = (function() {'
5026 5114 if (e.stopPropagation) e.stopPropagation();
5027 5115 else e.cancelBubble = true;
5028 5116 }
5117 function e_defaultPrevented(e) {
5118 return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5119 }
5029 5120 function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5030 5121 CodeMirror.e_stop = e_stop;
5031 5122 CodeMirror.e_preventDefault = e_preventDefault;
@@ -5092,6 +5183,11 b' window.CodeMirror = (function() {'
5092 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 5191 function fireDelayed() {
5096 5192 --delayedCallbackDepth;
5097 5193 var delayed = delayedCallbacks;
@@ -5146,7 +5242,11 b' window.CodeMirror = (function() {'
5146 5242 if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5147 5243 node.selectionStart = 0;
5148 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 5252 function indexOf(collection, elt) {
@@ -5180,7 +5280,7 b' window.CodeMirror = (function() {'
5180 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 5284 function isWordChar(ch) {
5185 5285 return /\w/.test(ch) || ch > "\x80" &&
5186 5286 (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
@@ -5241,13 +5341,24 b' window.CodeMirror = (function() {'
5241 5341 // word wrapping between certain characters *only* if a new inline
5242 5342 // element is started between them. This makes it hard to reliably
5243 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 5345 // character combinations that suffer from this phenomenon on the
5246 5346 // various browsers.
5247 var spanAffectsWrapping = /^$/; // Won't match any two-character string
5248 if (gecko) spanAffectsWrapping = /$'/;
5249 else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
5250 else if (webkit) spanAffectsWrapping = /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.]|\?[\w~`@#$%\^&*(_=+{[|><]/;
5347 function spanAffectsWrapping() { return false; }
5348 if (gecko) // Only for "$'"
5349 spanAffectsWrapping = function(str, i) {
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 5363 var knownScrollbarWidth;
5253 5364 function scrollbarWidth(measure) {
@@ -5366,6 +5477,40 b' window.CodeMirror = (function() {'
5366 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 5514 // This is somewhat involved. It is needed in order to move
5370 5515 // 'visually' through bi-directional text -- i.e., pressing left
5371 5516 // should make the cursor go left, even when in RTL text. The
@@ -5375,37 +5520,24 b' window.CodeMirror = (function() {'
5375 5520 function moveVisually(line, start, dir, byUnit) {
5376 5521 var bidi = getOrder(line);
5377 5522 if (!bidi) return moveLogically(line, start, dir, byUnit);
5378 var moveOneUnit = byUnit ? function(pos, dir) {
5379 do pos += dir;
5380 while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5381 return pos;
5382 } : function(pos, dir) { return pos + dir; };
5383 var linedir = bidi[0].level;
5384 for (var i = 0; i < bidi.length; ++i) {
5385 var part = bidi[i], sticky = part.level % 2 == linedir;
5386 if ((part.from < start && part.to > start) ||
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;
5523 var pos = getBidiPartAt(bidi, start), part = bidi[pos];
5524 var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
5525
5526 for (;;) {
5527 if (target > part.from && target < part.to) return target;
5528 if (target == part.from || target == part.to) {
5529 if (getBidiPartAt(bidi, target) == pos) return target;
5530 part = bidi[pos += dir];
5531 return (dir > 0) == part.level % 2 ? part.to : part.from;
5397 5532 } else {
5398 if (target == bidiLeft(part)) {
5399 part = bidi[--i];
5400 target = part && bidiRight(part);
5401 } else if (target == bidiRight(part)) {
5402 part = bidi[++i];
5403 target = part && bidiLeft(part);
5404 } else break;
5533 part = bidi[pos += dir];
5534 if (!part) return null;
5535 if ((dir > 0) == part.level % 2)
5536 target = moveInLine(line, part.to, -1, byUnit);
5537 else
5538 target = moveInLine(line, part.from, 1, byUnit);
5405 5539 }
5406 5540 }
5407
5408 return target < 0 || target > line.text.length ? null : target;
5409 5541 }
5410 5542
5411 5543 function moveLogically(line, start, dir, byUnit) {
@@ -5577,7 +5709,7 b' window.CodeMirror = (function() {'
5577 5709
5578 5710 // THE END
5579 5711
5580 CodeMirror.version = "3.12";
5712 CodeMirror.version = "3.14.0";
5581 5713
5582 5714 return CodeMirror;
5583 5715 })();
@@ -7,7 +7,7 b''
7 7 <link rel="stylesheet" href="../../lib/codemirror.css">
8 8 <script src="../../lib/codemirror.js"></script>
9 9 <script src="../../addon/edit/matchbrackets.js"></script>
10 <script src="apl.js"></script>
10 <script src="./apl.js"></script>
11 11 <style>
12 12 .CodeMirror { border: 2px inset #dee; }
13 13 </style>
@@ -16,6 +16,7 b' CodeMirror.modeInfo = ['
16 16 {name: 'ECL', mime: 'text/x-ecl', mode: 'ecl'},
17 17 {name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'},
18 18 {name: 'Gas', mime: 'text/x-gas', mode: 'gas'},
19 {name: 'GitHub Flavored Markdown', mode: 'gfm'},
19 20 {name: 'GO', mime: 'text/x-go', mode: 'go'},
20 21 {name: 'Groovy', mime: 'text/x-groovy', mode: 'groovy'},
21 22 {name: 'Haskell', mime: 'text/x-haskell', mode: 'haskell'},
@@ -74,232 +75,3 b' CodeMirror.modeInfo = ['
74 75 {name: 'YAML', mime: 'text/x-yaml', mode: 'yaml'},
75 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 43 </script>
44 44
45 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 47 JavaScript, CSS, HTMLMixed, and C-like modes.</p>
48 48
49 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