codemirror-rails 4.0 → 4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +302 -115
  4. data/vendor/assets/javascripts/codemirror/addons/display/rulers.js +2 -2
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +35 -18
  6. data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +18 -9
  7. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +1 -1
  8. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +3 -1
  9. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +31 -13
  10. data/vendor/assets/javascripts/codemirror/addons/lint/css-lint.js +1 -0
  11. data/vendor/assets/javascripts/codemirror/addons/lint/javascript-lint.js +1 -0
  12. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +15 -10
  13. data/vendor/assets/javascripts/codemirror/addons/mode/overlay.js +8 -2
  14. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +1 -0
  15. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.js +1 -0
  16. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +1 -0
  17. data/vendor/assets/javascripts/codemirror/addons/search/search.js +14 -14
  18. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +14 -2
  19. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +212 -141
  20. data/vendor/assets/javascripts/codemirror/modes/clike.js +4 -5
  21. data/vendor/assets/javascripts/codemirror/modes/css.js +23 -6
  22. data/vendor/assets/javascripts/codemirror/modes/django.js +64 -0
  23. data/vendor/assets/javascripts/codemirror/modes/dylan.js +284 -0
  24. data/vendor/assets/javascripts/codemirror/modes/erlang.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/modes/go.js +1 -0
  26. data/vendor/assets/javascripts/codemirror/modes/haml.js +3 -8
  27. data/vendor/assets/javascripts/codemirror/modes/haxe.js +75 -3
  28. data/vendor/assets/javascripts/codemirror/modes/javascript.js +14 -8
  29. data/vendor/assets/javascripts/codemirror/modes/jinja2.js +111 -35
  30. data/vendor/assets/javascripts/codemirror/modes/livescript.js +4 -4
  31. data/vendor/assets/javascripts/codemirror/modes/markdown.js +5 -2
  32. data/vendor/assets/javascripts/codemirror/modes/php.js +99 -9
  33. data/vendor/assets/javascripts/codemirror/modes/r.js +3 -1
  34. data/vendor/assets/javascripts/codemirror/modes/verilog.js +237 -78
  35. data/vendor/assets/javascripts/codemirror/modes/xml.js +61 -29
  36. data/vendor/assets/stylesheets/codemirror.css +5 -3
  37. data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +0 -1
  38. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +0 -4
  39. data/vendor/assets/stylesheets/codemirror/themes/mdn-like.css +1 -1
  40. data/vendor/assets/stylesheets/codemirror/themes/pastel-on-dark.css +0 -1
  41. data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +0 -2
  42. data/vendor/assets/stylesheets/codemirror/themes/solarized.css +3 -17
  43. metadata +20 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7bd8d5f3cb73a14f9ba71c164bfece36e2bca49b
4
- data.tar.gz: 2175fad70b9f62dbd07033563e8026323f2903c2
3
+ metadata.gz: dd16e48b5a4bf97bb9b7d6e9fe4369007477156a
4
+ data.tar.gz: e2cd3b0008e31a240d67416decca66fde5d62ec5
5
5
  SHA512:
6
- metadata.gz: 879221d705829f88de678fd2f1f43e3b871ed0558641dadc9fa05b670e1758e15f0082bed65956667d526e859a2187e5a4507826b686aa94bf7fad5684ccdbbf
7
- data.tar.gz: 32321a4e855066e5b82d47b34b6b89ce26362d9ae656b4f62b4d24032cf92e4435f55aca7027b0229b6613c55e4f2704b4572416edf0a16dd8a2a62f6a8cece3
6
+ metadata.gz: 1a4dbd28831a7db000009ca3abf95ecda5f30352e637c49b26936ea258fbb9f5f8f2a2d0ef086bb4b5aff3c69211253985b47205e289365e02838dfa3900e020
7
+ data.tar.gz: 1006bd816e052f66e24cbfb00ac4500aca09d043b772880cd7b8445072f129fd27208a95172d9d53d6466fcf4a6f8b8052c22d62af167fb4c065c88ebb371d70
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '4.0'
4
- CODEMIRROR_VERSION = '4.0'
3
+ VERSION = '4.1'
4
+ CODEMIRROR_VERSION = '4.1'
5
5
  end
6
6
  end
@@ -33,7 +33,6 @@
33
33
  var presto = /Opera\//.test(navigator.userAgent);
34
34
  var safari = /Apple Computer/.test(navigator.vendor);
35
35
  var khtml = /KHTML\//.test(navigator.userAgent);
36
- var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
37
36
  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
38
37
  var phantom = /PhantomJS/.test(navigator.userAgent);
39
38
 
@@ -63,8 +62,7 @@
63
62
 
64
63
  this.options = options = options || {};
65
64
  // Determine effective options based on given values and defaults.
66
- for (var opt in defaults) if (!options.hasOwnProperty(opt))
67
- options[opt] = defaults[opt];
65
+ copyObj(defaults, options, false);
68
66
  setGuttersForLineNumbers(options);
69
67
 
70
68
  var doc = options.value;
@@ -256,10 +254,10 @@
256
254
 
257
255
  function wrappingChanged(cm) {
258
256
  if (cm.options.lineWrapping) {
259
- cm.display.wrapper.className += " CodeMirror-wrap";
257
+ addClass(cm.display.wrapper, "CodeMirror-wrap");
260
258
  cm.display.sizer.style.minWidth = "";
261
259
  } else {
262
- cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
260
+ rmClass(cm.display.wrapper, "CodeMirror-wrap");
263
261
  findMaxLine(cm);
264
262
  }
265
263
  estimateLineHeights(cm);
@@ -329,9 +327,13 @@
329
327
  }
330
328
  }
331
329
  gutters.style.display = i ? "" : "none";
332
- var width = gutters.offsetWidth;
330
+ updateGutterSpace(cm);
331
+ }
332
+
333
+ function updateGutterSpace(cm) {
334
+ var width = cm.display.gutters.offsetWidth;
333
335
  cm.display.sizer.style.marginLeft = width + "px";
334
- if (i) cm.display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;
336
+ cm.display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;
335
337
  }
336
338
 
337
339
  // Compute the character length of a line, taking into account
@@ -434,14 +436,18 @@
434
436
  d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
435
437
  } else d.gutterFiller.style.display = "";
436
438
 
437
- if (mac_geLion && scrollbarWidth(d.measure) === 0) {
438
- d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
439
- var barMouseDown = function(e) {
440
- if (e_target(e) != d.scrollbarV && e_target(e) != d.scrollbarH)
441
- operation(cm, onMouseDown)(e);
442
- };
443
- on(d.scrollbarV, "mousedown", barMouseDown);
444
- on(d.scrollbarH, "mousedown", barMouseDown);
439
+ if (!cm.state.checkedOverlayScrollbar && measure.clientHeight > 0) {
440
+ if (scrollbarWidth(d.measure) === 0) {
441
+ var w = mac && !mac_geMountainLion ? "12px" : "18px";
442
+ d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = w;
443
+ var barMouseDown = function(e) {
444
+ if (e_target(e) != d.scrollbarV && e_target(e) != d.scrollbarH)
445
+ operation(cm, onMouseDown)(e);
446
+ };
447
+ on(d.scrollbarV, "mousedown", barMouseDown);
448
+ on(d.scrollbarH, "mousedown", barMouseDown);
449
+ }
450
+ cm.state.checkedOverlayScrollbar = true;
445
451
  }
446
452
  }
447
453
 
@@ -503,9 +509,7 @@
503
509
  display.lineNumWidth = display.lineNumInnerWidth + padding;
504
510
  display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
505
511
  display.lineGutter.style.width = display.lineNumWidth + "px";
506
- var width = display.gutters.offsetWidth;
507
- display.scrollbarH.style.left = cm.options.fixedGutter ? width + "px" : 0;
508
- display.sizer.style.marginLeft = width + "px";
512
+ updateGutterSpace(cm);
509
513
  return true;
510
514
  }
511
515
  return false;
@@ -546,6 +550,8 @@
546
550
  updateSelection(cm);
547
551
  setDocumentHeight(cm, barMeasure);
548
552
  updateScrollbars(cm, barMeasure);
553
+ if (webkit && cm.options.lineWrapping)
554
+ checkForWebkitWidthBug(cm, barMeasure); // (Issue #2420)
549
555
  if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {
550
556
  forced = true;
551
557
  continue;
@@ -653,6 +659,16 @@
653
659
  cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px";
654
660
  }
655
661
 
662
+
663
+ function checkForWebkitWidthBug(cm, measure) {
664
+ // Work around Webkit bug where it sometimes reserves space for a
665
+ // non-existing phantom scrollbar in the scroller (Issue #2420)
666
+ if (cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.display.scroller.clientWidth - 1) {
667
+ cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = "0px";
668
+ cm.display.gutters.style.height = measure.docHeight + "px";
669
+ }
670
+ }
671
+
656
672
  // Read the actual heights of the rendered lines, and update their
657
673
  // stored heights to match.
658
674
  function updateHeightsInViewport(cm) {
@@ -1138,9 +1154,10 @@
1138
1154
 
1139
1155
  doc.sel = sel;
1140
1156
 
1141
- if (doc.cm)
1142
- doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
1143
- doc.cm.curOp.cursorActivity = true;
1157
+ if (doc.cm) {
1158
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
1159
+ signalCursorActivity(doc.cm);
1160
+ }
1144
1161
  signalLater(doc, "cursorActivity", doc);
1145
1162
  }
1146
1163
 
@@ -1229,9 +1246,9 @@
1229
1246
  var range = doc.sel.ranges[i];
1230
1247
  var collapsed = range.empty();
1231
1248
  if (collapsed || cm.options.showCursorWhenSelecting)
1232
- updateSelectionCursor(cm, range, curFragment);
1249
+ drawSelectionCursor(cm, range, curFragment);
1233
1250
  if (!collapsed)
1234
- updateSelectionRange(cm, range, selFragment);
1251
+ drawSelectionRange(cm, range, selFragment);
1235
1252
  }
1236
1253
 
1237
1254
  // Move the hidden textarea near the cursor to prevent scrolling artifacts
@@ -1251,7 +1268,7 @@
1251
1268
  }
1252
1269
 
1253
1270
  // Draws a cursor for the given range
1254
- function updateSelectionCursor(cm, range, output) {
1271
+ function drawSelectionCursor(cm, range, output) {
1255
1272
  var pos = cursorCoords(cm, range.head, "div");
1256
1273
 
1257
1274
  var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
@@ -1270,13 +1287,15 @@
1270
1287
  }
1271
1288
 
1272
1289
  // Draws the given range as a highlighted selection
1273
- function updateSelectionRange(cm, range, output) {
1290
+ function drawSelectionRange(cm, range, output) {
1274
1291
  var display = cm.display, doc = cm.doc;
1275
1292
  var fragment = document.createDocumentFragment();
1276
1293
  var padding = paddingH(cm.display), leftSide = padding.left, rightSide = display.lineSpace.offsetWidth - padding.right;
1277
1294
 
1278
1295
  function add(left, top, width, bottom) {
1279
1296
  if (top < 0) top = 0;
1297
+ top = Math.round(top);
1298
+ bottom = Math.round(bottom);
1280
1299
  fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
1281
1300
  "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
1282
1301
  "px; height: " + (bottom - top) + "px"));
@@ -1372,7 +1391,10 @@
1372
1391
  doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
1373
1392
  if (doc.frontier >= cm.display.viewFrom) { // Visible
1374
1393
  var oldStyles = line.styles;
1375
- line.styles = highlightLine(cm, line, state, true);
1394
+ var highlighted = highlightLine(cm, line, state, true);
1395
+ line.styles = highlighted.styles;
1396
+ if (highlighted.classes) line.styleClasses = highlighted.classes;
1397
+ else if (line.styleClasses) line.styleClasses = null;
1376
1398
  var ischange = !oldStyles || oldStyles.length != line.styles.length;
1377
1399
  for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
1378
1400
  if (ischange) regLineChange(cm, doc.frontier, "text");
@@ -1435,8 +1457,9 @@
1435
1457
  if (display.cachedPaddingH) return display.cachedPaddingH;
1436
1458
  var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
1437
1459
  var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
1438
- return display.cachedPaddingH = {left: parseInt(style.paddingLeft),
1439
- right: parseInt(style.paddingRight)};
1460
+ var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
1461
+ if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
1462
+ return data;
1440
1463
  }
1441
1464
 
1442
1465
  // Ensure the lineView.wrapping.heights array is populated. This is
@@ -1870,7 +1893,7 @@
1870
1893
  updateInput: null, // Whether to reset the input textarea
1871
1894
  typing: false, // Whether this reset should be careful to leave existing text (for compositing)
1872
1895
  changeObjs: null, // Accumulated changes, for firing change events
1873
- cursorActivity: false, // Whether to fire a cursorActivity event
1896
+ cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
1874
1897
  selectionChanged: false, // Whether the selection needs to be redrawn
1875
1898
  updateMaxLine: false, // Set when the widest line needs to be determined anew
1876
1899
  scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
@@ -1935,13 +1958,12 @@
1935
1958
  delayedCallbacks = null;
1936
1959
  }
1937
1960
  // Fire change events, and delayed event handlers
1938
- if (op.changeObjs) {
1939
- for (var i = 0; i < op.changeObjs.length; i++)
1940
- signal(cm, "change", cm, op.changeObjs[i]);
1961
+ if (op.changeObjs)
1941
1962
  signal(cm, "changes", cm, op.changeObjs);
1942
- }
1943
- if (op.cursorActivity) signal(cm, "cursorActivity", cm);
1944
1963
  if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
1964
+ if (op.cursorActivityHandlers)
1965
+ for (var i = 0; i < op.cursorActivityHandlers.length; i++)
1966
+ op.cursorActivityHandlers[i](cm);
1945
1967
  }
1946
1968
 
1947
1969
  // Run the given function in an operation
@@ -2204,7 +2226,13 @@
2204
2226
  // possible when it is clear that nothing happened. hasSelection
2205
2227
  // will be the case when there is a lot of text in the textarea,
2206
2228
  // in which case reading its value would be expensive.
2207
- if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false;
2229
+ if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput)
2230
+ return false;
2231
+ // See paste handler for more on the fakedLastChar kludge
2232
+ if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
2233
+ input.value = input.value.substring(0, input.value.length - 1);
2234
+ cm.state.fakedLastChar = false;
2235
+ }
2208
2236
  var text = input.value;
2209
2237
  // If nothing changed, bail.
2210
2238
  if (text == prevInput && !cm.somethingSelected()) return false;
@@ -2245,12 +2273,18 @@
2245
2273
  if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
2246
2274
  cm.options.smartIndent && range.head.ch < 100 &&
2247
2275
  (!i || doc.sel.ranges[i - 1].head.line != range.head.line)) {
2248
- var electric = cm.getModeAt(range.head).electricChars;
2249
- if (electric) for (var j = 0; j < electric.length; j++)
2250
- if (inserted.indexOf(electric.charAt(j)) > -1) {
2276
+ var mode = cm.getModeAt(range.head);
2277
+ if (mode.electricChars) {
2278
+ for (var j = 0; j < mode.electricChars.length; j++)
2279
+ if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
2280
+ indentLine(cm, range.head.line, "smart");
2281
+ break;
2282
+ }
2283
+ } else if (mode.electricInput) {
2284
+ var end = changeEnd(changeEvent);
2285
+ if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
2251
2286
  indentLine(cm, range.head.line, "smart");
2252
- break;
2253
- }
2287
+ }
2254
2288
  }
2255
2289
  }
2256
2290
  ensureCursorVisible(cm);
@@ -2398,21 +2432,48 @@
2398
2432
  fastPoll(cm);
2399
2433
  });
2400
2434
  on(d.input, "paste", function() {
2435
+ // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
2436
+ // Add a char to the end of textarea before paste occur so that
2437
+ // selection doesn't span to the end of textarea.
2438
+ if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
2439
+ var start = d.input.selectionStart, end = d.input.selectionEnd;
2440
+ d.input.value += "$";
2441
+ d.input.selectionStart = start;
2442
+ d.input.selectionEnd = end;
2443
+ cm.state.fakedLastChar = true;
2444
+ }
2401
2445
  cm.state.pasteIncoming = true;
2402
2446
  fastPoll(cm);
2403
2447
  });
2404
2448
 
2405
- function prepareCopy(e) {
2406
- if (d.inaccurateSelection) {
2407
- d.prevInput = "";
2408
- d.inaccurateSelection = false;
2409
- d.input.value = cm.getSelection();
2410
- selectInput(d.input);
2449
+ function prepareCopyCut(e) {
2450
+ if (cm.somethingSelected()) {
2451
+ if (d.inaccurateSelection) {
2452
+ d.prevInput = "";
2453
+ d.inaccurateSelection = false;
2454
+ d.input.value = cm.getSelection();
2455
+ selectInput(d.input);
2456
+ }
2457
+ } else {
2458
+ var text = "", ranges = [];
2459
+ for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
2460
+ var line = cm.doc.sel.ranges[i].head.line;
2461
+ var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
2462
+ ranges.push(lineRange);
2463
+ text += cm.getRange(lineRange.anchor, lineRange.head);
2464
+ }
2465
+ if (e.type == "cut") {
2466
+ cm.setSelections(ranges, null, sel_dontScroll);
2467
+ } else {
2468
+ d.prevInput = "";
2469
+ d.input.value = text;
2470
+ selectInput(d.input);
2471
+ }
2411
2472
  }
2412
2473
  if (e.type == "cut") cm.state.cutIncoming = true;
2413
2474
  }
2414
- on(d.input, "cut", prepareCopy);
2415
- on(d.input, "copy", prepareCopy);
2475
+ on(d.input, "cut", prepareCopyCut);
2476
+ on(d.input, "copy", prepareCopyCut);
2416
2477
 
2417
2478
  // Needed to handle Tab key in KHTML
2418
2479
  if (khtml) on(d.sizer, "mouseup", function() {
@@ -2449,7 +2510,7 @@
2449
2510
  var coords = coordsChar(cm, x, y), line;
2450
2511
  if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
2451
2512
  var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
2452
- coords = Pos(coords.line, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff);
2513
+ coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
2453
2514
  }
2454
2515
  return coords;
2455
2516
  }
@@ -2552,7 +2613,7 @@
2552
2613
  e_preventDefault(e);
2553
2614
 
2554
2615
  var ourRange, ourIndex, startSel = doc.sel;
2555
- if (addNew) {
2616
+ if (addNew && !e.shiftKey) {
2556
2617
  ourIndex = doc.sel.contains(start);
2557
2618
  if (ourIndex > -1)
2558
2619
  ourRange = doc.sel.ranges[ourIndex];
@@ -2586,6 +2647,7 @@
2586
2647
  if (!addNew) {
2587
2648
  ourIndex = 0;
2588
2649
  setSelection(doc, new Selection([ourRange], 0), sel_mouse);
2650
+ startSel = doc.sel;
2589
2651
  } else if (ourIndex > -1) {
2590
2652
  replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
2591
2653
  } else {
@@ -2719,7 +2781,7 @@
2719
2781
  if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
2720
2782
  return;
2721
2783
  e_preventDefault(e);
2722
- if (ie_upto10) lastDrop = +new Date;
2784
+ if (ie) lastDrop = +new Date;
2723
2785
  var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
2724
2786
  if (!pos || isReadOnly(cm)) return;
2725
2787
  // Might be a file drop, in which case we simply extract the text
@@ -2728,7 +2790,7 @@
2728
2790
  var n = files.length, text = Array(n), read = 0;
2729
2791
  var loadFile = function(file, i) {
2730
2792
  var reader = new FileReader;
2731
- reader.onload = function() {
2793
+ reader.onload = operation(cm, function() {
2732
2794
  text[i] = reader.result;
2733
2795
  if (++read == n) {
2734
2796
  pos = clipPos(cm.doc, pos);
@@ -2736,7 +2798,7 @@
2736
2798
  makeChange(cm.doc, change);
2737
2799
  setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
2738
2800
  }
2739
- };
2801
+ });
2740
2802
  reader.readAsText(file);
2741
2803
  };
2742
2804
  for (var i = 0; i < n; ++i) loadFile(files[i], i);
@@ -2764,7 +2826,7 @@
2764
2826
  }
2765
2827
 
2766
2828
  function onDragStart(cm, e) {
2767
- if (ie_upto10 && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
2829
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
2768
2830
  if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
2769
2831
 
2770
2832
  e.dataTransfer.setData("Text", cm.getSelection());
@@ -2999,6 +3061,25 @@
2999
3061
  if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
3000
3062
  cm.replaceSelection("", null, "cut");
3001
3063
  }
3064
+
3065
+ // Turn mouse into crosshair when Alt is held on Mac.
3066
+ if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
3067
+ showCrossHair(cm);
3068
+ }
3069
+
3070
+ function showCrossHair(cm) {
3071
+ var lineDiv = cm.display.lineDiv;
3072
+ addClass(lineDiv, "CodeMirror-crosshair");
3073
+
3074
+ function up(e) {
3075
+ if (e.keyCode == 18 || !e.altKey) {
3076
+ rmClass(lineDiv, "CodeMirror-crosshair");
3077
+ off(document, "keyup", up);
3078
+ off(document, "mouseover", up);
3079
+ }
3080
+ }
3081
+ on(document, "keyup", up);
3082
+ on(document, "mouseover", up);
3002
3083
  }
3003
3084
 
3004
3085
  function onKeyUp(e) {
@@ -3025,9 +3106,11 @@
3025
3106
  if (!cm.state.focused) {
3026
3107
  signal(cm, "focus", cm);
3027
3108
  cm.state.focused = true;
3028
- if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
3029
- cm.display.wrapper.className += " CodeMirror-focused";
3030
- if (!cm.curOp) {
3109
+ addClass(cm.display.wrapper, "CodeMirror-focused");
3110
+ // The prevInput test prevents this from firing when a context
3111
+ // menu is closed (since the resetInput would kill the
3112
+ // select-all detection hack)
3113
+ if (!cm.curOp && cm.display.selForContextMenu == cm.doc.sel) {
3031
3114
  resetInput(cm);
3032
3115
  if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
3033
3116
  }
@@ -3039,7 +3122,7 @@
3039
3122
  if (cm.state.focused) {
3040
3123
  signal(cm, "blur", cm);
3041
3124
  cm.state.focused = false;
3042
- cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
3125
+ rmClass(cm.display.wrapper, "CodeMirror-focused");
3043
3126
  }
3044
3127
  clearInterval(cm.display.blinker);
3045
3128
  setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
@@ -3075,14 +3158,16 @@
3075
3158
  resetInput(cm);
3076
3159
  // Adds "Select all" to context menu in FF
3077
3160
  if (!cm.somethingSelected()) display.input.value = display.prevInput = " ";
3161
+ display.selForContextMenu = cm.doc.sel;
3078
3162
 
3079
3163
  // Select-all will be greyed out if there's nothing to select, so
3080
3164
  // this adds a zero-width space so that we can later check whether
3081
3165
  // it got selected.
3082
3166
  function prepareSelectAllHack() {
3083
3167
  if (display.input.selectionStart != null) {
3084
- var extval = display.input.value = "\u200b" + (cm.somethingSelected() ? display.input.value : "");
3085
- display.prevInput = "\u200b";
3168
+ var selected = cm.somethingSelected();
3169
+ var extval = display.input.value = "\u200b" + (selected ? display.input.value : "");
3170
+ display.prevInput = selected ? "" : "\u200b";
3086
3171
  display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
3087
3172
  }
3088
3173
  }
@@ -3096,8 +3181,8 @@
3096
3181
  if (display.input.selectionStart != null) {
3097
3182
  if (!ie || ie_upto8) prepareSelectAllHack();
3098
3183
  clearTimeout(detectingSelectAll);
3099
- var i = 0, poll = function(){
3100
- if (display.prevInput == "\u200b" && display.input.selectionStart == 0)
3184
+ var i = 0, poll = function() {
3185
+ if (display.selForContextMenu == cm.doc.sel && display.input.selectionStart == 0)
3101
3186
  operation(cm, commands.selectAll)(cm);
3102
3187
  else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
3103
3188
  else resetInput(cm);
@@ -3373,7 +3458,7 @@
3373
3458
  }
3374
3459
 
3375
3460
  if (doc.sel.contains(change.from, change.to) > -1)
3376
- cm.curOp.cursorActivity = true;
3461
+ signalCursorActivity(cm);
3377
3462
 
3378
3463
  updateDoc(doc, change, spans, estimateHeight(cm));
3379
3464
 
@@ -3401,13 +3486,17 @@
3401
3486
  else
3402
3487
  regChange(cm, from.line, to.line + 1, lendiff);
3403
3488
 
3404
- if (hasHandler(cm, "change") || hasHandler(cm, "changes"))
3405
- (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push({
3489
+ var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
3490
+ if (changeHandler || changesHandler) {
3491
+ var obj = {
3406
3492
  from: from, to: to,
3407
3493
  text: change.text,
3408
3494
  removed: change.removed,
3409
3495
  origin: change.origin
3410
- });
3496
+ };
3497
+ if (changeHandler) signalLater(cm, "change", cm, obj);
3498
+ if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
3499
+ }
3411
3500
  }
3412
3501
 
3413
3502
  function replaceRange(doc, code, from, to, origin) {
@@ -3613,7 +3702,6 @@
3613
3702
  else no = lineNo(handle);
3614
3703
  if (no == null) return null;
3615
3704
  if (op(line, no)) regLineChange(cm, no, changeType);
3616
- else return null;
3617
3705
  return line;
3618
3706
  }
3619
3707
 
@@ -3826,7 +3914,7 @@
3826
3914
  var stream = new StringStream(line.text, this.options.tabSize);
3827
3915
  while (stream.pos < pos.ch && !stream.eol()) {
3828
3916
  stream.start = stream.pos;
3829
- var style = mode.token(stream, state);
3917
+ var style = readToken(mode, stream, state);
3830
3918
  }
3831
3919
  return {start: stream.start,
3832
3920
  end: stream.pos,
@@ -3839,13 +3927,16 @@
3839
3927
  pos = clipPos(this.doc, pos);
3840
3928
  var styles = getLineStyles(this, getLine(this.doc, pos.line));
3841
3929
  var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
3842
- if (ch == 0) return styles[2];
3843
- for (;;) {
3930
+ var type;
3931
+ if (ch == 0) type = styles[2];
3932
+ else for (;;) {
3844
3933
  var mid = (before + after) >> 1;
3845
3934
  if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
3846
3935
  else if (styles[mid * 2 + 1] < ch) before = mid + 1;
3847
- else return styles[mid * 2 + 2];
3936
+ else { type = styles[mid * 2 + 2]; break; }
3848
3937
  }
3938
+ var cut = type ? type.indexOf("cm-overlay ") : -1;
3939
+ return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);
3849
3940
  },
3850
3941
 
3851
3942
  getModeAt: function(pos) {
@@ -4098,9 +4189,9 @@
4098
4189
  toggleOverwrite: function(value) {
4099
4190
  if (value != null && value == this.state.overwrite) return;
4100
4191
  if (this.state.overwrite = !this.state.overwrite)
4101
- this.display.cursorDiv.className += " CodeMirror-overwrite";
4192
+ addClass(this.display.cursorDiv, "CodeMirror-overwrite");
4102
4193
  else
4103
- this.display.cursorDiv.className = this.display.cursorDiv.className.replace(" CodeMirror-overwrite", "");
4194
+ rmClass(this.display.cursorDiv, "CodeMirror-overwrite");
4104
4195
 
4105
4196
  signal(this, "overwriteToggle", this, this.state.overwrite);
4106
4197
  },
@@ -4158,8 +4249,10 @@
4158
4249
  refresh: methodOp(function() {
4159
4250
  var oldHeight = this.display.cachedTextHeight;
4160
4251
  regChange(this);
4252
+ this.curOp.forceUpdate = true;
4161
4253
  clearCaches(this);
4162
4254
  this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
4255
+ updateGutterSpace(this);
4163
4256
  if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
4164
4257
  estimateLineHeights(this);
4165
4258
  signal(this, "refresh", this);
@@ -4510,6 +4603,15 @@
4510
4603
  indentMore: function(cm) {cm.indentSelection("add");},
4511
4604
  indentLess: function(cm) {cm.indentSelection("subtract");},
4512
4605
  insertTab: function(cm) {cm.replaceSelection("\t");},
4606
+ insertSoftTab: function(cm) {
4607
+ var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
4608
+ for (var i = 0; i < ranges.length; i++) {
4609
+ var pos = ranges[i].from();
4610
+ var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
4611
+ spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
4612
+ }
4613
+ cm.replaceSelections(spaces);
4614
+ },
4513
4615
  defaultTab: function(cm) {
4514
4616
  if (cm.somethingSelected()) cm.indentSelection("add");
4515
4617
  else cm.execCommand("insertTab");
@@ -4826,6 +4928,7 @@
4826
4928
  }
4827
4929
  if (cm) signalLater(cm, "markerCleared", cm, this);
4828
4930
  if (withOp) endOperation(cm);
4931
+ if (this.parent) this.parent.clear();
4829
4932
  };
4830
4933
 
4831
4934
  // Find the position of the marker in the document. Returns a {from,
@@ -4905,7 +5008,7 @@
4905
5008
  if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
4906
5009
 
4907
5010
  var marker = new TextMarker(doc, type), diff = cmp(from, to);
4908
- if (options) copyObj(options, marker);
5011
+ if (options) copyObj(options, marker, false);
4909
5012
  // Don't connect empty markers unless clearWhenEmpty is false
4910
5013
  if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
4911
5014
  return marker;
@@ -4973,10 +5076,8 @@
4973
5076
  var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
4974
5077
  this.markers = markers;
4975
5078
  this.primary = primary;
4976
- for (var i = 0, me = this; i < markers.length; ++i) {
5079
+ for (var i = 0; i < markers.length; ++i)
4977
5080
  markers[i].parent = this;
4978
- on(markers[i], "clear", function(){me.clear();});
4979
- }
4980
5081
  };
4981
5082
  eventMixin(SharedTextMarker);
4982
5083
 
@@ -5006,6 +5107,37 @@
5006
5107
  return new SharedTextMarker(markers, primary);
5007
5108
  }
5008
5109
 
5110
+ function findSharedMarkers(doc) {
5111
+ return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),
5112
+ function(m) { return m.parent; });
5113
+ }
5114
+
5115
+ function copySharedMarkers(doc, markers) {
5116
+ for (var i = 0; i < markers.length; i++) {
5117
+ var marker = markers[i], pos = marker.find();
5118
+ var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
5119
+ if (cmp(mFrom, mTo)) {
5120
+ var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
5121
+ marker.markers.push(subMark);
5122
+ subMark.parent = marker;
5123
+ }
5124
+ }
5125
+ }
5126
+
5127
+ function detachSharedMarkers(markers) {
5128
+ for (var i = 0; i < markers.length; i++) {
5129
+ var marker = markers[i], linked = [marker.primary.doc];;
5130
+ linkedDocs(marker.primary.doc, function(d) { linked.push(d); });
5131
+ for (var j = 0; j < marker.markers.length; j++) {
5132
+ var subMarker = marker.markers[j];
5133
+ if (indexOf(linked, subMarker.doc) == -1) {
5134
+ subMarker.parent = null;
5135
+ marker.markers.splice(j--, 1);
5136
+ }
5137
+ }
5138
+ }
5139
+ }
5140
+
5009
5141
  // TEXTMARKER SPANS
5010
5142
 
5011
5143
  function MarkedSpan(marker, from, to) {
@@ -5430,13 +5562,41 @@
5430
5562
  detachMarkedSpans(line);
5431
5563
  }
5432
5564
 
5565
+ function extractLineClasses(type, output) {
5566
+ if (type) for (;;) {
5567
+ var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
5568
+ if (!lineClass) break;
5569
+ type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
5570
+ var prop = lineClass[1] ? "bgClass" : "textClass";
5571
+ if (output[prop] == null)
5572
+ output[prop] = lineClass[2];
5573
+ else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
5574
+ output[prop] += " " + lineClass[2];
5575
+ }
5576
+ return type;
5577
+ }
5578
+
5579
+ function callBlankLine(mode, state) {
5580
+ if (mode.blankLine) return mode.blankLine(state);
5581
+ if (!mode.innerMode) return;
5582
+ var inner = CodeMirror.innerMode(mode, state);
5583
+ if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
5584
+ }
5585
+
5586
+ function readToken(mode, stream, state) {
5587
+ var style = mode.token(stream, state);
5588
+ if (stream.pos <= stream.start)
5589
+ throw new Error("Mode " + mode.name + " failed to advance stream.");
5590
+ return style;
5591
+ }
5592
+
5433
5593
  // Run the given mode's parser over a line, calling f for each token.
5434
- function runMode(cm, text, mode, state, f, forceToEnd) {
5594
+ function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
5435
5595
  var flattenSpans = mode.flattenSpans;
5436
5596
  if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
5437
5597
  var curStart = 0, curStyle = null;
5438
5598
  var stream = new StringStream(text, cm.options.tabSize), style;
5439
- if (text == "" && mode.blankLine) mode.blankLine(state);
5599
+ if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
5440
5600
  while (!stream.eol()) {
5441
5601
  if (stream.pos > cm.options.maxHighlightLength) {
5442
5602
  flattenSpans = false;
@@ -5444,7 +5604,7 @@
5444
5604
  stream.pos = text.length;
5445
5605
  style = null;
5446
5606
  } else {
5447
- style = mode.token(stream, state);
5607
+ style = extractLineClasses(readToken(mode, stream, state), lineClasses);
5448
5608
  }
5449
5609
  if (cm.options.addModeClass) {
5450
5610
  var mName = CodeMirror.innerMode(mode, state).mode.name;
@@ -5471,11 +5631,11 @@
5471
5631
  function highlightLine(cm, line, state, forceToEnd) {
5472
5632
  // A styles array always starts with a number identifying the
5473
5633
  // mode/overlays that it is based on (for easy invalidation).
5474
- var st = [cm.state.modeGen];
5634
+ var st = [cm.state.modeGen], lineClasses = {};
5475
5635
  // Compute the base array of styles
5476
5636
  runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
5477
5637
  st.push(end, style);
5478
- }, forceToEnd);
5638
+ }, lineClasses, forceToEnd);
5479
5639
 
5480
5640
  // Run overlays, adjust style array.
5481
5641
  for (var o = 0; o < cm.state.overlays.length; ++o) {
@@ -5492,23 +5652,27 @@
5492
5652
  }
5493
5653
  if (!style) return;
5494
5654
  if (overlay.opaque) {
5495
- st.splice(start, i - start, end, style);
5655
+ st.splice(start, i - start, end, "cm-overlay " + style);
5496
5656
  i = start + 2;
5497
5657
  } else {
5498
5658
  for (; start < i; start += 2) {
5499
5659
  var cur = st[start+1];
5500
- st[start+1] = cur ? cur + " " + style : style;
5660
+ st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;
5501
5661
  }
5502
5662
  }
5503
- });
5663
+ }, lineClasses);
5504
5664
  }
5505
5665
 
5506
- return st;
5666
+ return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
5507
5667
  }
5508
5668
 
5509
5669
  function getLineStyles(cm, line) {
5510
- if (!line.styles || line.styles[0] != cm.state.modeGen)
5511
- line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
5670
+ if (!line.styles || line.styles[0] != cm.state.modeGen) {
5671
+ var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
5672
+ line.styles = result.styles;
5673
+ if (result.classes) line.styleClasses = result.classes;
5674
+ else if (line.styleClasses) line.styleClasses = null;
5675
+ }
5512
5676
  return line.styles;
5513
5677
  }
5514
5678
 
@@ -5519,9 +5683,9 @@
5519
5683
  var mode = cm.doc.mode;
5520
5684
  var stream = new StringStream(text, cm.options.tabSize);
5521
5685
  stream.start = stream.pos = startAt || 0;
5522
- if (text == "" && mode.blankLine) mode.blankLine(state);
5686
+ if (text == "") callBlankLine(mode, state);
5523
5687
  while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
5524
- mode.token(stream, state);
5688
+ readToken(mode, stream, state);
5525
5689
  stream.start = stream.pos;
5526
5690
  }
5527
5691
  }
@@ -5530,20 +5694,9 @@
5530
5694
  // containing one or more styles) to a CSS style. This is cached,
5531
5695
  // and also looks for line-wide styles.
5532
5696
  var styleToClassCache = {}, styleToClassCacheWithMode = {};
5533
- function interpretTokenStyle(style, builder) {
5534
- if (!style) return null;
5535
- for (;;) {
5536
- var lineClass = style.match(/(?:^|\s+)line-(background-)?(\S+)/);
5537
- if (!lineClass) break;
5538
- style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length);
5539
- var prop = lineClass[1] ? "bgClass" : "textClass";
5540
- if (builder[prop] == null)
5541
- builder[prop] = lineClass[2];
5542
- else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop]))
5543
- builder[prop] += " " + lineClass[2];
5544
- }
5545
- if (/^\s*$/.test(style)) return null;
5546
- var cache = builder.cm.options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
5697
+ function interpretTokenStyle(style, options) {
5698
+ if (!style || /^\s*$/.test(style)) return null;
5699
+ var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
5547
5700
  return cache[style] ||
5548
5701
  (cache[style] = style.replace(/\S+/g, "cm-$&"));
5549
5702
  }
@@ -5574,6 +5727,12 @@
5574
5727
  builder.addToken = buildTokenBadBidi(builder.addToken, order);
5575
5728
  builder.map = [];
5576
5729
  insertLineContent(line, builder, getLineStyles(cm, line));
5730
+ if (line.styleClasses) {
5731
+ if (line.styleClasses.bgClass)
5732
+ builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
5733
+ if (line.styleClasses.textClass)
5734
+ builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");
5735
+ }
5577
5736
 
5578
5737
  // Ensure at least a single node is present, for measuring.
5579
5738
  if (builder.map.length == 0)
@@ -5699,7 +5858,7 @@
5699
5858
  var spans = line.markedSpans, allText = line.text, at = 0;
5700
5859
  if (!spans) {
5701
5860
  for (var i = 1; i < styles.length; i+=2)
5702
- builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder));
5861
+ builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));
5703
5862
  return;
5704
5863
  }
5705
5864
 
@@ -5749,7 +5908,7 @@
5749
5908
  spanStartStyle = "";
5750
5909
  }
5751
5910
  text = allText.slice(at, at = styles[i++]);
5752
- style = interpretTokenStyle(styles[i++], builder);
5911
+ style = interpretTokenStyle(styles[i++], builder.cm.options);
5753
5912
  }
5754
5913
  }
5755
5914
  }
@@ -6101,13 +6260,13 @@
6101
6260
  }
6102
6261
  return parts;
6103
6262
  },
6104
- replaceSelection: docMethodOp(function(code, collapse, origin) {
6263
+ replaceSelection: function(code, collapse, origin) {
6105
6264
  var dup = [];
6106
6265
  for (var i = 0; i < this.sel.ranges.length; i++)
6107
6266
  dup[i] = code;
6108
6267
  this.replaceSelections(dup, collapse, origin || "+input");
6109
- }),
6110
- replaceSelections: function(code, collapse, origin) {
6268
+ },
6269
+ replaceSelections: docMethodOp(function(code, collapse, origin) {
6111
6270
  var changes = [], sel = this.sel;
6112
6271
  for (var i = 0; i < sel.ranges.length; i++) {
6113
6272
  var range = sel.ranges[i];
@@ -6118,7 +6277,7 @@
6118
6277
  makeChange(this, changes[i]);
6119
6278
  if (newSel) setSelectionReplaceHistory(this, newSel);
6120
6279
  else if (this.cm) ensureCursorVisible(this.cm);
6121
- },
6280
+ }),
6122
6281
  undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
6123
6282
  redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
6124
6283
  undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
@@ -6178,7 +6337,7 @@
6178
6337
  }
6179
6338
  return markers;
6180
6339
  },
6181
- findMarks: function(from, to) {
6340
+ findMarks: function(from, to, filter) {
6182
6341
  from = clipPos(this, from); to = clipPos(this, to);
6183
6342
  var found = [], lineNo = from.line;
6184
6343
  this.iter(from.line, to.line + 1, function(line) {
@@ -6187,7 +6346,8 @@
6187
6346
  var span = spans[i];
6188
6347
  if (!(lineNo == from.line && from.ch > span.to ||
6189
6348
  span.from == null && lineNo != from.line||
6190
- lineNo == to.line && span.from > to.ch))
6349
+ lineNo == to.line && span.from > to.ch) &&
6350
+ (!filter || filter(span.marker)))
6191
6351
  found.push(span.marker.parent || span.marker);
6192
6352
  }
6193
6353
  ++lineNo;
@@ -6245,6 +6405,7 @@
6245
6405
  if (options.sharedHist) copy.history = this.history;
6246
6406
  (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
6247
6407
  copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
6408
+ copySharedMarkers(copy, findSharedMarkers(this));
6248
6409
  return copy;
6249
6410
  },
6250
6411
  unlinkDoc: function(other) {
@@ -6254,6 +6415,7 @@
6254
6415
  if (link.doc != other) continue;
6255
6416
  this.linked.splice(i, 1);
6256
6417
  other.unlinkDoc(this);
6418
+ detachSharedMarkers(findSharedMarkers(this));
6257
6419
  break;
6258
6420
  }
6259
6421
  // If the histories were shared, split them again
@@ -6765,6 +6927,14 @@
6765
6927
  return e_defaultPrevented(e) || e.codemirrorIgnore;
6766
6928
  }
6767
6929
 
6930
+ function signalCursorActivity(cm) {
6931
+ var arr = cm._handlers && cm._handlers.cursorActivity;
6932
+ if (!arr) return;
6933
+ var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
6934
+ for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
6935
+ set.push(arr[i]);
6936
+ }
6937
+
6768
6938
  function hasHandler(emitter, type) {
6769
6939
  var arr = emitter._handlers && emitter._handlers[type];
6770
6940
  return arr && arr.length > 0;
@@ -6869,9 +7039,11 @@
6869
7039
  return inst;
6870
7040
  };
6871
7041
 
6872
- function copyObj(obj, target) {
7042
+ function copyObj(obj, target, overwrite) {
6873
7043
  if (!target) target = {};
6874
- for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
7044
+ for (var prop in obj)
7045
+ if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
7046
+ target[prop] = obj[prop];
6875
7047
  return target;
6876
7048
  }
6877
7049
 
@@ -6951,6 +7123,21 @@
6951
7123
  catch(e) { return document.body; }
6952
7124
  };
6953
7125
 
7126
+ function classTest(cls) { return new RegExp("\\b" + cls + "\\b\\s*"); }
7127
+ function rmClass(node, cls) {
7128
+ var test = classTest(cls);
7129
+ if (test.test(node.className)) node.className = node.className.replace(test, "");
7130
+ }
7131
+ function addClass(node, cls) {
7132
+ if (!classTest(cls).test(node.className)) node.className += " " + cls;
7133
+ }
7134
+ function joinClasses(a, b) {
7135
+ var as = a.split(" ");
7136
+ for (var i = 0; i < as.length; i++)
7137
+ if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
7138
+ return b;
7139
+ }
7140
+
6954
7141
  // FEATURE DETECTION
6955
7142
 
6956
7143
  // Detect drag-and-drop
@@ -7333,7 +7520,7 @@
7333
7520
 
7334
7521
  // THE END
7335
7522
 
7336
- CodeMirror.version = "4.0.3";
7523
+ CodeMirror.version = "4.1.0";
7337
7524
 
7338
7525
  return CodeMirror;
7339
7526
  });