codemirror-rails 3.02 → 3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/codemirror-rails.gemspec +1 -0
- data/doc/CodeMirror-LICENSE +5 -1
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror/{utils → addons/dialog}/dialog.js +4 -0
- data/vendor/assets/javascripts/codemirror/addons/display/placeholder.js +54 -0
- data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +54 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/edit}/closetag.js +9 -8
- data/vendor/assets/javascripts/codemirror/{utils → addons/edit}/continuecomment.js +12 -4
- data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +25 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/edit}/matchbrackets.js +30 -11
- data/vendor/assets/javascripts/codemirror/addons/fold/brace-fold.js +31 -0
- data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +32 -0
- data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +11 -0
- data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +64 -0
- data/vendor/assets/javascripts/codemirror/addons/hint/html-hint.js +582 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/hint}/javascript-hint.js +15 -11
- data/vendor/assets/javascripts/codemirror/{utils → addons/hint}/pig-hint.js +19 -19
- data/vendor/assets/javascripts/codemirror/{utils → addons/hint}/python-hint.js +2 -2
- data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +180 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/hint}/xml-hint.js +5 -18
- data/vendor/assets/javascripts/codemirror/addons/lint/javascript-lint.js +127 -0
- data/vendor/assets/javascripts/codemirror/addons/lint/json-lint.js +14 -0
- data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +197 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/mode}/loadmode.js +0 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/mode}/multiplex.js +2 -2
- data/vendor/assets/javascripts/codemirror/{utils → addons/mode}/overlay.js +2 -2
- data/vendor/assets/javascripts/codemirror/{utils → addons/runmode}/colorize.js +0 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/runmode}/runmode-standalone.js +2 -3
- data/vendor/assets/javascripts/codemirror/{utils → addons/runmode}/runmode.js +0 -0
- data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +89 -0
- data/vendor/assets/javascripts/codemirror/addons/search/match-highlighter.js +60 -0
- data/vendor/assets/javascripts/codemirror/{utils → addons/search}/search.js +5 -5
- data/vendor/assets/javascripts/codemirror/{utils → addons/search}/searchcursor.js +37 -30
- data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +39 -0
- data/vendor/assets/javascripts/codemirror/addons/selection/mark-selection.js +34 -0
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +721 -188
- data/vendor/assets/javascripts/codemirror/modes/asterisk.js +6 -6
- data/vendor/assets/javascripts/codemirror/modes/clike.js +14 -14
- data/vendor/assets/javascripts/codemirror/modes/clojure.js +23 -7
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/css.js +337 -235
- data/vendor/assets/javascripts/codemirror/modes/ecl.js +12 -12
- data/vendor/assets/javascripts/codemirror/modes/erlang.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/gas.js +326 -0
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +1 -0
- data/vendor/assets/javascripts/codemirror/modes/haskell.js +26 -26
- data/vendor/assets/javascripts/codemirror/modes/haxe.js +17 -17
- data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +6 -6
- data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +43 -23
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +78 -33
- data/vendor/assets/javascripts/codemirror/modes/jinja2.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/less.js +38 -38
- data/vendor/assets/javascripts/codemirror/modes/livescript.js +267 -0
- data/vendor/assets/javascripts/codemirror/modes/lua.js +7 -7
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +108 -57
- data/vendor/assets/javascripts/codemirror/modes/mirc.js +177 -0
- data/vendor/assets/javascripts/codemirror/modes/ntriples.js +22 -22
- data/vendor/assets/javascripts/codemirror/modes/ocaml.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/perl.js +791 -791
- data/vendor/assets/javascripts/codemirror/modes/php.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/pig.js +163 -163
- data/vendor/assets/javascripts/codemirror/modes/python.js +31 -31
- data/vendor/assets/javascripts/codemirror/modes/q.js +124 -0
- data/vendor/assets/javascripts/codemirror/modes/rst.js +486 -250
- data/vendor/assets/javascripts/codemirror/modes/sass.js +3 -3
- data/vendor/assets/javascripts/codemirror/modes/scss_test.js +80 -0
- data/vendor/assets/javascripts/codemirror/modes/shell.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/sieve.js +10 -10
- data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +129 -129
- data/vendor/assets/javascripts/codemirror/modes/smarty.js +3 -3
- data/vendor/assets/javascripts/codemirror/modes/sparql.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/sql.js +23 -23
- data/vendor/assets/javascripts/codemirror/modes/stex.js +192 -121
- data/vendor/assets/javascripts/codemirror/modes/tcl.js +131 -0
- data/vendor/assets/javascripts/codemirror/modes/test.js +64 -0
- data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +345 -345
- data/vendor/assets/javascripts/codemirror/modes/tiki.js +297 -298
- data/vendor/assets/javascripts/codemirror/modes/turtle.js +145 -0
- data/vendor/assets/javascripts/codemirror/modes/vb.js +31 -32
- data/vendor/assets/javascripts/codemirror/modes/vbscript.js +4 -4
- data/vendor/assets/javascripts/codemirror/modes/xml.js +10 -6
- data/vendor/assets/javascripts/codemirror/modes/xquery.js +55 -55
- data/vendor/assets/javascripts/codemirror/modes/yaml.js +90 -90
- data/vendor/assets/javascripts/codemirror/modes/z80.js +82 -110
- data/vendor/assets/javascripts/codemirror.js +1914 -1115
- data/vendor/assets/stylesheets/codemirror/{utils → addons/dialog}/dialog.css +0 -0
- data/vendor/assets/stylesheets/codemirror/addons/hint/show-hint.css +38 -0
- data/vendor/assets/stylesheets/codemirror/addons/lint/lint.css +96 -0
- data/vendor/assets/stylesheets/codemirror/modes/tiki.css +2 -2
- data/vendor/assets/stylesheets/codemirror/themes/ambiance-mobile.css +0 -1
- data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +0 -1
- data/vendor/assets/stylesheets/codemirror/themes/eclipse.css +2 -2
- data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +5 -5
- data/vendor/assets/stylesheets/codemirror/themes/midnight.css +52 -0
- data/vendor/assets/stylesheets/codemirror/themes/xq-light.css +43 -0
- data/vendor/assets/stylesheets/codemirror.css +16 -10
- metadata +60 -52
- data/vendor/assets/javascripts/codemirror/modes/mysql.js +0 -203
- data/vendor/assets/javascripts/codemirror/modes/plsql.js +0 -216
- data/vendor/assets/javascripts/codemirror/utils/collapserange.js +0 -68
- data/vendor/assets/javascripts/codemirror/utils/continuelist.js +0 -28
- data/vendor/assets/javascripts/codemirror/utils/foldcode.js +0 -183
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +0 -114
- data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +0 -46
- data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +0 -102
- data/vendor/assets/stylesheets/codemirror/utils/simple-hint.css +0 -16
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CodeMirror version 3.
|
|
1
|
+
// CodeMirror version 3.12
|
|
2
2
|
//
|
|
3
3
|
// CodeMirror is the only global var we claim
|
|
4
4
|
window.CodeMirror = (function() {
|
|
@@ -32,6 +32,7 @@ window.CodeMirror = (function() {
|
|
|
32
32
|
if (opera_version) opera_version = Number(opera_version[1]);
|
|
33
33
|
// Some browsers use the wrong event properties to signal cmd/ctrl on OS X
|
|
34
34
|
var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
|
|
35
|
+
var captureMiddleClick = gecko || (ie && !ie_lt9);
|
|
35
36
|
|
|
36
37
|
// Optimize some code when these features are not used
|
|
37
38
|
var sawReadOnlySpans = false, sawCollapsedSpans = false;
|
|
@@ -40,31 +41,38 @@ window.CodeMirror = (function() {
|
|
|
40
41
|
|
|
41
42
|
function CodeMirror(place, options) {
|
|
42
43
|
if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
|
|
43
|
-
|
|
44
|
+
|
|
44
45
|
this.options = options = options || {};
|
|
45
46
|
// Determine effective options based on given values and defaults.
|
|
46
47
|
for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
|
|
47
48
|
options[opt] = defaults[opt];
|
|
48
49
|
setGuttersForLineNumbers(options);
|
|
49
50
|
|
|
50
|
-
var
|
|
51
|
+
var docStart = typeof options.value == "string" ? 0 : options.value.first;
|
|
52
|
+
var display = this.display = makeDisplay(place, docStart);
|
|
51
53
|
display.wrapper.CodeMirror = this;
|
|
52
54
|
updateGutters(this);
|
|
53
55
|
if (options.autofocus && !mobile) focusInput(this);
|
|
54
56
|
|
|
55
|
-
this.
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
this.state = {keyMaps: [],
|
|
58
|
+
overlays: [],
|
|
59
|
+
modeGen: 0,
|
|
60
|
+
overwrite: false, focused: false,
|
|
61
|
+
suppressEdits: false, pasteIncoming: false,
|
|
62
|
+
draggingText: false,
|
|
63
|
+
highlight: new Delayed()};
|
|
64
|
+
|
|
58
65
|
themeChanged(this);
|
|
59
66
|
if (options.lineWrapping)
|
|
60
67
|
this.display.wrapper.className += " CodeMirror-wrap";
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
var doc = options.value;
|
|
70
|
+
if (typeof doc == "string") doc = new Doc(options.value, options.mode);
|
|
71
|
+
operation(this, attachDoc)(this, doc);
|
|
72
|
+
|
|
64
73
|
// Override magic textarea content restore that IE sometimes does
|
|
65
74
|
// on our hidden textarea on reload
|
|
66
75
|
if (ie) setTimeout(bind(resetInput, this, true), 20);
|
|
67
|
-
this.view.history = makeHistory();
|
|
68
76
|
|
|
69
77
|
registerEventHandlers(this);
|
|
70
78
|
// IE throws unspecified error in certain cases, when
|
|
@@ -83,12 +91,16 @@ window.CodeMirror = (function() {
|
|
|
83
91
|
|
|
84
92
|
// DISPLAY CONSTRUCTOR
|
|
85
93
|
|
|
86
|
-
function makeDisplay(place) {
|
|
94
|
+
function makeDisplay(place, docStart) {
|
|
87
95
|
var d = {};
|
|
88
|
-
|
|
96
|
+
|
|
97
|
+
var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
|
|
89
98
|
if (webkit) input.style.width = "1000px";
|
|
90
99
|
else input.setAttribute("wrap", "off");
|
|
100
|
+
// if border: 0; -- iOS fails to open keyboard (issue #1287)
|
|
101
|
+
if (ios) input.style.border = "1px solid black";
|
|
91
102
|
input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off");
|
|
103
|
+
|
|
92
104
|
// Wraps and hides input textarea
|
|
93
105
|
d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
|
|
94
106
|
// The actual fake scrollbars.
|
|
@@ -112,7 +124,7 @@ window.CodeMirror = (function() {
|
|
|
112
124
|
// Set to the height of the text, causes scrolling
|
|
113
125
|
d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
|
|
114
126
|
// D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
|
|
115
|
-
d.heightForcer = elt("div",
|
|
127
|
+
d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
|
|
116
128
|
// Will contain the gutters, if any
|
|
117
129
|
d.gutters = elt("div", null, "CodeMirror-gutters");
|
|
118
130
|
d.lineGutter = null;
|
|
@@ -137,7 +149,8 @@ window.CodeMirror = (function() {
|
|
|
137
149
|
else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
|
|
138
150
|
|
|
139
151
|
// Current visible range (may be bigger than the view window).
|
|
140
|
-
d.viewOffset = d.
|
|
152
|
+
d.viewOffset = d.lastSizeC = 0;
|
|
153
|
+
d.showingFrom = d.showingTo = docStart;
|
|
141
154
|
|
|
142
155
|
// Used to only resize the line number gutter when necessary (when
|
|
143
156
|
// the amount of lines crosses a boundary that makes its width change)
|
|
@@ -153,8 +166,6 @@ window.CodeMirror = (function() {
|
|
|
153
166
|
d.pollingFast = false;
|
|
154
167
|
// Self-resetting timeout for the poller
|
|
155
168
|
d.poll = new Delayed();
|
|
156
|
-
// True when a drag from the editor is active
|
|
157
|
-
d.draggingText = false;
|
|
158
169
|
|
|
159
170
|
d.cachedCharWidth = d.cachedTextHeight = null;
|
|
160
171
|
d.measureLineCache = [];
|
|
@@ -164,40 +175,16 @@ window.CodeMirror = (function() {
|
|
|
164
175
|
// string instead of the (large) selection.
|
|
165
176
|
d.inaccurateSelection = false;
|
|
166
177
|
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
d.
|
|
178
|
+
// Tracks the maximum line length so that the horizontal scrollbar
|
|
179
|
+
// can be kept static when scrolling.
|
|
180
|
+
d.maxLine = null;
|
|
181
|
+
d.maxLineLength = 0;
|
|
182
|
+
d.maxLineChanged = false;
|
|
170
183
|
|
|
171
184
|
// Used for measuring wheel scrolling granularity
|
|
172
185
|
d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
|
|
173
|
-
|
|
174
|
-
return d;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// VIEW CONSTRUCTOR
|
|
178
186
|
|
|
179
|
-
|
|
180
|
-
var selPos = {line: 0, ch: 0};
|
|
181
|
-
return {
|
|
182
|
-
doc: doc,
|
|
183
|
-
// frontier is the point up to which the content has been parsed,
|
|
184
|
-
frontier: 0, highlight: new Delayed(),
|
|
185
|
-
sel: {from: selPos, to: selPos, head: selPos, anchor: selPos, shift: false, extend: false},
|
|
186
|
-
scrollTop: 0, scrollLeft: 0,
|
|
187
|
-
overwrite: false, focused: false,
|
|
188
|
-
// Tracks the maximum line length so that
|
|
189
|
-
// the horizontal scrollbar can be kept
|
|
190
|
-
// static when scrolling.
|
|
191
|
-
maxLine: getLine(doc, 0),
|
|
192
|
-
maxLineLength: 0,
|
|
193
|
-
maxLineChanged: false,
|
|
194
|
-
suppressEdits: false,
|
|
195
|
-
goalColumn: null,
|
|
196
|
-
cantEdit: false,
|
|
197
|
-
keyMaps: [],
|
|
198
|
-
overlays: [],
|
|
199
|
-
modeGen: 0
|
|
200
|
-
};
|
|
187
|
+
return d;
|
|
201
188
|
}
|
|
202
189
|
|
|
203
190
|
// STATE UPDATES
|
|
@@ -205,39 +192,50 @@ window.CodeMirror = (function() {
|
|
|
205
192
|
// Used to get the editor into a consistent state again when options change.
|
|
206
193
|
|
|
207
194
|
function loadMode(cm) {
|
|
208
|
-
|
|
209
|
-
cm.
|
|
210
|
-
doc.iter(0, doc.size, function(line) {
|
|
195
|
+
cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
|
|
196
|
+
cm.doc.iter(function(line) {
|
|
211
197
|
if (line.stateAfter) line.stateAfter = null;
|
|
212
198
|
if (line.styles) line.styles = null;
|
|
213
199
|
});
|
|
214
|
-
cm.
|
|
200
|
+
cm.doc.frontier = cm.doc.first;
|
|
215
201
|
startWorker(cm, 100);
|
|
216
|
-
cm.
|
|
217
|
-
if (cm.curOp) regChange(cm
|
|
202
|
+
cm.state.modeGen++;
|
|
203
|
+
if (cm.curOp) regChange(cm);
|
|
218
204
|
}
|
|
219
205
|
|
|
220
206
|
function wrappingChanged(cm) {
|
|
221
|
-
var doc = cm.view.doc, th = textHeight(cm.display);
|
|
222
207
|
if (cm.options.lineWrapping) {
|
|
223
208
|
cm.display.wrapper.className += " CodeMirror-wrap";
|
|
224
|
-
var perLine = cm.display.scroller.clientWidth / charWidth(cm.display) - 3;
|
|
225
|
-
doc.iter(0, doc.size, function(line) {
|
|
226
|
-
if (line.height == 0) return;
|
|
227
|
-
var guess = Math.ceil(line.text.length / perLine) || 1;
|
|
228
|
-
if (guess != 1) updateLineHeight(line, guess * th);
|
|
229
|
-
});
|
|
230
209
|
cm.display.sizer.style.minWidth = "";
|
|
231
210
|
} else {
|
|
232
211
|
cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
|
|
233
|
-
computeMaxLength(cm
|
|
234
|
-
doc.iter(0, doc.size, function(line) {
|
|
235
|
-
if (line.height != 0) updateLineHeight(line, th);
|
|
236
|
-
});
|
|
212
|
+
computeMaxLength(cm);
|
|
237
213
|
}
|
|
238
|
-
|
|
214
|
+
estimateLineHeights(cm);
|
|
215
|
+
regChange(cm);
|
|
239
216
|
clearCaches(cm);
|
|
240
|
-
setTimeout(function(){updateScrollbars(cm.display, cm.
|
|
217
|
+
setTimeout(function(){updateScrollbars(cm.display, cm.doc.height);}, 100);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function estimateHeight(cm) {
|
|
221
|
+
var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
|
|
222
|
+
var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
|
|
223
|
+
return function(line) {
|
|
224
|
+
if (lineIsHidden(cm.doc, line))
|
|
225
|
+
return 0;
|
|
226
|
+
else if (wrapping)
|
|
227
|
+
return (Math.ceil(line.text.length / perLine) || 1) * th;
|
|
228
|
+
else
|
|
229
|
+
return th;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function estimateLineHeights(cm) {
|
|
234
|
+
var doc = cm.doc, est = estimateHeight(cm);
|
|
235
|
+
doc.iter(function(line) {
|
|
236
|
+
var estHeight = est(line);
|
|
237
|
+
if (estHeight != line.height) updateLineHeight(line, estHeight);
|
|
238
|
+
});
|
|
241
239
|
}
|
|
242
240
|
|
|
243
241
|
function keyMapChanged(cm) {
|
|
@@ -254,7 +252,7 @@ window.CodeMirror = (function() {
|
|
|
254
252
|
|
|
255
253
|
function guttersChanged(cm) {
|
|
256
254
|
updateGutters(cm);
|
|
257
|
-
|
|
255
|
+
regChange(cm);
|
|
258
256
|
}
|
|
259
257
|
|
|
260
258
|
function updateGutters(cm) {
|
|
@@ -289,15 +287,16 @@ window.CodeMirror = (function() {
|
|
|
289
287
|
return len;
|
|
290
288
|
}
|
|
291
289
|
|
|
292
|
-
function computeMaxLength(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
290
|
+
function computeMaxLength(cm) {
|
|
291
|
+
var d = cm.display, doc = cm.doc;
|
|
292
|
+
d.maxLine = getLine(doc, doc.first);
|
|
293
|
+
d.maxLineLength = lineLength(doc, d.maxLine);
|
|
294
|
+
d.maxLineChanged = true;
|
|
295
|
+
doc.iter(function(line) {
|
|
296
|
+
var len = lineLength(doc, line);
|
|
297
|
+
if (len > d.maxLineLength) {
|
|
298
|
+
d.maxLineLength = len;
|
|
299
|
+
d.maxLine = line;
|
|
301
300
|
}
|
|
302
301
|
});
|
|
303
302
|
}
|
|
@@ -321,7 +320,7 @@ window.CodeMirror = (function() {
|
|
|
321
320
|
// Re-synchronize the fake scrollbars with the actual size of the
|
|
322
321
|
// content. Optionally force a scrollTop.
|
|
323
322
|
function updateScrollbars(d /* display */, docHeight) {
|
|
324
|
-
var totalHeight = docHeight +
|
|
323
|
+
var totalHeight = docHeight + paddingVert(d);
|
|
325
324
|
d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
|
|
326
325
|
var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
|
|
327
326
|
var needsH = d.scroller.scrollWidth > d.scroller.clientWidth;
|
|
@@ -329,7 +328,7 @@ window.CodeMirror = (function() {
|
|
|
329
328
|
if (needsV) {
|
|
330
329
|
d.scrollbarV.style.display = "block";
|
|
331
330
|
d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
|
|
332
|
-
d.scrollbarV.firstChild.style.height =
|
|
331
|
+
d.scrollbarV.firstChild.style.height =
|
|
333
332
|
(scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
|
|
334
333
|
} else d.scrollbarV.style.display = "";
|
|
335
334
|
if (needsH) {
|
|
@@ -361,7 +360,7 @@ window.CodeMirror = (function() {
|
|
|
361
360
|
function alignHorizontally(cm) {
|
|
362
361
|
var display = cm.display;
|
|
363
362
|
if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
|
|
364
|
-
var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.
|
|
363
|
+
var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
|
|
365
364
|
var gutterW = display.gutters.offsetWidth, l = comp + "px";
|
|
366
365
|
for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
|
|
367
366
|
for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
|
|
@@ -372,7 +371,7 @@ window.CodeMirror = (function() {
|
|
|
372
371
|
|
|
373
372
|
function maybeUpdateLineNumberWidth(cm) {
|
|
374
373
|
if (!cm.options.lineNumbers) return false;
|
|
375
|
-
var doc = cm.
|
|
374
|
+
var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
|
|
376
375
|
if (last.length != display.lineNumChars) {
|
|
377
376
|
var test = display.measure.appendChild(elt("div", [elt("div", last)],
|
|
378
377
|
"CodeMirror-linenumber CodeMirror-gutter-elt"));
|
|
@@ -391,21 +390,33 @@ window.CodeMirror = (function() {
|
|
|
391
390
|
return String(options.lineNumberFormatter(i + options.firstLineNumber));
|
|
392
391
|
}
|
|
393
392
|
function compensateForHScroll(display) {
|
|
394
|
-
return display.scroller
|
|
393
|
+
return getRect(display.scroller).left - getRect(display.sizer).left;
|
|
395
394
|
}
|
|
396
395
|
|
|
397
396
|
// DISPLAY DRAWING
|
|
398
397
|
|
|
399
398
|
function updateDisplay(cm, changes, viewPort) {
|
|
400
|
-
var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo;
|
|
401
|
-
var
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
signalLater(cm,
|
|
399
|
+
var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
|
|
400
|
+
var visible = visibleLines(cm.display, cm.doc, viewPort);
|
|
401
|
+
for (;;) {
|
|
402
|
+
if (updateDisplayInner(cm, changes, visible)) {
|
|
403
|
+
updated = true;
|
|
404
|
+
signalLater(cm, "update", cm);
|
|
405
|
+
if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
|
|
406
|
+
signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
|
|
407
|
+
} else break;
|
|
408
|
+
updateSelection(cm);
|
|
409
|
+
updateScrollbars(cm.display, cm.doc.height);
|
|
410
|
+
|
|
411
|
+
// Clip forced viewport to actual scrollable area
|
|
412
|
+
if (viewPort)
|
|
413
|
+
viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
|
|
414
|
+
typeof viewPort == "number" ? viewPort : viewPort.top);
|
|
415
|
+
visible = visibleLines(cm.display, cm.doc, viewPort);
|
|
416
|
+
if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
|
|
417
|
+
break;
|
|
418
|
+
changes = [];
|
|
406
419
|
}
|
|
407
|
-
updateSelection(cm);
|
|
408
|
-
updateScrollbars(cm.display, cm.view.doc.height);
|
|
409
420
|
|
|
410
421
|
return updated;
|
|
411
422
|
}
|
|
@@ -413,58 +424,59 @@ window.CodeMirror = (function() {
|
|
|
413
424
|
// Uses a set of changes plus the current scroll position to
|
|
414
425
|
// determine which DOM updates have to be made, and makes the
|
|
415
426
|
// updates.
|
|
416
|
-
function updateDisplayInner(cm, changes,
|
|
417
|
-
var display = cm.display, doc = cm.
|
|
427
|
+
function updateDisplayInner(cm, changes, visible) {
|
|
428
|
+
var display = cm.display, doc = cm.doc;
|
|
418
429
|
if (!display.wrapper.clientWidth) {
|
|
419
|
-
display.showingFrom = display.showingTo =
|
|
430
|
+
display.showingFrom = display.showingTo = doc.first;
|
|
431
|
+
display.viewOffset = 0;
|
|
420
432
|
return;
|
|
421
433
|
}
|
|
422
434
|
|
|
423
|
-
// Compute the new visible window
|
|
424
|
-
// If scrollTop is specified, use that to determine which lines
|
|
425
|
-
// to render instead of the current scrollbar position.
|
|
426
|
-
var visible = visibleLines(display, doc, viewPort);
|
|
427
435
|
// Bail out if the visible area is already rendered and nothing changed.
|
|
428
|
-
if (changes
|
|
436
|
+
if (changes.length == 0 &&
|
|
429
437
|
visible.from > display.showingFrom && visible.to < display.showingTo)
|
|
430
438
|
return;
|
|
431
439
|
|
|
432
|
-
if (
|
|
433
|
-
changes =
|
|
440
|
+
if (maybeUpdateLineNumberWidth(cm))
|
|
441
|
+
changes = [{from: doc.first, to: doc.first + doc.size}];
|
|
434
442
|
var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
|
|
435
443
|
display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
|
|
436
444
|
|
|
437
|
-
// When merged lines are present, the line that needs to be
|
|
438
|
-
// redrawn might not be the one that was changed.
|
|
439
|
-
if (changes !== true && sawCollapsedSpans)
|
|
440
|
-
for (var i = 0; i < changes.length; ++i) {
|
|
441
|
-
var ch = changes[i], merged;
|
|
442
|
-
while (merged = collapsedSpanAtStart(getLine(doc, ch.from))) {
|
|
443
|
-
var from = merged.find().from.line;
|
|
444
|
-
if (ch.diff) ch.diff -= ch.from - from;
|
|
445
|
-
ch.from = from;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
445
|
// Used to determine which lines need their line numbers updated
|
|
450
|
-
var positionsChangedFrom =
|
|
451
|
-
if (cm.options.lineNumbers
|
|
446
|
+
var positionsChangedFrom = Infinity;
|
|
447
|
+
if (cm.options.lineNumbers)
|
|
452
448
|
for (var i = 0; i < changes.length; ++i)
|
|
453
449
|
if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
|
|
454
450
|
|
|
455
|
-
var
|
|
456
|
-
var
|
|
457
|
-
|
|
458
|
-
if (display.
|
|
451
|
+
var end = doc.first + doc.size;
|
|
452
|
+
var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
|
|
453
|
+
var to = Math.min(end, visible.to + cm.options.viewportMargin);
|
|
454
|
+
if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
|
|
455
|
+
if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
|
|
459
456
|
if (sawCollapsedSpans) {
|
|
460
457
|
from = lineNo(visualLine(doc, getLine(doc, from)));
|
|
461
|
-
while (to <
|
|
458
|
+
while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
|
|
462
459
|
}
|
|
463
460
|
|
|
464
461
|
// Create a range of theoretically intact lines, and punch holes
|
|
465
462
|
// in that using the change info.
|
|
466
|
-
var intact =
|
|
467
|
-
|
|
463
|
+
var intact = [{from: Math.max(display.showingFrom, doc.first),
|
|
464
|
+
to: Math.min(display.showingTo, end)}];
|
|
465
|
+
if (intact[0].from >= intact[0].to) intact = [];
|
|
466
|
+
else intact = computeIntact(intact, changes);
|
|
467
|
+
// When merged lines are present, we might have to reduce the
|
|
468
|
+
// intact ranges because changes in continued fragments of the
|
|
469
|
+
// intact lines do require the lines to be redrawn.
|
|
470
|
+
if (sawCollapsedSpans)
|
|
471
|
+
for (var i = 0; i < intact.length; ++i) {
|
|
472
|
+
var range = intact[i], merged;
|
|
473
|
+
while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
|
|
474
|
+
var newTo = merged.find().from.line;
|
|
475
|
+
if (newTo > range.from) range.to = newTo;
|
|
476
|
+
else { intact.splice(i--, 1); break; }
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
468
480
|
// Clip off the parts that won't be visible
|
|
469
481
|
var intactLines = 0;
|
|
470
482
|
for (var i = 0; i < intact.length; ++i) {
|
|
@@ -474,15 +486,20 @@ window.CodeMirror = (function() {
|
|
|
474
486
|
if (range.from >= range.to) intact.splice(i--, 1);
|
|
475
487
|
else intactLines += range.to - range.from;
|
|
476
488
|
}
|
|
477
|
-
if (intactLines == to - from && from == display.showingFrom && to == display.showingTo)
|
|
489
|
+
if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
|
|
490
|
+
updateViewOffset(cm);
|
|
478
491
|
return;
|
|
492
|
+
}
|
|
479
493
|
intact.sort(function(a, b) {return a.from - b.from;});
|
|
480
494
|
|
|
481
|
-
|
|
495
|
+
// Avoid crashing on IE's "unspecified error" when in iframes
|
|
496
|
+
try {
|
|
497
|
+
var focused = document.activeElement;
|
|
498
|
+
} catch(e) {}
|
|
482
499
|
if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
|
|
483
500
|
patchDisplay(cm, from, to, intact, positionsChangedFrom);
|
|
484
501
|
display.lineDiv.style.display = "";
|
|
485
|
-
if (document.activeElement != focused && focused.offsetHeight) focused.focus();
|
|
502
|
+
if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
|
|
486
503
|
|
|
487
504
|
var different = from != display.showingFrom || to != display.showingTo ||
|
|
488
505
|
display.lastSizeC != display.wrapper.clientHeight;
|
|
@@ -499,7 +516,7 @@ window.CodeMirror = (function() {
|
|
|
499
516
|
height = bot - prevBottom;
|
|
500
517
|
prevBottom = bot;
|
|
501
518
|
} else {
|
|
502
|
-
var box = node
|
|
519
|
+
var box = getRect(node);
|
|
503
520
|
height = box.bottom - box.top;
|
|
504
521
|
}
|
|
505
522
|
var diff = node.lineObj.height - height;
|
|
@@ -511,15 +528,17 @@ window.CodeMirror = (function() {
|
|
|
511
528
|
widgets[i].height = widgets[i].node.offsetHeight;
|
|
512
529
|
}
|
|
513
530
|
}
|
|
514
|
-
|
|
515
|
-
// Position the mover div to align with the current virtual scroll position
|
|
516
|
-
display.mover.style.top = display.viewOffset + "px";
|
|
531
|
+
updateViewOffset(cm);
|
|
517
532
|
|
|
518
|
-
if (visibleLines(display, doc, viewPort).to >= to)
|
|
519
|
-
updateDisplayInner(cm, [], viewPort);
|
|
520
533
|
return true;
|
|
521
534
|
}
|
|
522
535
|
|
|
536
|
+
function updateViewOffset(cm) {
|
|
537
|
+
var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
|
|
538
|
+
// Position the mover div to align with the current virtual scroll position
|
|
539
|
+
cm.display.mover.style.top = off + "px";
|
|
540
|
+
}
|
|
541
|
+
|
|
523
542
|
function computeIntact(intact, changes) {
|
|
524
543
|
for (var i = 0, l = changes.length || 0; i < l; ++i) {
|
|
525
544
|
var change = changes[i], intact2 = [], diff = change.diff || 0;
|
|
@@ -572,56 +591,101 @@ window.CodeMirror = (function() {
|
|
|
572
591
|
return next;
|
|
573
592
|
}
|
|
574
593
|
|
|
575
|
-
var nextIntact = intact.shift(),
|
|
576
|
-
cm.
|
|
577
|
-
if (nextIntact && nextIntact.to ==
|
|
578
|
-
if (lineIsHidden(line)) {
|
|
594
|
+
var nextIntact = intact.shift(), lineN = from;
|
|
595
|
+
cm.doc.iter(from, to, function(line) {
|
|
596
|
+
if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
|
|
597
|
+
if (lineIsHidden(cm.doc, line)) {
|
|
579
598
|
if (line.height != 0) updateLineHeight(line, 0);
|
|
580
599
|
if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i)
|
|
581
600
|
if (line.widgets[i].showIfHidden) {
|
|
582
601
|
var prev = cur.previousSibling;
|
|
583
|
-
if (prev.
|
|
602
|
+
if (/pre/i.test(prev.nodeName)) {
|
|
584
603
|
var wrap = elt("div", null, null, "position: relative");
|
|
585
604
|
prev.parentNode.replaceChild(wrap, prev);
|
|
586
605
|
wrap.appendChild(prev);
|
|
587
606
|
prev = wrap;
|
|
588
607
|
}
|
|
589
|
-
prev.appendChild(
|
|
608
|
+
var wnode = prev.appendChild(elt("div", [line.widgets[i].node], "CodeMirror-linewidget"));
|
|
609
|
+
positionLineWidget(line.widgets[i], wnode, prev, dims);
|
|
590
610
|
}
|
|
591
|
-
} else if (nextIntact && nextIntact.from <=
|
|
611
|
+
} else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
|
|
592
612
|
// This line is intact. Skip to the actual node. Update its
|
|
593
613
|
// line number if needed.
|
|
594
614
|
while (cur.lineObj != line) cur = rm(cur);
|
|
595
|
-
if (lineNumbers && updateNumbersFrom <=
|
|
596
|
-
setTextContent(cur.lineNumber, lineNumberFor(cm.options,
|
|
615
|
+
if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
|
|
616
|
+
setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
|
|
597
617
|
cur = cur.nextSibling;
|
|
598
618
|
} else {
|
|
619
|
+
// For lines with widgets, make an attempt to find and reuse
|
|
620
|
+
// the existing element, so that widgets aren't needlessly
|
|
621
|
+
// removed and re-inserted into the dom
|
|
622
|
+
if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
|
|
623
|
+
if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
|
|
599
624
|
// This line needs to be generated.
|
|
600
|
-
var lineNode = buildLineElement(cm, line,
|
|
601
|
-
|
|
625
|
+
var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
|
|
626
|
+
if (lineNode != reuse) {
|
|
627
|
+
container.insertBefore(lineNode, cur);
|
|
628
|
+
} else {
|
|
629
|
+
while (cur != reuse) cur = rm(cur);
|
|
630
|
+
cur = cur.nextSibling;
|
|
631
|
+
}
|
|
632
|
+
|
|
602
633
|
lineNode.lineObj = line;
|
|
603
634
|
}
|
|
604
|
-
++
|
|
635
|
+
++lineN;
|
|
605
636
|
});
|
|
606
637
|
while (cur) cur = rm(cur);
|
|
607
638
|
}
|
|
608
639
|
|
|
609
|
-
function buildLineElement(cm, line, lineNo, dims) {
|
|
640
|
+
function buildLineElement(cm, line, lineNo, dims, reuse) {
|
|
610
641
|
var lineElement = lineContent(cm, line);
|
|
611
|
-
var markers = line.gutterMarkers, display = cm.display;
|
|
612
|
-
|
|
613
|
-
if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass &&
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
// Lines with gutter elements or a background class need
|
|
617
|
-
// to be wrapped again, and have the extra elements added
|
|
618
|
-
//
|
|
619
|
-
|
|
620
|
-
|
|
642
|
+
var markers = line.gutterMarkers, display = cm.display, wrap;
|
|
643
|
+
|
|
644
|
+
if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
|
|
645
|
+
return lineElement;
|
|
646
|
+
|
|
647
|
+
// Lines with gutter elements, widgets or a background class need
|
|
648
|
+
// to be wrapped again, and have the extra elements added to the
|
|
649
|
+
// wrapper div
|
|
650
|
+
|
|
651
|
+
if (reuse) {
|
|
652
|
+
reuse.alignable = null;
|
|
653
|
+
var isOk = true, widgetsSeen = 0;
|
|
654
|
+
for (var n = reuse.firstChild, next; n; n = next) {
|
|
655
|
+
next = n.nextSibling;
|
|
656
|
+
if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
|
|
657
|
+
reuse.removeChild(n);
|
|
658
|
+
} else {
|
|
659
|
+
for (var i = 0, first = true; i < line.widgets.length; ++i) {
|
|
660
|
+
var widget = line.widgets[i], isFirst = false;
|
|
661
|
+
if (!widget.above) { isFirst = first; first = false; }
|
|
662
|
+
if (widget.node == n.firstChild) {
|
|
663
|
+
positionLineWidget(widget, n, reuse, dims);
|
|
664
|
+
++widgetsSeen;
|
|
665
|
+
if (isFirst) reuse.insertBefore(lineElement, n);
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
if (i == line.widgets.length) { isOk = false; break; }
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (isOk && widgetsSeen == line.widgets.length) {
|
|
673
|
+
wrap = reuse;
|
|
674
|
+
reuse.className = line.wrapClass || "";
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (!wrap) {
|
|
678
|
+
wrap = elt("div", null, line.wrapClass, "position: relative");
|
|
679
|
+
wrap.appendChild(lineElement);
|
|
680
|
+
}
|
|
681
|
+
// Kludge to make sure the styled element lies behind the selection (by z-index)
|
|
682
|
+
if (line.bgClass)
|
|
683
|
+
wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
|
|
621
684
|
if (cm.options.lineNumbers || markers) {
|
|
622
|
-
var gutterWrap = wrap.
|
|
623
|
-
|
|
624
|
-
|
|
685
|
+
var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
|
|
686
|
+
(cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
|
|
687
|
+
wrap.firstChild);
|
|
688
|
+
if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
|
|
625
689
|
if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
|
|
626
690
|
wrap.lineNumber = gutterWrap.appendChild(
|
|
627
691
|
elt("div", lineNumberFor(cm.options, lineNo),
|
|
@@ -636,24 +700,20 @@ window.CodeMirror = (function() {
|
|
|
636
700
|
dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
|
|
637
701
|
}
|
|
638
702
|
}
|
|
639
|
-
|
|
640
|
-
if (line.
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
if (line.widgets) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
|
|
644
|
-
var widget = ws[i], node = buildLineWidget(widget, wrap, dims);
|
|
703
|
+
if (ie_lt8) wrap.style.zIndex = 2;
|
|
704
|
+
if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
|
|
705
|
+
var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
|
|
706
|
+
positionLineWidget(widget, node, wrap, dims);
|
|
645
707
|
if (widget.above)
|
|
646
708
|
wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
|
|
647
709
|
else
|
|
648
710
|
wrap.appendChild(node);
|
|
711
|
+
signalLater(widget, "redraw");
|
|
649
712
|
}
|
|
650
|
-
if (ie_lt8) wrap.style.zIndex = 2;
|
|
651
713
|
return wrap;
|
|
652
714
|
}
|
|
653
715
|
|
|
654
|
-
function
|
|
655
|
-
var node = elt("div", [widget.node], "CodeMirror-linewidget");
|
|
656
|
-
node.widget = widget;
|
|
716
|
+
function positionLineWidget(widget, node, wrap, dims) {
|
|
657
717
|
if (widget.noHScroll) {
|
|
658
718
|
(wrap.alignable || (wrap.alignable = [])).push(node);
|
|
659
719
|
var width = dims.wrapperWidth;
|
|
@@ -669,14 +729,13 @@ window.CodeMirror = (function() {
|
|
|
669
729
|
node.style.position = "relative";
|
|
670
730
|
if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
|
|
671
731
|
}
|
|
672
|
-
return node;
|
|
673
732
|
}
|
|
674
733
|
|
|
675
734
|
// SELECTION / CURSOR
|
|
676
735
|
|
|
677
736
|
function updateSelection(cm) {
|
|
678
737
|
var display = cm.display;
|
|
679
|
-
var collapsed = posEq(cm.
|
|
738
|
+
var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
|
|
680
739
|
if (collapsed || cm.options.showCursorWhenSelecting)
|
|
681
740
|
updateSelectionCursor(cm);
|
|
682
741
|
else
|
|
@@ -687,17 +746,19 @@ window.CodeMirror = (function() {
|
|
|
687
746
|
display.selectionDiv.style.display = "none";
|
|
688
747
|
|
|
689
748
|
// Move the hidden textarea near the cursor to prevent scrolling artifacts
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
749
|
+
if (cm.options.moveInputWithCursor) {
|
|
750
|
+
var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
|
|
751
|
+
var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
|
|
752
|
+
display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
|
|
753
|
+
headPos.top + lineOff.top - wrapOff.top)) + "px";
|
|
754
|
+
display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
|
|
755
|
+
headPos.left + lineOff.left - wrapOff.left)) + "px";
|
|
756
|
+
}
|
|
696
757
|
}
|
|
697
758
|
|
|
698
759
|
// No selection, plain cursor
|
|
699
760
|
function updateSelectionCursor(cm) {
|
|
700
|
-
var display = cm.display, pos = cursorCoords(cm, cm.
|
|
761
|
+
var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
|
|
701
762
|
display.cursor.style.left = pos.left + "px";
|
|
702
763
|
display.cursor.style.top = pos.top + "px";
|
|
703
764
|
display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
|
|
@@ -713,7 +774,7 @@ window.CodeMirror = (function() {
|
|
|
713
774
|
|
|
714
775
|
// Highlight selection
|
|
715
776
|
function updateSelectionRange(cm) {
|
|
716
|
-
var display = cm.display, doc = cm.
|
|
777
|
+
var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
|
|
717
778
|
var fragment = document.createDocumentFragment();
|
|
718
779
|
var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
|
|
719
780
|
|
|
@@ -728,13 +789,20 @@ window.CodeMirror = (function() {
|
|
|
728
789
|
var lineObj = getLine(doc, line);
|
|
729
790
|
var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity;
|
|
730
791
|
function coords(ch) {
|
|
731
|
-
return charCoords(cm,
|
|
792
|
+
return charCoords(cm, Pos(line, ch), "div", lineObj);
|
|
732
793
|
}
|
|
733
794
|
|
|
734
795
|
iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
|
|
735
|
-
var leftPos = coords(
|
|
736
|
-
|
|
737
|
-
|
|
796
|
+
var leftPos = coords(from), rightPos, left, right;
|
|
797
|
+
if (from == to) {
|
|
798
|
+
rightPos = leftPos;
|
|
799
|
+
left = right = leftPos.left;
|
|
800
|
+
} else {
|
|
801
|
+
rightPos = coords(to - 1);
|
|
802
|
+
if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
|
|
803
|
+
left = leftPos.left;
|
|
804
|
+
right = rightPos.right;
|
|
805
|
+
}
|
|
738
806
|
if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
|
|
739
807
|
add(left, leftPos.top, null, leftPos.bottom);
|
|
740
808
|
left = pl;
|
|
@@ -793,12 +861,12 @@ window.CodeMirror = (function() {
|
|
|
793
861
|
|
|
794
862
|
// Cursor-blinking
|
|
795
863
|
function restartBlink(cm) {
|
|
864
|
+
if (!cm.state.focused) return;
|
|
796
865
|
var display = cm.display;
|
|
797
866
|
clearInterval(display.blinker);
|
|
798
867
|
var on = true;
|
|
799
868
|
display.cursor.style.visibility = display.otherCursor.style.visibility = "";
|
|
800
869
|
display.blinker = setInterval(function() {
|
|
801
|
-
if (!display.cursor.offsetHeight) return;
|
|
802
870
|
display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
|
|
803
871
|
}, cm.options.cursorBlinkRate);
|
|
804
872
|
}
|
|
@@ -806,33 +874,33 @@ window.CodeMirror = (function() {
|
|
|
806
874
|
// HIGHLIGHT WORKER
|
|
807
875
|
|
|
808
876
|
function startWorker(cm, time) {
|
|
809
|
-
if (cm.
|
|
810
|
-
cm.
|
|
877
|
+
if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
|
|
878
|
+
cm.state.highlight.set(time, bind(highlightWorker, cm));
|
|
811
879
|
}
|
|
812
880
|
|
|
813
881
|
function highlightWorker(cm) {
|
|
814
|
-
var
|
|
815
|
-
if (
|
|
882
|
+
var doc = cm.doc;
|
|
883
|
+
if (doc.frontier < doc.first) doc.frontier = doc.first;
|
|
884
|
+
if (doc.frontier >= cm.display.showingTo) return;
|
|
816
885
|
var end = +new Date + cm.options.workTime;
|
|
817
|
-
var state = copyState(
|
|
886
|
+
var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
|
|
818
887
|
var changed = [], prevChange;
|
|
819
|
-
doc.iter(
|
|
820
|
-
if (
|
|
888
|
+
doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
|
|
889
|
+
if (doc.frontier >= cm.display.showingFrom) { // Visible
|
|
821
890
|
var oldStyles = line.styles;
|
|
822
891
|
line.styles = highlightLine(cm, line, state);
|
|
823
892
|
var ischange = !oldStyles || oldStyles.length != line.styles.length;
|
|
824
|
-
for (var i = 0; !ischange && i < oldStyles.length; ++i)
|
|
825
|
-
ischange = oldStyles[i] != line.styles[i];
|
|
893
|
+
for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
|
|
826
894
|
if (ischange) {
|
|
827
|
-
if (prevChange && prevChange.end ==
|
|
828
|
-
else changed.push(prevChange = {start:
|
|
895
|
+
if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
|
|
896
|
+
else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
|
|
829
897
|
}
|
|
830
|
-
line.stateAfter = copyState(
|
|
898
|
+
line.stateAfter = copyState(doc.mode, state);
|
|
831
899
|
} else {
|
|
832
900
|
processLine(cm, line, state);
|
|
833
|
-
line.stateAfter =
|
|
901
|
+
line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
|
|
834
902
|
}
|
|
835
|
-
++
|
|
903
|
+
++doc.frontier;
|
|
836
904
|
if (+new Date > end) {
|
|
837
905
|
startWorker(cm, cm.options.workDelay);
|
|
838
906
|
return true;
|
|
@@ -851,10 +919,10 @@ window.CodeMirror = (function() {
|
|
|
851
919
|
// smallest indentation, which tends to need the least context to
|
|
852
920
|
// parse correctly.
|
|
853
921
|
function findStartLine(cm, n) {
|
|
854
|
-
var minindent, minline, doc = cm.
|
|
922
|
+
var minindent, minline, doc = cm.doc;
|
|
855
923
|
for (var search = n, lim = n - 100; search > lim; --search) {
|
|
856
|
-
if (search
|
|
857
|
-
var line = getLine(doc, search-1);
|
|
924
|
+
if (search <= doc.first) return doc.first;
|
|
925
|
+
var line = getLine(doc, search - 1);
|
|
858
926
|
if (line.stateAfter) return search;
|
|
859
927
|
var indented = countColumn(line.text, null, cm.options.tabSize);
|
|
860
928
|
if (minline == null || minindent > indented) {
|
|
@@ -866,32 +934,33 @@ window.CodeMirror = (function() {
|
|
|
866
934
|
}
|
|
867
935
|
|
|
868
936
|
function getStateBefore(cm, n) {
|
|
869
|
-
var
|
|
870
|
-
|
|
871
|
-
var pos = findStartLine(cm, n), state = pos && getLine(
|
|
872
|
-
if (!state) state = startState(
|
|
873
|
-
else state = copyState(
|
|
874
|
-
|
|
937
|
+
var doc = cm.doc, display = cm.display;
|
|
938
|
+
if (!doc.mode.startState) return true;
|
|
939
|
+
var pos = findStartLine(cm, n), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
|
|
940
|
+
if (!state) state = startState(doc.mode);
|
|
941
|
+
else state = copyState(doc.mode, state);
|
|
942
|
+
doc.iter(pos, n, function(line) {
|
|
875
943
|
processLine(cm, line, state);
|
|
876
|
-
var save = pos == n - 1 || pos % 5 == 0 || pos >=
|
|
877
|
-
line.stateAfter = save ? copyState(
|
|
944
|
+
var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
|
|
945
|
+
line.stateAfter = save ? copyState(doc.mode, state) : null;
|
|
878
946
|
++pos;
|
|
879
947
|
});
|
|
880
948
|
return state;
|
|
881
949
|
}
|
|
882
950
|
|
|
883
951
|
// POSITION MEASUREMENT
|
|
884
|
-
|
|
952
|
+
|
|
885
953
|
function paddingTop(display) {return display.lineSpace.offsetTop;}
|
|
954
|
+
function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
|
|
886
955
|
function paddingLeft(display) {
|
|
887
|
-
var e = removeChildrenAndAdd(display.measure, elt("pre")).appendChild(elt("span", "x"));
|
|
956
|
+
var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
|
|
888
957
|
return e.offsetLeft;
|
|
889
958
|
}
|
|
890
959
|
|
|
891
960
|
function measureChar(cm, line, ch, data) {
|
|
892
961
|
var dir = -1;
|
|
893
962
|
data = data || measureLine(cm, line);
|
|
894
|
-
|
|
963
|
+
|
|
895
964
|
for (var pos = ch;; pos += dir) {
|
|
896
965
|
var r = data[pos];
|
|
897
966
|
if (r) break;
|
|
@@ -902,22 +971,30 @@ window.CodeMirror = (function() {
|
|
|
902
971
|
top: r.top, bottom: r.bottom};
|
|
903
972
|
}
|
|
904
973
|
|
|
905
|
-
function
|
|
906
|
-
|
|
907
|
-
var display = cm.display, cache = cm.display.measureLineCache;
|
|
974
|
+
function findCachedMeasurement(cm, line) {
|
|
975
|
+
var cache = cm.display.measureLineCache;
|
|
908
976
|
for (var i = 0; i < cache.length; ++i) {
|
|
909
977
|
var memo = cache[i];
|
|
910
978
|
if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
|
|
911
|
-
display.scroller.clientWidth == memo.width
|
|
979
|
+
cm.display.scroller.clientWidth == memo.width &&
|
|
980
|
+
memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
|
|
912
981
|
return memo.measure;
|
|
913
982
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
if (
|
|
920
|
-
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
function measureLine(cm, line) {
|
|
986
|
+
// First look in the cache
|
|
987
|
+
var measure = findCachedMeasurement(cm, line);
|
|
988
|
+
if (!measure) {
|
|
989
|
+
// Failing that, recompute and store result in cache
|
|
990
|
+
measure = measureLineInner(cm, line);
|
|
991
|
+
var cache = cm.display.measureLineCache;
|
|
992
|
+
var memo = {text: line.text, width: cm.display.scroller.clientWidth,
|
|
993
|
+
markedSpans: line.markedSpans, measure: measure,
|
|
994
|
+
classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
|
|
995
|
+
if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
|
|
996
|
+
else cache.push(memo);
|
|
997
|
+
}
|
|
921
998
|
return measure;
|
|
922
999
|
}
|
|
923
1000
|
|
|
@@ -952,10 +1029,15 @@ window.CodeMirror = (function() {
|
|
|
952
1029
|
|
|
953
1030
|
removeChildrenAndAdd(display.measure, pre);
|
|
954
1031
|
|
|
955
|
-
var outer = display.lineDiv
|
|
1032
|
+
var outer = getRect(display.lineDiv);
|
|
956
1033
|
var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
|
|
1034
|
+
// Work around an IE7/8 bug where it will sometimes have randomly
|
|
1035
|
+
// replaced our pre with a clone at this point.
|
|
1036
|
+
if (ie_lt9 && display.measure.first != pre)
|
|
1037
|
+
removeChildrenAndAdd(display.measure, pre);
|
|
1038
|
+
|
|
957
1039
|
for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
|
|
958
|
-
var size = cur
|
|
1040
|
+
var size = getRect(cur);
|
|
959
1041
|
var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
|
|
960
1042
|
for (var j = 0; j < vranges.length; j += 2) {
|
|
961
1043
|
var rtop = vranges[j], rbot = vranges[j+1];
|
|
@@ -969,19 +1051,38 @@ window.CodeMirror = (function() {
|
|
|
969
1051
|
}
|
|
970
1052
|
}
|
|
971
1053
|
if (j == vranges.length) vranges.push(top, bot);
|
|
972
|
-
|
|
1054
|
+
var right = size.right;
|
|
1055
|
+
if (cur.measureRight) right = getRect(cur.measureRight).left;
|
|
1056
|
+
data[i] = {left: size.left - outer.left, right: right - outer.left, top: j};
|
|
973
1057
|
}
|
|
974
1058
|
for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
|
|
975
1059
|
var vr = cur.top;
|
|
976
1060
|
cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
|
|
977
1061
|
}
|
|
1062
|
+
|
|
978
1063
|
return data;
|
|
979
1064
|
}
|
|
980
1065
|
|
|
1066
|
+
function measureLineWidth(cm, line) {
|
|
1067
|
+
var hasBadSpan = false;
|
|
1068
|
+
if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
|
|
1069
|
+
var sp = line.markedSpans[i];
|
|
1070
|
+
if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
|
|
1071
|
+
}
|
|
1072
|
+
var cached = !hasBadSpan && findCachedMeasurement(cm, line);
|
|
1073
|
+
if (cached) return measureChar(cm, line, line.text.length, cached).right;
|
|
1074
|
+
|
|
1075
|
+
var pre = lineContent(cm, line);
|
|
1076
|
+
var end = pre.appendChild(zeroWidthElement(cm.display.measure));
|
|
1077
|
+
removeChildrenAndAdd(cm.display.measure, pre);
|
|
1078
|
+
return getRect(end).right - getRect(cm.display.lineDiv).left;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
981
1081
|
function clearCaches(cm) {
|
|
982
1082
|
cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
|
|
983
1083
|
cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
|
|
984
|
-
cm.
|
|
1084
|
+
if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
|
|
1085
|
+
cm.display.lineNumChars = null;
|
|
985
1086
|
}
|
|
986
1087
|
|
|
987
1088
|
// Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
|
|
@@ -995,7 +1096,7 @@ window.CodeMirror = (function() {
|
|
|
995
1096
|
var yOff = heightAtLine(cm, lineObj);
|
|
996
1097
|
if (context != "local") yOff -= cm.display.viewOffset;
|
|
997
1098
|
if (context == "page") {
|
|
998
|
-
var lOff = cm.display.lineSpace
|
|
1099
|
+
var lOff = getRect(cm.display.lineSpace);
|
|
999
1100
|
yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop);
|
|
1000
1101
|
var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft);
|
|
1001
1102
|
rect.left += xOff; rect.right += xOff;
|
|
@@ -1004,13 +1105,33 @@ window.CodeMirror = (function() {
|
|
|
1004
1105
|
return rect;
|
|
1005
1106
|
}
|
|
1006
1107
|
|
|
1108
|
+
// Context may be "window", "page", "div", or "local"/null
|
|
1109
|
+
// Result is in "div" coords
|
|
1110
|
+
function fromCoordSystem(cm, coords, context) {
|
|
1111
|
+
if (context == "div") return coords;
|
|
1112
|
+
var left = coords.left, top = coords.top;
|
|
1113
|
+
if (context == "page") {
|
|
1114
|
+
left -= window.pageXOffset || (document.documentElement || document.body).scrollLeft;
|
|
1115
|
+
top -= window.pageYOffset || (document.documentElement || document.body).scrollTop;
|
|
1116
|
+
}
|
|
1117
|
+
var lineSpaceBox = getRect(cm.display.lineSpace);
|
|
1118
|
+
left -= lineSpaceBox.left;
|
|
1119
|
+
top -= lineSpaceBox.top;
|
|
1120
|
+
if (context == "local" || !context) {
|
|
1121
|
+
var editorBox = getRect(cm.display.wrapper);
|
|
1122
|
+
left += editorBox.left;
|
|
1123
|
+
top += editorBox.top;
|
|
1124
|
+
}
|
|
1125
|
+
return {left: left, top: top};
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1007
1128
|
function charCoords(cm, pos, context, lineObj) {
|
|
1008
|
-
if (!lineObj) lineObj = getLine(cm.
|
|
1129
|
+
if (!lineObj) lineObj = getLine(cm.doc, pos.line);
|
|
1009
1130
|
return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), context);
|
|
1010
1131
|
}
|
|
1011
1132
|
|
|
1012
1133
|
function cursorCoords(cm, pos, context, lineObj, measurement) {
|
|
1013
|
-
lineObj = lineObj || getLine(cm.
|
|
1134
|
+
lineObj = lineObj || getLine(cm.doc, pos.line);
|
|
1014
1135
|
if (!measurement) measurement = measureLine(cm, lineObj);
|
|
1015
1136
|
function get(ch, right) {
|
|
1016
1137
|
var m = measureChar(cm, lineObj, ch, measurement);
|
|
@@ -1025,10 +1146,9 @@ window.CodeMirror = (function() {
|
|
|
1025
1146
|
if (part.from < ch && part.to > ch) return get(ch, rtl);
|
|
1026
1147
|
var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to;
|
|
1027
1148
|
if (left == ch) {
|
|
1028
|
-
//
|
|
1029
|
-
//
|
|
1030
|
-
//
|
|
1031
|
-
// level.
|
|
1149
|
+
// IE returns bogus offsets and widths for edges where the
|
|
1150
|
+
// direction flips, but only for the side with the lower
|
|
1151
|
+
// level. So we try to use the side with the higher level.
|
|
1032
1152
|
if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true);
|
|
1033
1153
|
else here = get(rtl && part.from != part.to ? ch - 1 : ch);
|
|
1034
1154
|
if (rtl == linedir) main = here; else other = here;
|
|
@@ -1046,13 +1166,20 @@ window.CodeMirror = (function() {
|
|
|
1046
1166
|
return main;
|
|
1047
1167
|
}
|
|
1048
1168
|
|
|
1169
|
+
function PosMaybeOutside(line, ch, outside) {
|
|
1170
|
+
var pos = new Pos(line, ch);
|
|
1171
|
+
if (outside) pos.outside = true;
|
|
1172
|
+
return pos;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1049
1175
|
// Coords must be lineSpace-local
|
|
1050
1176
|
function coordsChar(cm, x, y) {
|
|
1051
|
-
var doc = cm.
|
|
1177
|
+
var doc = cm.doc;
|
|
1052
1178
|
y += cm.display.viewOffset;
|
|
1053
|
-
if (y < 0) return
|
|
1054
|
-
var lineNo = lineAtHeight(doc, y);
|
|
1055
|
-
if (lineNo
|
|
1179
|
+
if (y < 0) return PosMaybeOutside(doc.first, 0, true);
|
|
1180
|
+
var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
|
|
1181
|
+
if (lineNo > last)
|
|
1182
|
+
return PosMaybeOutside(doc.first + doc.size - 1, getLine(doc, last).text.length, true);
|
|
1056
1183
|
if (x < 0) x = 0;
|
|
1057
1184
|
|
|
1058
1185
|
for (;;) {
|
|
@@ -1069,30 +1196,32 @@ window.CodeMirror = (function() {
|
|
|
1069
1196
|
|
|
1070
1197
|
function coordsCharInner(cm, lineObj, lineNo, x, y) {
|
|
1071
1198
|
var innerOff = y - heightAtLine(cm, lineObj);
|
|
1072
|
-
var wrongLine = false,
|
|
1199
|
+
var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
|
|
1073
1200
|
var measurement = measureLine(cm, lineObj);
|
|
1074
1201
|
|
|
1075
1202
|
function getX(ch) {
|
|
1076
|
-
var sp = cursorCoords(cm,
|
|
1203
|
+
var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
|
|
1077
1204
|
lineObj, measurement);
|
|
1078
1205
|
wrongLine = true;
|
|
1079
|
-
if (innerOff > sp.bottom) return
|
|
1080
|
-
else if (innerOff < sp.top) return sp.left +
|
|
1206
|
+
if (innerOff > sp.bottom) return sp.left - adjust;
|
|
1207
|
+
else if (innerOff < sp.top) return sp.left + adjust;
|
|
1081
1208
|
else wrongLine = false;
|
|
1082
1209
|
return sp.left;
|
|
1083
1210
|
}
|
|
1084
1211
|
|
|
1085
1212
|
var bidi = getOrder(lineObj), dist = lineObj.text.length;
|
|
1086
1213
|
var from = lineLeft(lineObj), to = lineRight(lineObj);
|
|
1087
|
-
var fromX =
|
|
1214
|
+
var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
|
|
1088
1215
|
|
|
1089
|
-
if (x > toX) return
|
|
1216
|
+
if (x > toX) return PosMaybeOutside(lineNo, to, toOutside);
|
|
1090
1217
|
// Do a binary search between these bounds.
|
|
1091
1218
|
for (;;) {
|
|
1092
1219
|
if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
|
|
1093
1220
|
var after = x - fromX < toX - x, ch = after ? from : to;
|
|
1094
1221
|
while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
|
|
1095
|
-
|
|
1222
|
+
var pos = PosMaybeOutside(lineNo, ch, after ? fromOutside : toOutside);
|
|
1223
|
+
pos.after = after;
|
|
1224
|
+
return pos;
|
|
1096
1225
|
}
|
|
1097
1226
|
var step = Math.ceil(dist / 2), middle = from + step;
|
|
1098
1227
|
if (bidi) {
|
|
@@ -1100,8 +1229,8 @@ window.CodeMirror = (function() {
|
|
|
1100
1229
|
for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
|
|
1101
1230
|
}
|
|
1102
1231
|
var middleX = getX(middle);
|
|
1103
|
-
if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; dist
|
|
1104
|
-
else {from = middle; fromX = middleX;
|
|
1232
|
+
if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
|
|
1233
|
+
else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
|
|
1105
1234
|
}
|
|
1106
1235
|
}
|
|
1107
1236
|
|
|
@@ -1142,81 +1271,120 @@ window.CodeMirror = (function() {
|
|
|
1142
1271
|
// be awkward, slow, and error-prone), but instead updates are
|
|
1143
1272
|
// batched and then all combined and executed at once.
|
|
1144
1273
|
|
|
1274
|
+
var nextOpId = 0;
|
|
1145
1275
|
function startOperation(cm) {
|
|
1146
|
-
|
|
1147
|
-
else cm.curOp = {
|
|
1148
|
-
// Nested operations delay update until the outermost one
|
|
1149
|
-
// finishes.
|
|
1150
|
-
depth: 1,
|
|
1276
|
+
cm.curOp = {
|
|
1151
1277
|
// An array of ranges of lines that have to be updated. See
|
|
1152
1278
|
// updateDisplay.
|
|
1153
1279
|
changes: [],
|
|
1154
|
-
delayedCallbacks: [],
|
|
1155
1280
|
updateInput: null,
|
|
1156
1281
|
userSelChange: null,
|
|
1157
1282
|
textChanged: null,
|
|
1158
1283
|
selectionChanged: false,
|
|
1284
|
+
cursorActivity: false,
|
|
1159
1285
|
updateMaxLine: false,
|
|
1160
|
-
|
|
1286
|
+
updateScrollPos: false,
|
|
1287
|
+
id: ++nextOpId
|
|
1161
1288
|
};
|
|
1289
|
+
if (!delayedCallbackDepth++) delayedCallbacks = [];
|
|
1162
1290
|
}
|
|
1163
1291
|
|
|
1164
1292
|
function endOperation(cm) {
|
|
1165
|
-
var op = cm.curOp;
|
|
1166
|
-
if (--op.depth) return;
|
|
1293
|
+
var op = cm.curOp, doc = cm.doc, display = cm.display;
|
|
1167
1294
|
cm.curOp = null;
|
|
1168
|
-
|
|
1169
|
-
if (op.updateMaxLine) computeMaxLength(
|
|
1170
|
-
if (
|
|
1171
|
-
var width =
|
|
1172
|
-
display.sizer.style.minWidth = (width + 3 + scrollerCutOff) + "px";
|
|
1173
|
-
|
|
1295
|
+
|
|
1296
|
+
if (op.updateMaxLine) computeMaxLength(cm);
|
|
1297
|
+
if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
|
|
1298
|
+
var width = measureLineWidth(cm, display.maxLine);
|
|
1299
|
+
display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
|
|
1300
|
+
display.maxLineChanged = false;
|
|
1174
1301
|
var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
|
|
1175
|
-
if (maxScrollLeft <
|
|
1302
|
+
if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
|
|
1176
1303
|
setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
|
|
1177
1304
|
}
|
|
1178
1305
|
var newScrollPos, updated;
|
|
1179
|
-
if (op.
|
|
1180
|
-
|
|
1306
|
+
if (op.updateScrollPos) {
|
|
1307
|
+
newScrollPos = op.updateScrollPos;
|
|
1308
|
+
} else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
|
|
1309
|
+
var coords = cursorCoords(cm, doc.sel.head);
|
|
1181
1310
|
newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
|
|
1182
1311
|
}
|
|
1183
|
-
if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null)
|
|
1312
|
+
if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) {
|
|
1184
1313
|
updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
|
|
1314
|
+
if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
|
|
1315
|
+
}
|
|
1185
1316
|
if (!updated && op.selectionChanged) updateSelection(cm);
|
|
1186
|
-
if (
|
|
1317
|
+
if (op.updateScrollPos) {
|
|
1318
|
+
display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
|
|
1319
|
+
display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
|
|
1320
|
+
alignHorizontally(cm);
|
|
1321
|
+
if (op.scrollToPos)
|
|
1322
|
+
scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
|
|
1323
|
+
} else if (newScrollPos) {
|
|
1324
|
+
scrollCursorIntoView(cm);
|
|
1325
|
+
}
|
|
1187
1326
|
if (op.selectionChanged) restartBlink(cm);
|
|
1188
1327
|
|
|
1189
|
-
if (
|
|
1328
|
+
if (cm.state.focused && op.updateInput)
|
|
1190
1329
|
resetInput(cm, op.userSelChange);
|
|
1191
1330
|
|
|
1331
|
+
var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
|
|
1332
|
+
if (hidden) for (var i = 0; i < hidden.length; ++i)
|
|
1333
|
+
if (!hidden[i].lines.length) signal(hidden[i], "hide");
|
|
1334
|
+
if (unhidden) for (var i = 0; i < unhidden.length; ++i)
|
|
1335
|
+
if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
|
|
1336
|
+
|
|
1337
|
+
var delayed;
|
|
1338
|
+
if (!--delayedCallbackDepth) {
|
|
1339
|
+
delayed = delayedCallbacks;
|
|
1340
|
+
delayedCallbacks = null;
|
|
1341
|
+
}
|
|
1192
1342
|
if (op.textChanged)
|
|
1193
1343
|
signal(cm, "change", cm, op.textChanged);
|
|
1194
|
-
if (op.
|
|
1195
|
-
for (var i = 0; i <
|
|
1344
|
+
if (op.cursorActivity) signal(cm, "cursorActivity", cm);
|
|
1345
|
+
if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
|
|
1196
1346
|
}
|
|
1197
1347
|
|
|
1198
1348
|
// Wraps a function in an operation. Returns the wrapped function.
|
|
1199
1349
|
function operation(cm1, f) {
|
|
1200
1350
|
return function() {
|
|
1201
|
-
var cm = cm1 || this;
|
|
1202
|
-
startOperation(cm);
|
|
1203
|
-
try {var result = f.apply(cm, arguments);}
|
|
1204
|
-
finally {endOperation(cm);}
|
|
1351
|
+
var cm = cm1 || this, withOp = !cm.curOp;
|
|
1352
|
+
if (withOp) startOperation(cm);
|
|
1353
|
+
try { var result = f.apply(cm, arguments); }
|
|
1354
|
+
finally { if (withOp) endOperation(cm); }
|
|
1355
|
+
return result;
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
function docOperation(f) {
|
|
1359
|
+
return function() {
|
|
1360
|
+
var withOp = this.cm && !this.cm.curOp, result;
|
|
1361
|
+
if (withOp) startOperation(this.cm);
|
|
1362
|
+
try { result = f.apply(this, arguments); }
|
|
1363
|
+
finally { if (withOp) endOperation(this.cm); }
|
|
1205
1364
|
return result;
|
|
1206
1365
|
};
|
|
1207
1366
|
}
|
|
1367
|
+
function runInOp(cm, f) {
|
|
1368
|
+
var withOp = !cm.curOp, result;
|
|
1369
|
+
if (withOp) startOperation(cm);
|
|
1370
|
+
try { result = f(); }
|
|
1371
|
+
finally { if (withOp) endOperation(cm); }
|
|
1372
|
+
return result;
|
|
1373
|
+
}
|
|
1208
1374
|
|
|
1209
1375
|
function regChange(cm, from, to, lendiff) {
|
|
1376
|
+
if (from == null) from = cm.doc.first;
|
|
1377
|
+
if (to == null) to = cm.doc.first + cm.doc.size;
|
|
1210
1378
|
cm.curOp.changes.push({from: from, to: to, diff: lendiff});
|
|
1211
1379
|
}
|
|
1212
1380
|
|
|
1213
1381
|
// INPUT HANDLING
|
|
1214
1382
|
|
|
1215
1383
|
function slowPoll(cm) {
|
|
1216
|
-
if (cm.
|
|
1384
|
+
if (cm.display.pollingFast) return;
|
|
1217
1385
|
cm.display.poll.set(cm.options.pollInterval, function() {
|
|
1218
1386
|
readInput(cm);
|
|
1219
|
-
if (cm.
|
|
1387
|
+
if (cm.state.focused) slowPoll(cm);
|
|
1220
1388
|
});
|
|
1221
1389
|
}
|
|
1222
1390
|
|
|
@@ -1237,50 +1405,61 @@ window.CodeMirror = (function() {
|
|
|
1237
1405
|
// events that indicate IME taking place, but these are not widely
|
|
1238
1406
|
// supported or compatible enough yet to rely on.)
|
|
1239
1407
|
function readInput(cm) {
|
|
1240
|
-
var input = cm.display.input, prevInput = cm.display.prevInput,
|
|
1241
|
-
if (!
|
|
1408
|
+
var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
|
|
1409
|
+
if (!cm.state.focused || hasSelection(input) || isReadOnly(cm)) return false;
|
|
1242
1410
|
var text = input.value;
|
|
1243
1411
|
if (text == prevInput && posEq(sel.from, sel.to)) return false;
|
|
1244
|
-
|
|
1245
|
-
|
|
1412
|
+
if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
|
|
1413
|
+
resetInput(cm, true);
|
|
1414
|
+
return false;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
var withOp = !cm.curOp;
|
|
1418
|
+
if (withOp) startOperation(cm);
|
|
1419
|
+
sel.shift = false;
|
|
1246
1420
|
var same = 0, l = Math.min(prevInput.length, text.length);
|
|
1247
|
-
while (same < l && prevInput
|
|
1421
|
+
while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
|
|
1248
1422
|
var from = sel.from, to = sel.to;
|
|
1249
1423
|
if (same < prevInput.length)
|
|
1250
|
-
from =
|
|
1251
|
-
else if (
|
|
1252
|
-
to =
|
|
1424
|
+
from = Pos(from.line, from.ch - (prevInput.length - same));
|
|
1425
|
+
else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
|
|
1426
|
+
to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
|
|
1253
1427
|
var updateInput = cm.curOp.updateInput;
|
|
1254
|
-
|
|
1255
|
-
|
|
1428
|
+
makeChange(cm.doc, {from: from, to: to, text: splitLines(text.slice(same)),
|
|
1429
|
+
origin: cm.state.pasteIncoming ? "paste" : "+input"}, "end");
|
|
1430
|
+
|
|
1256
1431
|
cm.curOp.updateInput = updateInput;
|
|
1257
|
-
if (text.length > 1000) input.value = cm.display.prevInput = "";
|
|
1432
|
+
if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
|
|
1258
1433
|
else cm.display.prevInput = text;
|
|
1259
|
-
endOperation(cm);
|
|
1260
|
-
cm.
|
|
1434
|
+
if (withOp) endOperation(cm);
|
|
1435
|
+
cm.state.pasteIncoming = false;
|
|
1261
1436
|
return true;
|
|
1262
1437
|
}
|
|
1263
1438
|
|
|
1264
1439
|
function resetInput(cm, user) {
|
|
1265
|
-
var
|
|
1266
|
-
if (!posEq(
|
|
1440
|
+
var minimal, selected, doc = cm.doc;
|
|
1441
|
+
if (!posEq(doc.sel.from, doc.sel.to)) {
|
|
1267
1442
|
cm.display.prevInput = "";
|
|
1268
1443
|
minimal = hasCopyEvent &&
|
|
1269
|
-
(
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
if (
|
|
1273
|
-
|
|
1444
|
+
(doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
|
|
1445
|
+
var content = minimal ? "-" : selected || cm.getSelection();
|
|
1446
|
+
cm.display.input.value = content;
|
|
1447
|
+
if (cm.state.focused) selectInput(cm.display.input);
|
|
1448
|
+
if (ie && !ie_lt9) cm.display.inputHasSelection = content;
|
|
1449
|
+
} else if (user) {
|
|
1450
|
+
cm.display.prevInput = cm.display.input.value = "";
|
|
1451
|
+
if (ie && !ie_lt9) cm.display.inputHasSelection = null;
|
|
1452
|
+
}
|
|
1274
1453
|
cm.display.inaccurateSelection = minimal;
|
|
1275
1454
|
}
|
|
1276
1455
|
|
|
1277
1456
|
function focusInput(cm) {
|
|
1278
|
-
if (cm.options.readOnly != "nocursor" && (
|
|
1457
|
+
if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
|
|
1279
1458
|
cm.display.input.focus();
|
|
1280
1459
|
}
|
|
1281
1460
|
|
|
1282
1461
|
function isReadOnly(cm) {
|
|
1283
|
-
return cm.options.readOnly || cm.
|
|
1462
|
+
return cm.options.readOnly || cm.doc.cantEdit;
|
|
1284
1463
|
}
|
|
1285
1464
|
|
|
1286
1465
|
// EVENT HANDLERS
|
|
@@ -1288,57 +1467,67 @@ window.CodeMirror = (function() {
|
|
|
1288
1467
|
function registerEventHandlers(cm) {
|
|
1289
1468
|
var d = cm.display;
|
|
1290
1469
|
on(d.scroller, "mousedown", operation(cm, onMouseDown));
|
|
1291
|
-
|
|
1470
|
+
if (ie)
|
|
1471
|
+
on(d.scroller, "dblclick", operation(cm, function(e) {
|
|
1472
|
+
var pos = posFromMouse(cm, e);
|
|
1473
|
+
if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
|
|
1474
|
+
e_preventDefault(e);
|
|
1475
|
+
var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
|
|
1476
|
+
extendSelection(cm.doc, word.from, word.to);
|
|
1477
|
+
}));
|
|
1478
|
+
else
|
|
1479
|
+
on(d.scroller, "dblclick", e_preventDefault);
|
|
1292
1480
|
on(d.lineSpace, "selectstart", function(e) {
|
|
1293
1481
|
if (!eventInWidget(d, e)) e_preventDefault(e);
|
|
1294
1482
|
});
|
|
1295
1483
|
// Gecko browsers fire contextmenu *after* opening the menu, at
|
|
1296
1484
|
// which point we can't mess with it anymore. Context menu is
|
|
1297
1485
|
// handled in onMouseDown for Gecko.
|
|
1298
|
-
if (!
|
|
1486
|
+
if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
|
|
1299
1487
|
|
|
1300
1488
|
on(d.scroller, "scroll", function() {
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1489
|
+
if (d.scroller.clientHeight) {
|
|
1490
|
+
setScrollTop(cm, d.scroller.scrollTop);
|
|
1491
|
+
setScrollLeft(cm, d.scroller.scrollLeft, true);
|
|
1492
|
+
signal(cm, "scroll", cm);
|
|
1493
|
+
}
|
|
1304
1494
|
});
|
|
1305
1495
|
on(d.scrollbarV, "scroll", function() {
|
|
1306
|
-
setScrollTop(cm, d.scrollbarV.scrollTop);
|
|
1496
|
+
if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
|
|
1307
1497
|
});
|
|
1308
1498
|
on(d.scrollbarH, "scroll", function() {
|
|
1309
|
-
setScrollLeft(cm, d.scrollbarH.scrollLeft);
|
|
1499
|
+
if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
|
|
1310
1500
|
});
|
|
1311
1501
|
|
|
1312
1502
|
on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
|
|
1313
1503
|
on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
|
|
1314
1504
|
|
|
1315
|
-
function reFocus() { if (cm.
|
|
1505
|
+
function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
|
|
1316
1506
|
on(d.scrollbarH, "mousedown", reFocus);
|
|
1317
1507
|
on(d.scrollbarV, "mousedown", reFocus);
|
|
1318
1508
|
// Prevent wrapper from ever scrolling
|
|
1319
1509
|
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
|
|
1320
1510
|
|
|
1321
|
-
if (!window.registered) window.registered = 0;
|
|
1322
|
-
++window.registered;
|
|
1323
1511
|
function onResize() {
|
|
1324
1512
|
// Might be a text scaling operation, clear size caches.
|
|
1325
1513
|
d.cachedCharWidth = d.cachedTextHeight = null;
|
|
1326
1514
|
clearCaches(cm);
|
|
1327
|
-
|
|
1515
|
+
runInOp(cm, bind(regChange, cm));
|
|
1328
1516
|
}
|
|
1329
1517
|
on(window, "resize", onResize);
|
|
1330
1518
|
// Above handler holds on to the editor and its data structures.
|
|
1331
1519
|
// Here we poll to unregister it when the editor is no longer in
|
|
1332
1520
|
// the document, so that it can be garbage-collected.
|
|
1333
|
-
|
|
1521
|
+
function unregister() {
|
|
1334
1522
|
for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
|
|
1335
1523
|
if (p) setTimeout(unregister, 5000);
|
|
1336
|
-
else
|
|
1337
|
-
}
|
|
1524
|
+
else off(window, "resize", onResize);
|
|
1525
|
+
}
|
|
1526
|
+
setTimeout(unregister, 5000);
|
|
1338
1527
|
|
|
1339
1528
|
on(d.input, "keyup", operation(cm, function(e) {
|
|
1340
1529
|
if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
|
|
1341
|
-
if (
|
|
1530
|
+
if (e.keyCode == 16) cm.doc.sel.shift = false;
|
|
1342
1531
|
}));
|
|
1343
1532
|
on(d.input, "input", bind(fastPoll, cm));
|
|
1344
1533
|
on(d.input, "keydown", operation(cm, onKeyDown));
|
|
@@ -1358,11 +1547,11 @@ window.CodeMirror = (function() {
|
|
|
1358
1547
|
}
|
|
1359
1548
|
on(d.scroller, "paste", function(e){
|
|
1360
1549
|
if (eventInWidget(d, e)) return;
|
|
1361
|
-
focusInput(cm);
|
|
1550
|
+
focusInput(cm);
|
|
1362
1551
|
fastPoll(cm);
|
|
1363
1552
|
});
|
|
1364
1553
|
on(d.input, "paste", function() {
|
|
1365
|
-
|
|
1554
|
+
cm.state.pasteIncoming = true;
|
|
1366
1555
|
fastPoll(cm);
|
|
1367
1556
|
});
|
|
1368
1557
|
|
|
@@ -1400,7 +1589,7 @@ window.CodeMirror = (function() {
|
|
|
1400
1589
|
target == display.scrollbarV || target == display.scrollbarV.firstChild ||
|
|
1401
1590
|
target == display.scrollbarFiller) return null;
|
|
1402
1591
|
}
|
|
1403
|
-
var x, y, space = display.lineSpace
|
|
1592
|
+
var x, y, space = getRect(display.lineSpace);
|
|
1404
1593
|
// Fails unpredictably on IE[67] when mouse is dragged around quickly.
|
|
1405
1594
|
try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
|
|
1406
1595
|
return coordsChar(cm, x - space.left, y - space.top);
|
|
@@ -1408,8 +1597,8 @@ window.CodeMirror = (function() {
|
|
|
1408
1597
|
|
|
1409
1598
|
var lastClick, lastDoubleClick;
|
|
1410
1599
|
function onMouseDown(e) {
|
|
1411
|
-
var cm = this, display = cm.display,
|
|
1412
|
-
sel.shift =
|
|
1600
|
+
var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
|
|
1601
|
+
sel.shift = e.shiftKey;
|
|
1413
1602
|
|
|
1414
1603
|
if (eventInWidget(display, e)) {
|
|
1415
1604
|
if (!webkit) {
|
|
@@ -1423,10 +1612,10 @@ window.CodeMirror = (function() {
|
|
|
1423
1612
|
|
|
1424
1613
|
switch (e_button(e)) {
|
|
1425
1614
|
case 3:
|
|
1426
|
-
if (
|
|
1615
|
+
if (captureMiddleClick) onContextMenu.call(cm, cm, e);
|
|
1427
1616
|
return;
|
|
1428
1617
|
case 2:
|
|
1429
|
-
if (start) extendSelection(cm, start);
|
|
1618
|
+
if (start) extendSelection(cm.doc, start);
|
|
1430
1619
|
setTimeout(bind(focusInput, cm), 20);
|
|
1431
1620
|
e_preventDefault(e);
|
|
1432
1621
|
return;
|
|
@@ -1436,7 +1625,7 @@ window.CodeMirror = (function() {
|
|
|
1436
1625
|
// selection.
|
|
1437
1626
|
if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
|
|
1438
1627
|
|
|
1439
|
-
if (!
|
|
1628
|
+
if (!cm.state.focused) onFocus(cm);
|
|
1440
1629
|
|
|
1441
1630
|
var now = +new Date, type = "single";
|
|
1442
1631
|
if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
|
|
@@ -1449,7 +1638,7 @@ window.CodeMirror = (function() {
|
|
|
1449
1638
|
lastDoubleClick = {time: now, pos: start};
|
|
1450
1639
|
e_preventDefault(e);
|
|
1451
1640
|
var word = findWordAt(getLine(doc, start.line).text, start);
|
|
1452
|
-
extendSelection(cm, word.from, word.to);
|
|
1641
|
+
extendSelection(cm.doc, word.from, word.to);
|
|
1453
1642
|
} else { lastClick = {time: now, pos: start}; }
|
|
1454
1643
|
|
|
1455
1644
|
var last = start;
|
|
@@ -1457,18 +1646,18 @@ window.CodeMirror = (function() {
|
|
|
1457
1646
|
!posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
|
|
1458
1647
|
var dragEnd = operation(cm, function(e2) {
|
|
1459
1648
|
if (webkit) display.scroller.draggable = false;
|
|
1460
|
-
|
|
1649
|
+
cm.state.draggingText = false;
|
|
1461
1650
|
off(document, "mouseup", dragEnd);
|
|
1462
1651
|
off(display.scroller, "drop", dragEnd);
|
|
1463
1652
|
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
|
|
1464
1653
|
e_preventDefault(e2);
|
|
1465
|
-
extendSelection(cm, start);
|
|
1654
|
+
extendSelection(cm.doc, start);
|
|
1466
1655
|
focusInput(cm);
|
|
1467
1656
|
}
|
|
1468
1657
|
});
|
|
1469
1658
|
// Let the drag handler handle this.
|
|
1470
1659
|
if (webkit) display.scroller.draggable = true;
|
|
1471
|
-
|
|
1660
|
+
cm.state.draggingText = dragEnd;
|
|
1472
1661
|
// IE's approach to draggable
|
|
1473
1662
|
if (display.scroller.dragDrop) display.scroller.dragDrop();
|
|
1474
1663
|
on(document, "mouseup", dragEnd);
|
|
@@ -1476,13 +1665,16 @@ window.CodeMirror = (function() {
|
|
|
1476
1665
|
return;
|
|
1477
1666
|
}
|
|
1478
1667
|
e_preventDefault(e);
|
|
1479
|
-
if (type == "single") extendSelection(cm, clipPos(doc, start));
|
|
1668
|
+
if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
|
|
1480
1669
|
|
|
1481
|
-
var startstart = sel.from, startend = sel.to;
|
|
1670
|
+
var startstart = sel.from, startend = sel.to, lastPos = start;
|
|
1482
1671
|
|
|
1483
1672
|
function doSelect(cur) {
|
|
1673
|
+
if (posEq(lastPos, cur)) return;
|
|
1674
|
+
lastPos = cur;
|
|
1675
|
+
|
|
1484
1676
|
if (type == "single") {
|
|
1485
|
-
extendSelection(cm, clipPos(doc, start), cur);
|
|
1677
|
+
extendSelection(cm.doc, clipPos(doc, start), cur);
|
|
1486
1678
|
return;
|
|
1487
1679
|
}
|
|
1488
1680
|
|
|
@@ -1490,15 +1682,15 @@ window.CodeMirror = (function() {
|
|
|
1490
1682
|
startend = clipPos(doc, startend);
|
|
1491
1683
|
if (type == "double") {
|
|
1492
1684
|
var word = findWordAt(getLine(doc, cur.line).text, cur);
|
|
1493
|
-
if (posLess(cur, startstart)) extendSelection(cm, word.from, startend);
|
|
1494
|
-
else extendSelection(cm, startstart, word.to);
|
|
1685
|
+
if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
|
|
1686
|
+
else extendSelection(cm.doc, startstart, word.to);
|
|
1495
1687
|
} else if (type == "triple") {
|
|
1496
|
-
if (posLess(cur, startstart)) extendSelection(cm, startend, clipPos(doc,
|
|
1497
|
-
else extendSelection(cm, startstart, clipPos(doc,
|
|
1688
|
+
if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
|
|
1689
|
+
else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
|
|
1498
1690
|
}
|
|
1499
1691
|
}
|
|
1500
1692
|
|
|
1501
|
-
var editorSize = display.wrapper
|
|
1693
|
+
var editorSize = getRect(display.wrapper);
|
|
1502
1694
|
// Used to ensure timeout re-tries don't fire when another extend
|
|
1503
1695
|
// happened in the meantime (clearTimeout isn't reliable -- at
|
|
1504
1696
|
// least on Chrome, the timeouts still happen even when cleared,
|
|
@@ -1510,7 +1702,7 @@ window.CodeMirror = (function() {
|
|
|
1510
1702
|
var cur = posFromMouse(cm, e, true);
|
|
1511
1703
|
if (!cur) return;
|
|
1512
1704
|
if (!posEq(cur, last)) {
|
|
1513
|
-
if (!
|
|
1705
|
+
if (!cm.state.focused) onFocus(cm);
|
|
1514
1706
|
last = cur;
|
|
1515
1707
|
doSelect(cur);
|
|
1516
1708
|
var visible = visibleLines(display, doc);
|
|
@@ -1559,11 +1751,8 @@ window.CodeMirror = (function() {
|
|
|
1559
1751
|
reader.onload = function() {
|
|
1560
1752
|
text[i] = reader.result;
|
|
1561
1753
|
if (++read == n) {
|
|
1562
|
-
pos = clipPos(cm.
|
|
1563
|
-
|
|
1564
|
-
var end = replaceRange(cm, text.join(""), pos, pos, "paste");
|
|
1565
|
-
setSelection(cm, pos, end);
|
|
1566
|
-
})();
|
|
1754
|
+
pos = clipPos(cm.doc, pos);
|
|
1755
|
+
makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
|
|
1567
1756
|
}
|
|
1568
1757
|
};
|
|
1569
1758
|
reader.readAsText(file);
|
|
@@ -1571,8 +1760,8 @@ window.CodeMirror = (function() {
|
|
|
1571
1760
|
for (var i = 0; i < n; ++i) loadFile(files[i], i);
|
|
1572
1761
|
} else {
|
|
1573
1762
|
// Don't do a replace if the drop happened inside of the selected text.
|
|
1574
|
-
if (cm.
|
|
1575
|
-
cm.
|
|
1763
|
+
if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
|
|
1764
|
+
cm.state.draggingText(e);
|
|
1576
1765
|
// Ensure the editor is re-focused
|
|
1577
1766
|
setTimeout(bind(focusInput, cm), 20);
|
|
1578
1767
|
return;
|
|
@@ -1580,9 +1769,9 @@ window.CodeMirror = (function() {
|
|
|
1580
1769
|
try {
|
|
1581
1770
|
var text = e.dataTransfer.getData("Text");
|
|
1582
1771
|
if (text) {
|
|
1583
|
-
var curFrom = cm.
|
|
1584
|
-
setSelection(cm, pos, pos);
|
|
1585
|
-
if (cm.
|
|
1772
|
+
var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
|
|
1773
|
+
setSelection(cm.doc, pos, pos);
|
|
1774
|
+
if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
|
|
1586
1775
|
cm.replaceSelection(text, null, "paste");
|
|
1587
1776
|
focusInput(cm);
|
|
1588
1777
|
onFocus(cm);
|
|
@@ -1597,20 +1786,20 @@ window.CodeMirror = (function() {
|
|
|
1597
1786
|
try { var mX = e.clientX, mY = e.clientY; }
|
|
1598
1787
|
catch(e) { return false; }
|
|
1599
1788
|
|
|
1600
|
-
if (mX >= Math.floor(display.gutters
|
|
1789
|
+
if (mX >= Math.floor(getRect(display.gutters).right)) return false;
|
|
1601
1790
|
e_preventDefault(e);
|
|
1602
1791
|
if (!hasHandler(cm, "gutterClick")) return true;
|
|
1603
1792
|
|
|
1604
|
-
var lineBox = display.lineDiv
|
|
1793
|
+
var lineBox = getRect(display.lineDiv);
|
|
1605
1794
|
if (mY > lineBox.bottom) return true;
|
|
1606
1795
|
mY -= lineBox.top - display.viewOffset;
|
|
1607
1796
|
|
|
1608
1797
|
for (var i = 0; i < cm.options.gutters.length; ++i) {
|
|
1609
1798
|
var g = display.gutters.childNodes[i];
|
|
1610
|
-
if (g && g
|
|
1611
|
-
var line = lineAtHeight(cm.
|
|
1799
|
+
if (g && getRect(g).right >= mX) {
|
|
1800
|
+
var line = lineAtHeight(cm.doc, mY);
|
|
1612
1801
|
var gutter = cm.options.gutters[i];
|
|
1613
|
-
signalLater(cm,
|
|
1802
|
+
signalLater(cm, "gutterClick", cm, line, gutter, e);
|
|
1614
1803
|
break;
|
|
1615
1804
|
}
|
|
1616
1805
|
}
|
|
@@ -1618,14 +1807,15 @@ window.CodeMirror = (function() {
|
|
|
1618
1807
|
}
|
|
1619
1808
|
|
|
1620
1809
|
function onDragStart(cm, e) {
|
|
1810
|
+
if (ie && !cm.state.draggingText) { e_stop(e); return; }
|
|
1621
1811
|
if (eventInWidget(cm.display, e)) return;
|
|
1622
|
-
|
|
1812
|
+
|
|
1623
1813
|
var txt = cm.getSelection();
|
|
1624
1814
|
e.dataTransfer.setData("Text", txt);
|
|
1625
1815
|
|
|
1626
1816
|
// Use dummy image instead of default browsers image.
|
|
1627
1817
|
// Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
|
|
1628
|
-
if (e.dataTransfer.setDragImage
|
|
1818
|
+
if (e.dataTransfer.setDragImage) {
|
|
1629
1819
|
var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
|
|
1630
1820
|
if (opera) {
|
|
1631
1821
|
img.width = img.height = 1;
|
|
@@ -1633,23 +1823,32 @@ window.CodeMirror = (function() {
|
|
|
1633
1823
|
// Force a relayout, or Opera won't use our image for some obscure reason
|
|
1634
1824
|
img._top = img.offsetTop;
|
|
1635
1825
|
}
|
|
1826
|
+
if (safari) {
|
|
1827
|
+
if (cm.display.dragImg) {
|
|
1828
|
+
img = cm.display.dragImg;
|
|
1829
|
+
} else {
|
|
1830
|
+
cm.display.dragImg = img;
|
|
1831
|
+
img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
|
|
1832
|
+
cm.display.wrapper.appendChild(img);
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1636
1835
|
e.dataTransfer.setDragImage(img, 0, 0);
|
|
1637
1836
|
if (opera) img.parentNode.removeChild(img);
|
|
1638
1837
|
}
|
|
1639
1838
|
}
|
|
1640
1839
|
|
|
1641
1840
|
function setScrollTop(cm, val) {
|
|
1642
|
-
if (Math.abs(cm.
|
|
1643
|
-
cm.
|
|
1841
|
+
if (Math.abs(cm.doc.scrollTop - val) < 2) return;
|
|
1842
|
+
cm.doc.scrollTop = val;
|
|
1644
1843
|
if (!gecko) updateDisplay(cm, [], val);
|
|
1645
1844
|
if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
|
|
1646
1845
|
if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
|
|
1647
1846
|
if (gecko) updateDisplay(cm, []);
|
|
1648
1847
|
}
|
|
1649
1848
|
function setScrollLeft(cm, val, isScroller) {
|
|
1650
|
-
if (isScroller ? val == cm.
|
|
1849
|
+
if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
|
|
1651
1850
|
val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
|
|
1652
|
-
cm.
|
|
1851
|
+
cm.doc.scrollLeft = val;
|
|
1653
1852
|
alignHorizontally(cm);
|
|
1654
1853
|
if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
|
|
1655
1854
|
if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
|
|
@@ -1682,6 +1881,11 @@ window.CodeMirror = (function() {
|
|
|
1682
1881
|
if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
|
|
1683
1882
|
else if (dy == null) dy = e.wheelDelta;
|
|
1684
1883
|
|
|
1884
|
+
var display = cm.display, scroll = display.scroller;
|
|
1885
|
+
// Quit if there's nothing to scroll here
|
|
1886
|
+
if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
|
|
1887
|
+
dy && scroll.scrollHeight > scroll.clientHeight)) return;
|
|
1888
|
+
|
|
1685
1889
|
// Webkit browsers on OS X abort momentum scrolls when the target
|
|
1686
1890
|
// of the scroll event is removed from the scrollable element.
|
|
1687
1891
|
// This hack (see related code in patchDisplay) makes sure the
|
|
@@ -1695,7 +1899,6 @@ window.CodeMirror = (function() {
|
|
|
1695
1899
|
}
|
|
1696
1900
|
}
|
|
1697
1901
|
|
|
1698
|
-
var display = cm.display, scroll = display.scroller;
|
|
1699
1902
|
// On some browsers, horizontal scrolling will cause redraws to
|
|
1700
1903
|
// happen before the gutter has been realigned, causing it to
|
|
1701
1904
|
// wriggle around in a most unseemly way. When we have an
|
|
@@ -1713,9 +1916,9 @@ window.CodeMirror = (function() {
|
|
|
1713
1916
|
|
|
1714
1917
|
if (dy && wheelPixelsPerUnit != null) {
|
|
1715
1918
|
var pixels = dy * wheelPixelsPerUnit;
|
|
1716
|
-
var top = cm.
|
|
1919
|
+
var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
|
|
1717
1920
|
if (pixels < 0) top = Math.max(0, top + pixels - 50);
|
|
1718
|
-
else bot = Math.min(cm.
|
|
1921
|
+
else bot = Math.min(cm.doc.height, bot + pixels + 50);
|
|
1719
1922
|
updateDisplay(cm, [], {top: top, bottom: bot});
|
|
1720
1923
|
}
|
|
1721
1924
|
|
|
@@ -1748,25 +1951,22 @@ window.CodeMirror = (function() {
|
|
|
1748
1951
|
// Ensure previous input has been read, so that the handler sees a
|
|
1749
1952
|
// consistent view of the document
|
|
1750
1953
|
if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
|
|
1751
|
-
var
|
|
1954
|
+
var doc = cm.doc, prevShift = doc.sel.shift, done = false;
|
|
1752
1955
|
try {
|
|
1753
|
-
if (isReadOnly(cm))
|
|
1754
|
-
if (dropShift)
|
|
1755
|
-
bound(cm);
|
|
1756
|
-
} catch(e) {
|
|
1757
|
-
if (e != Pass) throw e;
|
|
1758
|
-
return false;
|
|
1956
|
+
if (isReadOnly(cm)) cm.state.suppressEdits = true;
|
|
1957
|
+
if (dropShift) doc.sel.shift = false;
|
|
1958
|
+
done = bound(cm) != Pass;
|
|
1759
1959
|
} finally {
|
|
1760
|
-
|
|
1761
|
-
|
|
1960
|
+
doc.sel.shift = prevShift;
|
|
1961
|
+
cm.state.suppressEdits = false;
|
|
1762
1962
|
}
|
|
1763
|
-
return
|
|
1963
|
+
return done;
|
|
1764
1964
|
}
|
|
1765
1965
|
|
|
1766
1966
|
function allKeyMaps(cm) {
|
|
1767
|
-
var maps = cm.
|
|
1967
|
+
var maps = cm.state.keyMaps.slice(0);
|
|
1968
|
+
if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
|
|
1768
1969
|
maps.push(cm.options.keyMap);
|
|
1769
|
-
if (cm.options.extraKeys) maps.unshift(cm.options.extraKeys);
|
|
1770
1970
|
return maps;
|
|
1771
1971
|
}
|
|
1772
1972
|
|
|
@@ -1780,27 +1980,23 @@ window.CodeMirror = (function() {
|
|
|
1780
1980
|
cm.options.keyMap = (next.call ? next.call(null, cm) : next);
|
|
1781
1981
|
}, 50);
|
|
1782
1982
|
|
|
1783
|
-
var name =
|
|
1784
|
-
if (name
|
|
1785
|
-
if (e_prop(e, "altKey")) name = "Alt-" + name;
|
|
1786
|
-
if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name;
|
|
1787
|
-
if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name;
|
|
1788
|
-
|
|
1789
|
-
var stopped = false;
|
|
1790
|
-
function stop() { stopped = true; }
|
|
1983
|
+
var name = keyName(e, true), handled = false;
|
|
1984
|
+
if (!name) return false;
|
|
1791
1985
|
var keymaps = allKeyMaps(cm);
|
|
1792
1986
|
|
|
1793
|
-
if (
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1987
|
+
if (e.shiftKey) {
|
|
1988
|
+
// First try to resolve full name (including 'Shift-'). Failing
|
|
1989
|
+
// that, see if there is a cursor-motion command (starting with
|
|
1990
|
+
// 'go') bound to the keyname without 'Shift-'.
|
|
1991
|
+
handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
|
|
1992
|
+
|| lookupKey(name, keymaps, function(b) {
|
|
1993
|
+
if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(cm, b);
|
|
1994
|
+
});
|
|
1799
1995
|
} else {
|
|
1800
|
-
handled = lookupKey(name, keymaps,
|
|
1801
|
-
function(b) { return doHandleBinding(cm, b); }, stop);
|
|
1996
|
+
handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
|
|
1802
1997
|
}
|
|
1803
|
-
if (
|
|
1998
|
+
if (handled == "stop") handled = false;
|
|
1999
|
+
|
|
1804
2000
|
if (handled) {
|
|
1805
2001
|
e_preventDefault(e);
|
|
1806
2002
|
restartBlink(cm);
|
|
@@ -1822,18 +2018,18 @@ window.CodeMirror = (function() {
|
|
|
1822
2018
|
var lastStoppedKey = null;
|
|
1823
2019
|
function onKeyDown(e) {
|
|
1824
2020
|
var cm = this;
|
|
1825
|
-
if (!cm.
|
|
2021
|
+
if (!cm.state.focused) onFocus(cm);
|
|
1826
2022
|
if (ie && e.keyCode == 27) { e.returnValue = false; }
|
|
1827
2023
|
if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
|
|
1828
|
-
var code =
|
|
2024
|
+
var code = e.keyCode;
|
|
1829
2025
|
// IE does strange things with escape.
|
|
1830
|
-
cm.
|
|
2026
|
+
cm.doc.sel.shift = code == 16 || e.shiftKey;
|
|
1831
2027
|
// First give onKeyEvent option a chance to handle this.
|
|
1832
2028
|
var handled = handleKeyBinding(cm, e);
|
|
1833
2029
|
if (opera) {
|
|
1834
2030
|
lastStoppedKey = handled ? code : null;
|
|
1835
2031
|
// Opera has no cut event... we try to at least catch the key combo
|
|
1836
|
-
if (!handled && code == 88 && !hasCopyEvent &&
|
|
2032
|
+
if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
|
|
1837
2033
|
cm.replaceSelection("");
|
|
1838
2034
|
}
|
|
1839
2035
|
}
|
|
@@ -1841,56 +2037,56 @@ window.CodeMirror = (function() {
|
|
|
1841
2037
|
function onKeyPress(e) {
|
|
1842
2038
|
var cm = this;
|
|
1843
2039
|
if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
|
|
1844
|
-
var keyCode =
|
|
2040
|
+
var keyCode = e.keyCode, charCode = e.charCode;
|
|
1845
2041
|
if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
|
|
1846
2042
|
if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
|
|
1847
2043
|
var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
|
|
1848
|
-
if (this.options.electricChars && this.
|
|
2044
|
+
if (this.options.electricChars && this.doc.mode.electricChars &&
|
|
1849
2045
|
this.options.smartIndent && !isReadOnly(this) &&
|
|
1850
|
-
this.
|
|
1851
|
-
setTimeout(operation(cm, function() {indentLine(cm, cm.
|
|
2046
|
+
this.doc.mode.electricChars.indexOf(ch) > -1)
|
|
2047
|
+
setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
|
|
1852
2048
|
if (handleCharBinding(cm, e, ch)) return;
|
|
2049
|
+
if (ie && !ie_lt9) cm.display.inputHasSelection = null;
|
|
1853
2050
|
fastPoll(cm);
|
|
1854
2051
|
}
|
|
1855
2052
|
|
|
1856
2053
|
function onFocus(cm) {
|
|
1857
2054
|
if (cm.options.readOnly == "nocursor") return;
|
|
1858
|
-
if (!cm.
|
|
2055
|
+
if (!cm.state.focused) {
|
|
1859
2056
|
signal(cm, "focus", cm);
|
|
1860
|
-
cm.
|
|
1861
|
-
if (cm.display.
|
|
1862
|
-
cm.display.
|
|
2057
|
+
cm.state.focused = true;
|
|
2058
|
+
if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
|
|
2059
|
+
cm.display.wrapper.className += " CodeMirror-focused";
|
|
1863
2060
|
resetInput(cm, true);
|
|
1864
2061
|
}
|
|
1865
2062
|
slowPoll(cm);
|
|
1866
2063
|
restartBlink(cm);
|
|
1867
2064
|
}
|
|
1868
2065
|
function onBlur(cm) {
|
|
1869
|
-
if (cm.
|
|
2066
|
+
if (cm.state.focused) {
|
|
1870
2067
|
signal(cm, "blur", cm);
|
|
1871
|
-
cm.
|
|
1872
|
-
cm.display.
|
|
2068
|
+
cm.state.focused = false;
|
|
2069
|
+
cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
|
|
1873
2070
|
}
|
|
1874
2071
|
clearInterval(cm.display.blinker);
|
|
1875
|
-
setTimeout(function() {if (!cm.
|
|
2072
|
+
setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
|
|
1876
2073
|
}
|
|
1877
2074
|
|
|
1878
2075
|
var detectingSelectAll;
|
|
1879
2076
|
function onContextMenu(cm, e) {
|
|
1880
|
-
var display = cm.display;
|
|
2077
|
+
var display = cm.display, sel = cm.doc.sel;
|
|
1881
2078
|
if (eventInWidget(display, e)) return;
|
|
1882
|
-
|
|
1883
|
-
var sel = cm.view.sel;
|
|
2079
|
+
|
|
1884
2080
|
var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
|
|
1885
2081
|
if (!pos || opera) return; // Opera is difficult.
|
|
1886
2082
|
if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
|
|
1887
|
-
operation(cm, setSelection)(cm, pos, pos);
|
|
2083
|
+
operation(cm, setSelection)(cm.doc, pos, pos);
|
|
1888
2084
|
|
|
1889
2085
|
var oldCSS = display.input.style.cssText;
|
|
1890
2086
|
display.inputDiv.style.position = "absolute";
|
|
1891
2087
|
display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
|
|
1892
2088
|
"px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
|
|
1893
|
-
"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
|
|
2089
|
+
"border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
|
|
1894
2090
|
focusInput(cm);
|
|
1895
2091
|
resetInput(cm, true);
|
|
1896
2092
|
// Adds "Select all" to context menu in FF
|
|
@@ -1902,27 +2098,29 @@ window.CodeMirror = (function() {
|
|
|
1902
2098
|
if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
|
|
1903
2099
|
slowPoll(cm);
|
|
1904
2100
|
|
|
1905
|
-
// Try to detect the user choosing select-all
|
|
1906
|
-
if (display.input.selectionStart != null) {
|
|
2101
|
+
// Try to detect the user choosing select-all
|
|
2102
|
+
if (display.input.selectionStart != null && (!ie || ie_lt9)) {
|
|
1907
2103
|
clearTimeout(detectingSelectAll);
|
|
1908
2104
|
var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0;
|
|
1909
2105
|
display.prevInput = " ";
|
|
1910
2106
|
display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
|
|
1911
|
-
|
|
2107
|
+
var poll = function(){
|
|
1912
2108
|
if (display.prevInput == " " && display.input.selectionStart == 0)
|
|
1913
2109
|
operation(cm, commands.selectAll)(cm);
|
|
1914
2110
|
else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
|
|
1915
2111
|
else resetInput(cm);
|
|
1916
|
-
}
|
|
2112
|
+
};
|
|
2113
|
+
detectingSelectAll = setTimeout(poll, 200);
|
|
1917
2114
|
}
|
|
1918
2115
|
}
|
|
1919
2116
|
|
|
1920
|
-
if (
|
|
2117
|
+
if (captureMiddleClick) {
|
|
1921
2118
|
e_stop(e);
|
|
1922
|
-
|
|
2119
|
+
var mouseup = function() {
|
|
1923
2120
|
off(window, "mouseup", mouseup);
|
|
1924
2121
|
setTimeout(rehide, 20);
|
|
1925
|
-
}
|
|
2122
|
+
};
|
|
2123
|
+
on(window, "mouseup", mouseup);
|
|
1926
2124
|
} else {
|
|
1927
2125
|
setTimeout(rehide, 50);
|
|
1928
2126
|
}
|
|
@@ -1930,124 +2128,212 @@ window.CodeMirror = (function() {
|
|
|
1930
2128
|
|
|
1931
2129
|
// UPDATING
|
|
1932
2130
|
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
2131
|
+
function changeEnd(change) {
|
|
2132
|
+
if (!change.text) return change.to;
|
|
2133
|
+
return Pos(change.from.line + change.text.length - 1,
|
|
2134
|
+
lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
// Make sure a position will be valid after the given change.
|
|
2138
|
+
function clipPostChange(doc, change, pos) {
|
|
2139
|
+
if (!posLess(change.from, pos)) return clipPos(doc, pos);
|
|
2140
|
+
var diff = (change.text.length - 1) - (change.to.line - change.from.line);
|
|
2141
|
+
if (pos.line > change.to.line + diff) {
|
|
2142
|
+
var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
|
|
2143
|
+
if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
|
|
2144
|
+
return clipToLen(pos, getLine(doc, preLine).text.length);
|
|
2145
|
+
}
|
|
2146
|
+
if (pos.line == change.to.line + diff)
|
|
2147
|
+
return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
|
|
2148
|
+
getLine(doc, change.to.line).text.length - change.to.ch);
|
|
2149
|
+
var inside = pos.line - change.from.line;
|
|
2150
|
+
return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
// Hint can be null|"end"|"start"|"around"|{anchor,head}
|
|
2154
|
+
function computeSelAfterChange(doc, change, hint) {
|
|
2155
|
+
if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
|
|
2156
|
+
return {anchor: clipPostChange(doc, change, hint.anchor),
|
|
2157
|
+
head: clipPostChange(doc, change, hint.head)};
|
|
2158
|
+
|
|
2159
|
+
if (hint == "start") return {anchor: change.from, head: change.from};
|
|
2160
|
+
|
|
2161
|
+
var end = changeEnd(change);
|
|
2162
|
+
if (hint == "around") return {anchor: change.from, head: end};
|
|
2163
|
+
if (hint == "end") return {anchor: end, head: end};
|
|
2164
|
+
|
|
2165
|
+
// hint is null, leave the selection alone as much as possible
|
|
2166
|
+
var adjustPos = function(pos) {
|
|
2167
|
+
if (posLess(pos, change.from)) return pos;
|
|
2168
|
+
if (!posLess(change.to, pos)) return end;
|
|
2169
|
+
|
|
2170
|
+
var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
|
|
2171
|
+
if (pos.line == change.to.line) ch += end.ch - change.to.ch;
|
|
2172
|
+
return Pos(line, ch);
|
|
2173
|
+
};
|
|
2174
|
+
return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
function filterChange(doc, change) {
|
|
2178
|
+
var obj = {
|
|
2179
|
+
canceled: false,
|
|
2180
|
+
from: change.from,
|
|
2181
|
+
to: change.to,
|
|
2182
|
+
text: change.text,
|
|
2183
|
+
origin: change.origin,
|
|
2184
|
+
update: function(from, to, text, origin) {
|
|
2185
|
+
if (from) this.from = clipPos(doc, from);
|
|
2186
|
+
if (to) this.to = clipPos(doc, to);
|
|
2187
|
+
if (text) this.text = text;
|
|
2188
|
+
if (origin !== undefined) this.origin = origin;
|
|
2189
|
+
},
|
|
2190
|
+
cancel: function() { this.canceled = true; }
|
|
2191
|
+
};
|
|
2192
|
+
signal(doc, "beforeChange", doc, obj);
|
|
2193
|
+
if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
|
|
2194
|
+
|
|
2195
|
+
if (obj.canceled) return null;
|
|
2196
|
+
return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
// Replace the range from from to to by the strings in replacement.
|
|
2200
|
+
// change is a {from, to, text [, origin]} object
|
|
2201
|
+
function makeChange(doc, change, selUpdate, ignoreReadOnly) {
|
|
2202
|
+
if (doc.cm) {
|
|
2203
|
+
if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
|
|
2204
|
+
if (doc.cm.state.suppressEdits) return;
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
|
|
2208
|
+
change = filterChange(doc, change);
|
|
2209
|
+
if (!change) return;
|
|
2210
|
+
}
|
|
2211
|
+
|
|
1936
2212
|
// Possibly split or suppress the update based on the presence
|
|
1937
2213
|
// of read-only spans in its range.
|
|
1938
|
-
var split = sawReadOnlySpans &&
|
|
1939
|
-
removeReadOnlyRanges(cm.view.doc, from, to);
|
|
2214
|
+
var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
|
|
1940
2215
|
if (split) {
|
|
1941
2216
|
for (var i = split.length - 1; i >= 1; --i)
|
|
1942
|
-
|
|
2217
|
+
makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
|
|
1943
2218
|
if (split.length)
|
|
1944
|
-
|
|
2219
|
+
makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
|
|
1945
2220
|
} else {
|
|
1946
|
-
|
|
2221
|
+
makeChangeNoReadonly(doc, change, selUpdate);
|
|
1947
2222
|
}
|
|
1948
2223
|
}
|
|
1949
2224
|
|
|
1950
|
-
function
|
|
1951
|
-
|
|
2225
|
+
function makeChangeNoReadonly(doc, change, selUpdate) {
|
|
2226
|
+
var selAfter = computeSelAfterChange(doc, change, selUpdate);
|
|
2227
|
+
addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
|
|
1952
2228
|
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
2229
|
+
makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
|
|
2230
|
+
var rebased = [];
|
|
2231
|
+
|
|
2232
|
+
linkedDocs(doc, function(doc, sharedHist) {
|
|
2233
|
+
if (!sharedHist && indexOf(rebased, doc.history) == -1) {
|
|
2234
|
+
rebaseHist(doc.history, change);
|
|
2235
|
+
rebased.push(doc.history);
|
|
2236
|
+
}
|
|
2237
|
+
makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
|
|
1956
2238
|
});
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
if (
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
var
|
|
1968
|
-
|
|
1969
|
-
var anti = {events: [], fromBefore: set.fromAfter, toBefore: set.toAfter,
|
|
1970
|
-
fromAfter: set.fromBefore, toAfter: set.toBefore};
|
|
1971
|
-
for (var i = set.events.length - 1; i >= 0; i -= 1) {
|
|
1972
|
-
hist.dirtyCounter += type == "undo" ? -1 : 1;
|
|
1973
|
-
var change = set.events[i];
|
|
1974
|
-
var replaced = [], end = change.start + change.added;
|
|
1975
|
-
doc.iter(change.start, end, function(line) { replaced.push(newHL(line.text, line.markedSpans)); });
|
|
1976
|
-
anti.events.push({start: change.start, added: change.old.length, old: replaced});
|
|
1977
|
-
var selPos = i ? null : {from: set.fromBefore, to: set.toBefore};
|
|
1978
|
-
updateDocNoUndo(cm, {line: change.start, ch: 0}, {line: end - 1, ch: getLine(doc, end-1).text.length},
|
|
1979
|
-
change.old, selPos, type);
|
|
1980
|
-
}
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
function makeChangeFromHistory(doc, type) {
|
|
2242
|
+
if (doc.cm && doc.cm.state.suppressEdits) return;
|
|
2243
|
+
|
|
2244
|
+
var hist = doc.history;
|
|
2245
|
+
var event = (type == "undo" ? hist.done : hist.undone).pop();
|
|
2246
|
+
if (!event) return;
|
|
2247
|
+
hist.dirtyCounter += type == "undo" ? -1 : 1;
|
|
2248
|
+
|
|
2249
|
+
var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
|
|
2250
|
+
anchorAfter: event.anchorBefore, headAfter: event.headBefore};
|
|
1981
2251
|
(type == "undo" ? hist.undone : hist.done).push(anti);
|
|
2252
|
+
|
|
2253
|
+
for (var i = event.changes.length - 1; i >= 0; --i) {
|
|
2254
|
+
var change = event.changes[i];
|
|
2255
|
+
change.origin = type;
|
|
2256
|
+
anti.changes.push(historyChangeFromChange(doc, change));
|
|
2257
|
+
|
|
2258
|
+
var after = i ? computeSelAfterChange(doc, change, null)
|
|
2259
|
+
: {anchor: event.anchorBefore, head: event.headBefore};
|
|
2260
|
+
makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
|
|
2261
|
+
var rebased = [];
|
|
2262
|
+
|
|
2263
|
+
linkedDocs(doc, function(doc, sharedHist) {
|
|
2264
|
+
if (!sharedHist && indexOf(rebased, doc.history) == -1) {
|
|
2265
|
+
rebaseHist(doc.history, change);
|
|
2266
|
+
rebased.push(doc.history);
|
|
2267
|
+
}
|
|
2268
|
+
makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
function shiftDoc(doc, distance) {
|
|
2274
|
+
function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
|
|
2275
|
+
doc.first += distance;
|
|
2276
|
+
if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
|
|
2277
|
+
doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
|
|
2278
|
+
doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
function makeChangeSingleDoc(doc, change, selAfter, spans) {
|
|
2282
|
+
if (doc.cm && !doc.cm.curOp)
|
|
2283
|
+
return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
|
|
2284
|
+
|
|
2285
|
+
if (change.to.line < doc.first) {
|
|
2286
|
+
shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
if (change.from.line > doc.lastLine()) return;
|
|
2290
|
+
|
|
2291
|
+
// Clip the change to the size of this doc
|
|
2292
|
+
if (change.from.line < doc.first) {
|
|
2293
|
+
var shift = change.text.length - 1 - (doc.first - change.from.line);
|
|
2294
|
+
shiftDoc(doc, shift);
|
|
2295
|
+
change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
|
|
2296
|
+
text: [lst(change.text)], origin: change.origin};
|
|
2297
|
+
}
|
|
2298
|
+
var last = doc.lastLine();
|
|
2299
|
+
if (change.to.line > last) {
|
|
2300
|
+
change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
|
|
2301
|
+
text: [change.text[0]], origin: change.origin};
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
change.removed = getBetween(doc, change.from, change.to);
|
|
2305
|
+
|
|
2306
|
+
if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
|
|
2307
|
+
if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
|
|
2308
|
+
else updateDoc(doc, change, spans, selAfter);
|
|
1982
2309
|
}
|
|
1983
2310
|
|
|
1984
|
-
function
|
|
1985
|
-
var
|
|
1986
|
-
if (view.suppressEdits) return;
|
|
2311
|
+
function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
|
|
2312
|
+
var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
|
|
1987
2313
|
|
|
1988
|
-
var nlines = to.line - from.line, firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
|
|
1989
2314
|
var recomputeMaxLength = false, checkWidthStart = from.line;
|
|
1990
2315
|
if (!cm.options.lineWrapping) {
|
|
1991
|
-
checkWidthStart = lineNo(visualLine(doc,
|
|
2316
|
+
checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
|
|
1992
2317
|
doc.iter(checkWidthStart, to.line + 1, function(line) {
|
|
1993
|
-
if (line ==
|
|
2318
|
+
if (line == display.maxLine) {
|
|
1994
2319
|
recomputeMaxLength = true;
|
|
1995
2320
|
return true;
|
|
1996
2321
|
}
|
|
1997
2322
|
});
|
|
1998
2323
|
}
|
|
1999
2324
|
|
|
2000
|
-
|
|
2325
|
+
if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
|
|
2326
|
+
cm.curOp.cursorActivity = true;
|
|
2001
2327
|
|
|
2002
|
-
|
|
2003
|
-
if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") {
|
|
2004
|
-
// This is a whole-line replace. Treated specially to make
|
|
2005
|
-
// sure line objects move the way they are supposed to.
|
|
2006
|
-
var added = [];
|
|
2007
|
-
for (var i = 0, e = lines.length - 1; i < e; ++i)
|
|
2008
|
-
added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
|
|
2009
|
-
updateLine(cm, lastLine, lastLine.text, hlSpans(lastHL));
|
|
2010
|
-
if (nlines) doc.remove(from.line, nlines, cm);
|
|
2011
|
-
if (added.length) doc.insert(from.line, added);
|
|
2012
|
-
} else if (firstLine == lastLine) {
|
|
2013
|
-
if (lines.length == 1) {
|
|
2014
|
-
updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) +
|
|
2015
|
-
firstLine.text.slice(to.ch), hlSpans(lines[0]));
|
|
2016
|
-
} else {
|
|
2017
|
-
for (var added = [], i = 1, e = lines.length - 1; i < e; ++i)
|
|
2018
|
-
added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
|
|
2019
|
-
added.push(makeLine(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL), th));
|
|
2020
|
-
updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
|
|
2021
|
-
doc.insert(from.line + 1, added);
|
|
2022
|
-
}
|
|
2023
|
-
} else if (lines.length == 1) {
|
|
2024
|
-
updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) +
|
|
2025
|
-
lastLine.text.slice(to.ch), hlSpans(lines[0]));
|
|
2026
|
-
doc.remove(from.line + 1, nlines, cm);
|
|
2027
|
-
} else {
|
|
2028
|
-
var added = [];
|
|
2029
|
-
updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
|
|
2030
|
-
updateLine(cm, lastLine, hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL));
|
|
2031
|
-
for (var i = 1, e = lines.length - 1; i < e; ++i)
|
|
2032
|
-
added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
|
|
2033
|
-
if (nlines > 1) doc.remove(from.line + 1, nlines - 1, cm);
|
|
2034
|
-
doc.insert(from.line + 1, added);
|
|
2035
|
-
}
|
|
2328
|
+
updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
|
|
2036
2329
|
|
|
2037
|
-
if (cm.options.lineWrapping) {
|
|
2038
|
-
|
|
2039
|
-
doc.iter(from.line, from.line + lines.length, function(line) {
|
|
2040
|
-
if (line.height == 0) return;
|
|
2041
|
-
var guess = (Math.ceil(line.text.length / perLine) || 1) * th;
|
|
2042
|
-
if (guess != line.height) updateLineHeight(line, guess);
|
|
2043
|
-
});
|
|
2044
|
-
} else {
|
|
2045
|
-
doc.iter(checkWidthStart, from.line + lines.length, function(line) {
|
|
2330
|
+
if (!cm.options.lineWrapping) {
|
|
2331
|
+
doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
|
|
2046
2332
|
var len = lineLength(doc, line);
|
|
2047
|
-
if (len >
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2333
|
+
if (len > display.maxLineLength) {
|
|
2334
|
+
display.maxLine = line;
|
|
2335
|
+
display.maxLineLength = len;
|
|
2336
|
+
display.maxLineChanged = true;
|
|
2051
2337
|
recomputeMaxLength = false;
|
|
2052
2338
|
}
|
|
2053
2339
|
});
|
|
@@ -2055,82 +2341,66 @@ window.CodeMirror = (function() {
|
|
|
2055
2341
|
}
|
|
2056
2342
|
|
|
2057
2343
|
// Adjust frontier, schedule worker
|
|
2058
|
-
|
|
2344
|
+
doc.frontier = Math.min(doc.frontier, from.line);
|
|
2059
2345
|
startWorker(cm, 400);
|
|
2060
2346
|
|
|
2061
|
-
var lendiff =
|
|
2347
|
+
var lendiff = change.text.length - (to.line - from.line) - 1;
|
|
2062
2348
|
// Remember that these lines changed, for updating the display
|
|
2063
2349
|
regChange(cm, from.line, to.line + 1, lendiff);
|
|
2350
|
+
|
|
2064
2351
|
if (hasHandler(cm, "change")) {
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
var changeObj = {from: from, to: to, text: lines, origin: origin};
|
|
2352
|
+
var changeObj = {from: from, to: to,
|
|
2353
|
+
text: change.text,
|
|
2354
|
+
removed: change.removed,
|
|
2355
|
+
origin: change.origin};
|
|
2070
2356
|
if (cm.curOp.textChanged) {
|
|
2071
2357
|
for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
|
|
2072
2358
|
cur.next = changeObj;
|
|
2073
2359
|
} else cm.curOp.textChanged = changeObj;
|
|
2074
2360
|
}
|
|
2075
|
-
|
|
2076
|
-
// Update the selection
|
|
2077
|
-
var newSelFrom, newSelTo, end = {line: from.line + lines.length - 1,
|
|
2078
|
-
ch: hlText(lastHL).length + (lines.length == 1 ? from.ch : 0)};
|
|
2079
|
-
if (selUpdate && typeof selUpdate != "string") {
|
|
2080
|
-
if (selUpdate.from) { newSelFrom = selUpdate.from; newSelTo = selUpdate.to; }
|
|
2081
|
-
else newSelFrom = newSelTo = selUpdate;
|
|
2082
|
-
} else if (selUpdate == "end") {
|
|
2083
|
-
newSelFrom = newSelTo = end;
|
|
2084
|
-
} else if (selUpdate == "start") {
|
|
2085
|
-
newSelFrom = newSelTo = from;
|
|
2086
|
-
} else if (selUpdate == "around") {
|
|
2087
|
-
newSelFrom = from; newSelTo = end;
|
|
2088
|
-
} else {
|
|
2089
|
-
var adjustPos = function(pos) {
|
|
2090
|
-
if (posLess(pos, from)) return pos;
|
|
2091
|
-
if (!posLess(to, pos)) return end;
|
|
2092
|
-
var line = pos.line + lendiff;
|
|
2093
|
-
var ch = pos.ch;
|
|
2094
|
-
if (pos.line == to.line)
|
|
2095
|
-
ch += hlText(lastHL).length - (to.ch - (to.line == from.line ? from.ch : 0));
|
|
2096
|
-
return {line: line, ch: ch};
|
|
2097
|
-
};
|
|
2098
|
-
newSelFrom = adjustPos(view.sel.from);
|
|
2099
|
-
newSelTo = adjustPos(view.sel.to);
|
|
2100
|
-
}
|
|
2101
|
-
setSelection(cm, newSelFrom, newSelTo, null, true);
|
|
2102
|
-
return end;
|
|
2103
2361
|
}
|
|
2104
2362
|
|
|
2105
|
-
function replaceRange(
|
|
2363
|
+
function replaceRange(doc, code, from, to, origin) {
|
|
2106
2364
|
if (!to) to = from;
|
|
2107
2365
|
if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
|
|
2108
|
-
|
|
2366
|
+
if (typeof code == "string") code = splitLines(code);
|
|
2367
|
+
makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
|
|
2109
2368
|
}
|
|
2110
2369
|
|
|
2111
|
-
//
|
|
2370
|
+
// POSITION OBJECT
|
|
2371
|
+
|
|
2372
|
+
function Pos(line, ch) {
|
|
2373
|
+
if (!(this instanceof Pos)) return new Pos(line, ch);
|
|
2374
|
+
this.line = line; this.ch = ch;
|
|
2375
|
+
}
|
|
2376
|
+
CodeMirror.Pos = Pos;
|
|
2112
2377
|
|
|
2113
2378
|
function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
|
|
2114
2379
|
function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
|
|
2115
|
-
function copyPos(x) {return
|
|
2380
|
+
function copyPos(x) {return Pos(x.line, x.ch);}
|
|
2381
|
+
|
|
2382
|
+
// SELECTION
|
|
2116
2383
|
|
|
2117
|
-
function clipLine(doc, n) {return Math.max(
|
|
2384
|
+
function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
|
|
2118
2385
|
function clipPos(doc, pos) {
|
|
2119
|
-
if (pos.line <
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2386
|
+
if (pos.line < doc.first) return Pos(doc.first, 0);
|
|
2387
|
+
var last = doc.first + doc.size - 1;
|
|
2388
|
+
if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
|
|
2389
|
+
return clipToLen(pos, getLine(doc, pos.line).text.length);
|
|
2390
|
+
}
|
|
2391
|
+
function clipToLen(pos, linelen) {
|
|
2392
|
+
var ch = pos.ch;
|
|
2393
|
+
if (ch == null || ch > linelen) return Pos(pos.line, linelen);
|
|
2394
|
+
else if (ch < 0) return Pos(pos.line, 0);
|
|
2124
2395
|
else return pos;
|
|
2125
2396
|
}
|
|
2126
|
-
function isLine(doc, l) {return l >=
|
|
2397
|
+
function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
|
|
2127
2398
|
|
|
2128
2399
|
// If shift is held, this will move the selection anchor. Otherwise,
|
|
2129
2400
|
// it'll set the whole selection.
|
|
2130
|
-
function extendSelection(
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
var anchor = sel.anchor;
|
|
2401
|
+
function extendSelection(doc, pos, other, bias) {
|
|
2402
|
+
if (doc.sel.shift || doc.sel.extend) {
|
|
2403
|
+
var anchor = doc.sel.anchor;
|
|
2134
2404
|
if (other) {
|
|
2135
2405
|
var posBefore = posLess(pos, anchor);
|
|
2136
2406
|
if (posBefore != posLess(other, anchor)) {
|
|
@@ -2140,24 +2410,38 @@ window.CodeMirror = (function() {
|
|
|
2140
2410
|
pos = other;
|
|
2141
2411
|
}
|
|
2142
2412
|
}
|
|
2143
|
-
setSelection(
|
|
2413
|
+
setSelection(doc, anchor, pos, bias);
|
|
2144
2414
|
} else {
|
|
2145
|
-
setSelection(
|
|
2415
|
+
setSelection(doc, pos, other || pos, bias);
|
|
2146
2416
|
}
|
|
2147
|
-
cm.curOp.userSelChange = true;
|
|
2417
|
+
if (doc.cm) doc.cm.curOp.userSelChange = true;
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
function filterSelectionChange(doc, anchor, head) {
|
|
2421
|
+
var obj = {anchor: anchor, head: head};
|
|
2422
|
+
signal(doc, "beforeSelectionChange", doc, obj);
|
|
2423
|
+
if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
|
|
2424
|
+
obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
|
|
2425
|
+
return obj;
|
|
2148
2426
|
}
|
|
2149
2427
|
|
|
2150
2428
|
// Update the selection. Last two args are only used by
|
|
2151
2429
|
// updateDoc, since they have to be expressed in the line
|
|
2152
2430
|
// numbers before the update.
|
|
2153
|
-
function setSelection(
|
|
2154
|
-
cm.
|
|
2155
|
-
|
|
2431
|
+
function setSelection(doc, anchor, head, bias, checkAtomic) {
|
|
2432
|
+
if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
|
|
2433
|
+
var filtered = filterSelectionChange(doc, anchor, head);
|
|
2434
|
+
head = filtered.head;
|
|
2435
|
+
anchor = filtered.anchor;
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
var sel = doc.sel;
|
|
2439
|
+
sel.goalColumn = null;
|
|
2156
2440
|
// Skip over atomic spans.
|
|
2157
2441
|
if (checkAtomic || !posEq(anchor, sel.anchor))
|
|
2158
|
-
anchor = skipAtomic(
|
|
2442
|
+
anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
|
|
2159
2443
|
if (checkAtomic || !posEq(head, sel.head))
|
|
2160
|
-
head = skipAtomic(
|
|
2444
|
+
head = skipAtomic(doc, head, bias, checkAtomic != "push");
|
|
2161
2445
|
|
|
2162
2446
|
if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
|
|
2163
2447
|
|
|
@@ -2166,47 +2450,54 @@ window.CodeMirror = (function() {
|
|
|
2166
2450
|
sel.from = inv ? head : anchor;
|
|
2167
2451
|
sel.to = inv ? anchor : head;
|
|
2168
2452
|
|
|
2169
|
-
cm
|
|
2170
|
-
|
|
2453
|
+
if (doc.cm)
|
|
2454
|
+
doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
|
|
2455
|
+
doc.cm.curOp.cursorActivity = true;
|
|
2456
|
+
|
|
2457
|
+
signalLater(doc, "cursorActivity", doc);
|
|
2171
2458
|
}
|
|
2172
2459
|
|
|
2173
2460
|
function reCheckSelection(cm) {
|
|
2174
|
-
setSelection(cm, cm.
|
|
2461
|
+
setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
|
|
2175
2462
|
}
|
|
2176
2463
|
|
|
2177
|
-
function skipAtomic(
|
|
2178
|
-
var
|
|
2464
|
+
function skipAtomic(doc, pos, bias, mayClear) {
|
|
2465
|
+
var flipped = false, curPos = pos;
|
|
2179
2466
|
var dir = bias || 1;
|
|
2180
|
-
|
|
2467
|
+
doc.cantEdit = false;
|
|
2181
2468
|
search: for (;;) {
|
|
2182
|
-
var line = getLine(doc, curPos.line)
|
|
2469
|
+
var line = getLine(doc, curPos.line);
|
|
2183
2470
|
if (line.markedSpans) {
|
|
2184
2471
|
for (var i = 0; i < line.markedSpans.length; ++i) {
|
|
2185
2472
|
var sp = line.markedSpans[i], m = sp.marker;
|
|
2186
2473
|
if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
|
|
2187
2474
|
(sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
|
|
2188
|
-
if (mayClear
|
|
2189
|
-
(
|
|
2190
|
-
|
|
2191
|
-
|
|
2475
|
+
if (mayClear) {
|
|
2476
|
+
signal(m, "beforeCursorEnter");
|
|
2477
|
+
if (m.explicitlyCleared) {
|
|
2478
|
+
if (!line.markedSpans) break;
|
|
2479
|
+
else {--i; continue;}
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
if (!m.atomic) continue;
|
|
2192
2483
|
var newPos = m.find()[dir < 0 ? "from" : "to"];
|
|
2193
2484
|
if (posEq(newPos, curPos)) {
|
|
2194
2485
|
newPos.ch += dir;
|
|
2195
2486
|
if (newPos.ch < 0) {
|
|
2196
|
-
if (newPos.line) newPos = clipPos(doc,
|
|
2487
|
+
if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
|
|
2197
2488
|
else newPos = null;
|
|
2198
2489
|
} else if (newPos.ch > line.text.length) {
|
|
2199
|
-
if (newPos.line < doc.size - 1) newPos =
|
|
2490
|
+
if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
|
|
2200
2491
|
else newPos = null;
|
|
2201
2492
|
}
|
|
2202
2493
|
if (!newPos) {
|
|
2203
2494
|
if (flipped) {
|
|
2204
2495
|
// Driven in a corner -- no valid cursor position found at all
|
|
2205
2496
|
// -- try again *with* clearing, if we didn't already
|
|
2206
|
-
if (!mayClear) return skipAtomic(
|
|
2497
|
+
if (!mayClear) return skipAtomic(doc, pos, bias, true);
|
|
2207
2498
|
// Otherwise, turn off editing until further notice, and return the start of the doc
|
|
2208
|
-
|
|
2209
|
-
return
|
|
2499
|
+
doc.cantEdit = true;
|
|
2500
|
+
return Pos(doc.first, 0);
|
|
2210
2501
|
}
|
|
2211
2502
|
flipped = true; newPos = pos; dir = -dir;
|
|
2212
2503
|
}
|
|
@@ -2215,7 +2506,6 @@ window.CodeMirror = (function() {
|
|
|
2215
2506
|
continue search;
|
|
2216
2507
|
}
|
|
2217
2508
|
}
|
|
2218
|
-
if (toClear) for (var i = 0; i < toClear.length; ++i) toClear[i].clear();
|
|
2219
2509
|
}
|
|
2220
2510
|
return curPos;
|
|
2221
2511
|
}
|
|
@@ -2224,12 +2514,11 @@ window.CodeMirror = (function() {
|
|
|
2224
2514
|
// SCROLLING
|
|
2225
2515
|
|
|
2226
2516
|
function scrollCursorIntoView(cm) {
|
|
2227
|
-
var
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
if (coords.
|
|
2232
|
-
else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
|
|
2517
|
+
var coords = scrollPosIntoView(cm, cm.doc.sel.head);
|
|
2518
|
+
if (!cm.state.focused) return;
|
|
2519
|
+
var display = cm.display, box = getRect(display.sizer), doScroll = null, pTop = paddingTop(cm.display);
|
|
2520
|
+
if (coords.top + pTop + box.top < 0) doScroll = true;
|
|
2521
|
+
else if (coords.bottom + pTop + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
|
|
2233
2522
|
if (doScroll != null && !phantom) {
|
|
2234
2523
|
var hidden = display.cursor.style.display == "none";
|
|
2235
2524
|
if (hidden) {
|
|
@@ -2242,18 +2531,19 @@ window.CodeMirror = (function() {
|
|
|
2242
2531
|
}
|
|
2243
2532
|
}
|
|
2244
2533
|
|
|
2245
|
-
function scrollPosIntoView(cm, pos) {
|
|
2534
|
+
function scrollPosIntoView(cm, pos, margin) {
|
|
2535
|
+
if (margin == null) margin = 0;
|
|
2246
2536
|
for (;;) {
|
|
2247
2537
|
var changed = false, coords = cursorCoords(cm, pos);
|
|
2248
|
-
var scrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
|
|
2249
|
-
var startTop = cm.
|
|
2538
|
+
var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
|
|
2539
|
+
var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
|
|
2250
2540
|
if (scrollPos.scrollTop != null) {
|
|
2251
2541
|
setScrollTop(cm, scrollPos.scrollTop);
|
|
2252
|
-
if (Math.abs(cm.
|
|
2542
|
+
if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
|
|
2253
2543
|
}
|
|
2254
2544
|
if (scrollPos.scrollLeft != null) {
|
|
2255
2545
|
setScrollLeft(cm, scrollPos.scrollLeft);
|
|
2256
|
-
if (Math.abs(cm.
|
|
2546
|
+
if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
|
|
2257
2547
|
}
|
|
2258
2548
|
if (!changed) return coords;
|
|
2259
2549
|
}
|
|
@@ -2268,11 +2558,16 @@ window.CodeMirror = (function() {
|
|
|
2268
2558
|
function calculateScrollPos(cm, x1, y1, x2, y2) {
|
|
2269
2559
|
var display = cm.display, pt = paddingTop(display);
|
|
2270
2560
|
y1 += pt; y2 += pt;
|
|
2561
|
+
if (y1 < 0) y1 = 0;
|
|
2271
2562
|
var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
|
|
2272
|
-
var docBottom = cm.
|
|
2563
|
+
var docBottom = cm.doc.height + paddingVert(display);
|
|
2273
2564
|
var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
|
|
2274
|
-
if (y1 < screentop)
|
|
2275
|
-
|
|
2565
|
+
if (y1 < screentop) {
|
|
2566
|
+
result.scrollTop = atTop ? 0 : y1;
|
|
2567
|
+
} else if (y2 > screentop + screen) {
|
|
2568
|
+
var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
|
|
2569
|
+
if (newTop != screentop) result.scrollTop = newTop;
|
|
2570
|
+
}
|
|
2276
2571
|
|
|
2277
2572
|
var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
|
|
2278
2573
|
x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
|
|
@@ -2287,13 +2582,25 @@ window.CodeMirror = (function() {
|
|
|
2287
2582
|
return result;
|
|
2288
2583
|
}
|
|
2289
2584
|
|
|
2585
|
+
function updateScrollPos(cm, left, top) {
|
|
2586
|
+
cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
|
|
2587
|
+
scrollTop: top == null ? cm.doc.scrollTop : top};
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
function addToScrollPos(cm, left, top) {
|
|
2591
|
+
var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
|
|
2592
|
+
var scroll = cm.display.scroller;
|
|
2593
|
+
pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
|
|
2594
|
+
pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2290
2597
|
// API UTILITIES
|
|
2291
2598
|
|
|
2292
2599
|
function indentLine(cm, n, how, aggressive) {
|
|
2293
|
-
var doc = cm.
|
|
2600
|
+
var doc = cm.doc;
|
|
2294
2601
|
if (!how) how = "add";
|
|
2295
2602
|
if (how == "smart") {
|
|
2296
|
-
if (!cm.
|
|
2603
|
+
if (!cm.doc.mode.indent) how = "prev";
|
|
2297
2604
|
else var state = getStateBefore(cm, n);
|
|
2298
2605
|
}
|
|
2299
2606
|
|
|
@@ -2301,18 +2608,20 @@ window.CodeMirror = (function() {
|
|
|
2301
2608
|
var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
|
|
2302
2609
|
var curSpaceString = line.text.match(/^\s*/)[0], indentation;
|
|
2303
2610
|
if (how == "smart") {
|
|
2304
|
-
indentation = cm.
|
|
2611
|
+
indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
|
|
2305
2612
|
if (indentation == Pass) {
|
|
2306
2613
|
if (!aggressive) return;
|
|
2307
2614
|
how = "prev";
|
|
2308
2615
|
}
|
|
2309
2616
|
}
|
|
2310
2617
|
if (how == "prev") {
|
|
2311
|
-
if (n) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
|
|
2618
|
+
if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
|
|
2312
2619
|
else indentation = 0;
|
|
2620
|
+
} else if (how == "add") {
|
|
2621
|
+
indentation = curSpace + cm.options.indentUnit;
|
|
2622
|
+
} else if (how == "subtract") {
|
|
2623
|
+
indentation = curSpace - cm.options.indentUnit;
|
|
2313
2624
|
}
|
|
2314
|
-
else if (how == "add") indentation = curSpace + cm.options.indentUnit;
|
|
2315
|
-
else if (how == "subtract") indentation = curSpace - cm.options.indentUnit;
|
|
2316
2625
|
indentation = Math.max(0, indentation);
|
|
2317
2626
|
|
|
2318
2627
|
var indentString = "", pos = 0;
|
|
@@ -2321,12 +2630,12 @@ window.CodeMirror = (function() {
|
|
|
2321
2630
|
if (pos < indentation) indentString += spaceStr(indentation - pos);
|
|
2322
2631
|
|
|
2323
2632
|
if (indentString != curSpaceString)
|
|
2324
|
-
replaceRange(cm, indentString,
|
|
2633
|
+
replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
|
|
2325
2634
|
line.stateAfter = null;
|
|
2326
2635
|
}
|
|
2327
2636
|
|
|
2328
2637
|
function changeLine(cm, handle, op) {
|
|
2329
|
-
var no = handle, line = handle, doc = cm.
|
|
2638
|
+
var no = handle, line = handle, doc = cm.doc;
|
|
2330
2639
|
if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
|
|
2331
2640
|
else no = lineNo(handle);
|
|
2332
2641
|
if (no == null) return null;
|
|
@@ -2335,12 +2644,13 @@ window.CodeMirror = (function() {
|
|
|
2335
2644
|
return line;
|
|
2336
2645
|
}
|
|
2337
2646
|
|
|
2338
|
-
function findPosH(
|
|
2339
|
-
var
|
|
2647
|
+
function findPosH(doc, pos, dir, unit, visually) {
|
|
2648
|
+
var line = pos.line, ch = pos.ch;
|
|
2340
2649
|
var lineObj = getLine(doc, line);
|
|
2650
|
+
var possible = true;
|
|
2341
2651
|
function findNextLine() {
|
|
2342
2652
|
var l = line + dir;
|
|
2343
|
-
if (l <
|
|
2653
|
+
if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
|
|
2344
2654
|
line = l;
|
|
2345
2655
|
return lineObj = getLine(doc, l);
|
|
2346
2656
|
}
|
|
@@ -2350,22 +2660,50 @@ window.CodeMirror = (function() {
|
|
|
2350
2660
|
if (!boundToLine && findNextLine()) {
|
|
2351
2661
|
if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
|
|
2352
2662
|
else ch = dir < 0 ? lineObj.text.length : 0;
|
|
2353
|
-
} else return false;
|
|
2663
|
+
} else return (possible = false);
|
|
2354
2664
|
} else ch = next;
|
|
2355
2665
|
return true;
|
|
2356
2666
|
}
|
|
2667
|
+
|
|
2357
2668
|
if (unit == "char") moveOnce();
|
|
2358
2669
|
else if (unit == "column") moveOnce(true);
|
|
2359
|
-
else if (unit == "word") {
|
|
2360
|
-
var
|
|
2361
|
-
for (;;) {
|
|
2362
|
-
if (dir < 0
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2670
|
+
else if (unit == "word" || unit == "group") {
|
|
2671
|
+
var sawType = null, group = unit == "group";
|
|
2672
|
+
for (var first = true;; first = false) {
|
|
2673
|
+
if (dir < 0 && !moveOnce(!first)) break;
|
|
2674
|
+
var cur = lineObj.text.charAt(ch) || "\n";
|
|
2675
|
+
var type = isWordChar(cur) ? "w"
|
|
2676
|
+
: !group ? null
|
|
2677
|
+
: /\s/.test(cur) ? null
|
|
2678
|
+
: "p";
|
|
2679
|
+
if (sawType && sawType != type) {
|
|
2680
|
+
if (dir < 0) {dir = 1; moveOnce();}
|
|
2681
|
+
break;
|
|
2682
|
+
}
|
|
2683
|
+
if (type) sawType = type;
|
|
2684
|
+
if (dir > 0 && !moveOnce(!first)) break;
|
|
2366
2685
|
}
|
|
2367
2686
|
}
|
|
2368
|
-
|
|
2687
|
+
var result = skipAtomic(doc, Pos(line, ch), dir, true);
|
|
2688
|
+
if (!possible) result.hitSide = true;
|
|
2689
|
+
return result;
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
function findPosV(cm, pos, dir, unit) {
|
|
2693
|
+
var doc = cm.doc, x = pos.left, y;
|
|
2694
|
+
if (unit == "page") {
|
|
2695
|
+
var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
|
|
2696
|
+
y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
|
|
2697
|
+
} else if (unit == "line") {
|
|
2698
|
+
y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
|
|
2699
|
+
}
|
|
2700
|
+
for (;;) {
|
|
2701
|
+
var target = coordsChar(cm, x, y);
|
|
2702
|
+
if (!target.outside) break;
|
|
2703
|
+
if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
|
|
2704
|
+
y += dir * 5;
|
|
2705
|
+
}
|
|
2706
|
+
return target;
|
|
2369
2707
|
}
|
|
2370
2708
|
|
|
2371
2709
|
function findWordAt(line, pos) {
|
|
@@ -2373,17 +2711,17 @@ window.CodeMirror = (function() {
|
|
|
2373
2711
|
if (line) {
|
|
2374
2712
|
if (pos.after === false || end == line.length) --start; else ++end;
|
|
2375
2713
|
var startChar = line.charAt(start);
|
|
2376
|
-
var check = isWordChar(startChar) ? isWordChar
|
|
2377
|
-
/\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
|
|
2378
|
-
|
|
2714
|
+
var check = isWordChar(startChar) ? isWordChar
|
|
2715
|
+
: /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
|
|
2716
|
+
: function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
|
|
2379
2717
|
while (start > 0 && check(line.charAt(start - 1))) --start;
|
|
2380
2718
|
while (end < line.length && check(line.charAt(end))) ++end;
|
|
2381
2719
|
}
|
|
2382
|
-
return {from:
|
|
2720
|
+
return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
|
|
2383
2721
|
}
|
|
2384
2722
|
|
|
2385
2723
|
function selectLine(cm, line) {
|
|
2386
|
-
extendSelection(cm,
|
|
2724
|
+
extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
|
|
2387
2725
|
}
|
|
2388
2726
|
|
|
2389
2727
|
// PROTOTYPE
|
|
@@ -2392,24 +2730,6 @@ window.CodeMirror = (function() {
|
|
|
2392
2730
|
// 'wrap f in an operation, performed on its `this` parameter'
|
|
2393
2731
|
|
|
2394
2732
|
CodeMirror.prototype = {
|
|
2395
|
-
getValue: function(lineSep) {
|
|
2396
|
-
var text = [], doc = this.view.doc;
|
|
2397
|
-
doc.iter(0, doc.size, function(line) { text.push(line.text); });
|
|
2398
|
-
return text.join(lineSep || "\n");
|
|
2399
|
-
},
|
|
2400
|
-
|
|
2401
|
-
setValue: operation(null, function(code) {
|
|
2402
|
-
var doc = this.view.doc, top = {line: 0, ch: 0}, lastLen = getLine(doc, doc.size-1).text.length;
|
|
2403
|
-
updateDocInner(this, top, {line: doc.size - 1, ch: lastLen}, splitLines(code), top, top, "setValue");
|
|
2404
|
-
}),
|
|
2405
|
-
|
|
2406
|
-
getSelection: function(lineSep) { return this.getRange(this.view.sel.from, this.view.sel.to, lineSep); },
|
|
2407
|
-
|
|
2408
|
-
replaceSelection: operation(null, function(code, collapse, origin) {
|
|
2409
|
-
var sel = this.view.sel;
|
|
2410
|
-
updateDoc(this, sel.from, sel.to, splitLines(code), collapse || "around", origin);
|
|
2411
|
-
}),
|
|
2412
|
-
|
|
2413
2733
|
focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
|
|
2414
2734
|
|
|
2415
2735
|
setOption: function(option, value) {
|
|
@@ -2421,15 +2741,13 @@ window.CodeMirror = (function() {
|
|
|
2421
2741
|
},
|
|
2422
2742
|
|
|
2423
2743
|
getOption: function(option) {return this.options[option];},
|
|
2744
|
+
getDoc: function() {return this.doc;},
|
|
2424
2745
|
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
addKeyMap: function(map) {
|
|
2428
|
-
this.view.keyMaps.push(map);
|
|
2746
|
+
addKeyMap: function(map, bottom) {
|
|
2747
|
+
this.state.keyMaps[bottom ? "push" : "unshift"](map);
|
|
2429
2748
|
},
|
|
2430
|
-
|
|
2431
2749
|
removeKeyMap: function(map) {
|
|
2432
|
-
var maps = this.
|
|
2750
|
+
var maps = this.state.keyMaps;
|
|
2433
2751
|
for (var i = 0; i < maps.length; ++i)
|
|
2434
2752
|
if ((typeof map == "string" ? maps[i].name : maps[i]) == map) {
|
|
2435
2753
|
maps.splice(i, 1);
|
|
@@ -2440,84 +2758,42 @@ window.CodeMirror = (function() {
|
|
|
2440
2758
|
addOverlay: operation(null, function(spec, options) {
|
|
2441
2759
|
var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
|
|
2442
2760
|
if (mode.startState) throw new Error("Overlays may not be stateful.");
|
|
2443
|
-
this.
|
|
2444
|
-
this.
|
|
2445
|
-
regChange(this
|
|
2761
|
+
this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
|
|
2762
|
+
this.state.modeGen++;
|
|
2763
|
+
regChange(this);
|
|
2446
2764
|
}),
|
|
2447
2765
|
removeOverlay: operation(null, function(spec) {
|
|
2448
|
-
var overlays = this.
|
|
2766
|
+
var overlays = this.state.overlays;
|
|
2449
2767
|
for (var i = 0; i < overlays.length; ++i) {
|
|
2450
2768
|
if (overlays[i].modeSpec == spec) {
|
|
2451
2769
|
overlays.splice(i, 1);
|
|
2452
|
-
this.
|
|
2453
|
-
regChange(this
|
|
2770
|
+
this.state.modeGen++;
|
|
2771
|
+
regChange(this);
|
|
2454
2772
|
return;
|
|
2455
2773
|
}
|
|
2456
2774
|
}
|
|
2457
2775
|
}),
|
|
2458
2776
|
|
|
2459
|
-
undo: operation(null, function() {unredoHelper(this, "undo");}),
|
|
2460
|
-
redo: operation(null, function() {unredoHelper(this, "redo");}),
|
|
2461
|
-
|
|
2462
2777
|
indentLine: operation(null, function(n, dir, aggressive) {
|
|
2463
2778
|
if (typeof dir != "string") {
|
|
2464
2779
|
if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
|
|
2465
2780
|
else dir = dir ? "add" : "subtract";
|
|
2466
2781
|
}
|
|
2467
|
-
if (isLine(this.
|
|
2782
|
+
if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
|
|
2468
2783
|
}),
|
|
2469
|
-
|
|
2470
2784
|
indentSelection: operation(null, function(how) {
|
|
2471
|
-
var sel = this.
|
|
2785
|
+
var sel = this.doc.sel;
|
|
2472
2786
|
if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
|
|
2473
2787
|
var e = sel.to.line - (sel.to.ch ? 0 : 1);
|
|
2474
2788
|
for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
|
|
2475
2789
|
}),
|
|
2476
2790
|
|
|
2477
|
-
historySize: function() {
|
|
2478
|
-
var hist = this.view.history;
|
|
2479
|
-
return {undo: hist.done.length, redo: hist.undone.length};
|
|
2480
|
-
},
|
|
2481
|
-
|
|
2482
|
-
clearHistory: function() {this.view.history = makeHistory();},
|
|
2483
|
-
|
|
2484
|
-
markClean: function() {
|
|
2485
|
-
this.view.history.dirtyCounter = 0;
|
|
2486
|
-
this.view.history.lastOp = this.view.history.lastOrigin = null;
|
|
2487
|
-
},
|
|
2488
|
-
|
|
2489
|
-
isClean: function () {return this.view.history.dirtyCounter == 0;},
|
|
2490
|
-
|
|
2491
|
-
getHistory: function() {
|
|
2492
|
-
var hist = this.view.history;
|
|
2493
|
-
function cp(arr) {
|
|
2494
|
-
for (var i = 0, nw = [], nwelt; i < arr.length; ++i) {
|
|
2495
|
-
var set = arr[i];
|
|
2496
|
-
nw.push({events: nwelt = [], fromBefore: set.fromBefore, toBefore: set.toBefore,
|
|
2497
|
-
fromAfter: set.fromAfter, toAfter: set.toAfter});
|
|
2498
|
-
for (var j = 0, elt = set.events; j < elt.length; ++j) {
|
|
2499
|
-
var old = [], cur = elt[j];
|
|
2500
|
-
nwelt.push({start: cur.start, added: cur.added, old: old});
|
|
2501
|
-
for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k]));
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
return nw;
|
|
2505
|
-
}
|
|
2506
|
-
return {done: cp(hist.done), undone: cp(hist.undone)};
|
|
2507
|
-
},
|
|
2508
|
-
|
|
2509
|
-
setHistory: function(histData) {
|
|
2510
|
-
var hist = this.view.history = makeHistory();
|
|
2511
|
-
hist.done = histData.done;
|
|
2512
|
-
hist.undone = histData.undone;
|
|
2513
|
-
},
|
|
2514
|
-
|
|
2515
2791
|
// Fetch the parser token for a given character. Useful for hacks
|
|
2516
2792
|
// that want to inspect the mode state (say, for completion).
|
|
2517
2793
|
getTokenAt: function(pos) {
|
|
2518
|
-
var doc = this.
|
|
2794
|
+
var doc = this.doc;
|
|
2519
2795
|
pos = clipPos(doc, pos);
|
|
2520
|
-
var state = getStateBefore(this, pos.line), mode = this.
|
|
2796
|
+
var state = getStateBefore(this, pos.line), mode = this.doc.mode;
|
|
2521
2797
|
var line = getLine(doc, pos.line);
|
|
2522
2798
|
var stream = new StringStream(line.text, this.options.tabSize);
|
|
2523
2799
|
while (stream.pos < pos.ch && !stream.eol()) {
|
|
@@ -2533,52 +2809,30 @@ window.CodeMirror = (function() {
|
|
|
2533
2809
|
},
|
|
2534
2810
|
|
|
2535
2811
|
getStateAfter: function(line) {
|
|
2536
|
-
var doc = this.
|
|
2537
|
-
line = clipLine(doc, line == null ? doc.size - 1: line);
|
|
2812
|
+
var doc = this.doc;
|
|
2813
|
+
line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
|
|
2538
2814
|
return getStateBefore(this, line + 1);
|
|
2539
2815
|
},
|
|
2540
2816
|
|
|
2541
2817
|
cursorCoords: function(start, mode) {
|
|
2542
|
-
var pos, sel = this.
|
|
2818
|
+
var pos, sel = this.doc.sel;
|
|
2543
2819
|
if (start == null) pos = sel.head;
|
|
2544
|
-
else if (typeof start == "object") pos = clipPos(this.
|
|
2820
|
+
else if (typeof start == "object") pos = clipPos(this.doc, start);
|
|
2545
2821
|
else pos = start ? sel.from : sel.to;
|
|
2546
2822
|
return cursorCoords(this, pos, mode || "page");
|
|
2547
2823
|
},
|
|
2548
2824
|
|
|
2549
2825
|
charCoords: function(pos, mode) {
|
|
2550
|
-
return charCoords(this, clipPos(this.
|
|
2826
|
+
return charCoords(this, clipPos(this.doc, pos), mode || "page");
|
|
2551
2827
|
},
|
|
2552
2828
|
|
|
2553
|
-
coordsChar: function(coords) {
|
|
2554
|
-
|
|
2555
|
-
return coordsChar(this, coords.left
|
|
2829
|
+
coordsChar: function(coords, mode) {
|
|
2830
|
+
coords = fromCoordSystem(this, coords, mode || "page");
|
|
2831
|
+
return coordsChar(this, coords.left, coords.top);
|
|
2556
2832
|
},
|
|
2557
2833
|
|
|
2558
2834
|
defaultTextHeight: function() { return textHeight(this.display); },
|
|
2559
|
-
|
|
2560
|
-
markText: operation(null, function(from, to, options) {
|
|
2561
|
-
return markText(this, clipPos(this.view.doc, from), clipPos(this.view.doc, to),
|
|
2562
|
-
options, "range");
|
|
2563
|
-
}),
|
|
2564
|
-
|
|
2565
|
-
setBookmark: operation(null, function(pos, widget) {
|
|
2566
|
-
pos = clipPos(this.view.doc, pos);
|
|
2567
|
-
return markText(this, pos, pos, widget ? {replacedWith: widget} : {}, "bookmark");
|
|
2568
|
-
}),
|
|
2569
|
-
|
|
2570
|
-
findMarksAt: function(pos) {
|
|
2571
|
-
var doc = this.view.doc;
|
|
2572
|
-
pos = clipPos(doc, pos);
|
|
2573
|
-
var markers = [], spans = getLine(doc, pos.line).markedSpans;
|
|
2574
|
-
if (spans) for (var i = 0; i < spans.length; ++i) {
|
|
2575
|
-
var span = spans[i];
|
|
2576
|
-
if ((span.from == null || span.from <= pos.ch) &&
|
|
2577
|
-
(span.to == null || span.to >= pos.ch))
|
|
2578
|
-
markers.push(span.marker);
|
|
2579
|
-
}
|
|
2580
|
-
return markers;
|
|
2581
|
-
},
|
|
2835
|
+
defaultCharWidth: function() { return charWidth(this.display); },
|
|
2582
2836
|
|
|
2583
2837
|
setGutterMarker: operation(null, function(line, gutterID, value) {
|
|
2584
2838
|
return changeLine(this, line, function(line) {
|
|
@@ -2590,8 +2844,8 @@ window.CodeMirror = (function() {
|
|
|
2590
2844
|
}),
|
|
2591
2845
|
|
|
2592
2846
|
clearGutter: operation(null, function(gutterID) {
|
|
2593
|
-
var
|
|
2594
|
-
doc.iter(
|
|
2847
|
+
var cm = this, doc = cm.doc, i = doc.first;
|
|
2848
|
+
doc.iter(function(line) {
|
|
2595
2849
|
if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
|
|
2596
2850
|
line.gutterMarkers[gutterID] = null;
|
|
2597
2851
|
regChange(cm, i, i + 1);
|
|
@@ -2634,9 +2888,9 @@ window.CodeMirror = (function() {
|
|
|
2634
2888
|
|
|
2635
2889
|
lineInfo: function(line) {
|
|
2636
2890
|
if (typeof line == "number") {
|
|
2637
|
-
if (!isLine(this.
|
|
2891
|
+
if (!isLine(this.doc, line)) return null;
|
|
2638
2892
|
var n = line;
|
|
2639
|
-
line = getLine(this.
|
|
2893
|
+
line = getLine(this.doc, line);
|
|
2640
2894
|
if (!line) return null;
|
|
2641
2895
|
} else {
|
|
2642
2896
|
var n = lineNo(line);
|
|
@@ -2651,16 +2905,20 @@ window.CodeMirror = (function() {
|
|
|
2651
2905
|
|
|
2652
2906
|
addWidget: function(pos, node, scroll, vert, horiz) {
|
|
2653
2907
|
var display = this.display;
|
|
2654
|
-
pos = cursorCoords(this, clipPos(this.
|
|
2655
|
-
var top = pos.
|
|
2908
|
+
pos = cursorCoords(this, clipPos(this.doc, pos));
|
|
2909
|
+
var top = pos.bottom, left = pos.left;
|
|
2656
2910
|
node.style.position = "absolute";
|
|
2657
2911
|
display.sizer.appendChild(node);
|
|
2658
|
-
if (vert == "over")
|
|
2659
|
-
|
|
2660
|
-
|
|
2912
|
+
if (vert == "over") {
|
|
2913
|
+
top = pos.top;
|
|
2914
|
+
} else if (vert == "above" || vert == "near") {
|
|
2915
|
+
var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
|
|
2661
2916
|
hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
|
|
2662
|
-
|
|
2917
|
+
// Default to positioning above (if specified and possible); otherwise default to positioning below
|
|
2918
|
+
if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
|
|
2663
2919
|
top = pos.top - node.offsetHeight;
|
|
2920
|
+
else if (pos.bottom + node.offsetHeight <= vspace)
|
|
2921
|
+
top = pos.bottom;
|
|
2664
2922
|
if (left + node.offsetWidth > hspace)
|
|
2665
2923
|
left = hspace - node.offsetWidth;
|
|
2666
2924
|
}
|
|
@@ -2678,147 +2936,71 @@ window.CodeMirror = (function() {
|
|
|
2678
2936
|
scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
|
|
2679
2937
|
},
|
|
2680
2938
|
|
|
2681
|
-
|
|
2939
|
+
triggerOnKeyDown: operation(null, onKeyDown),
|
|
2682
2940
|
|
|
2683
|
-
|
|
2941
|
+
execCommand: function(cmd) {return commands[cmd](this);},
|
|
2684
2942
|
|
|
2685
|
-
|
|
2686
|
-
var
|
|
2687
|
-
if (
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
somethingSelected: function() {return !posEq(this.view.sel.from, this.view.sel.to);},
|
|
2695
|
-
|
|
2696
|
-
setCursor: operation(null, function(line, ch, extend) {
|
|
2697
|
-
var pos = clipPos(this.view.doc, typeof line == "number" ? {line: line, ch: ch || 0} : line);
|
|
2698
|
-
if (extend) extendSelection(this, pos);
|
|
2699
|
-
else setSelection(this, pos, pos);
|
|
2700
|
-
}),
|
|
2701
|
-
|
|
2702
|
-
setSelection: operation(null, function(anchor, head) {
|
|
2703
|
-
var doc = this.view.doc;
|
|
2704
|
-
setSelection(this, clipPos(doc, anchor), clipPos(doc, head || anchor));
|
|
2705
|
-
}),
|
|
2706
|
-
|
|
2707
|
-
extendSelection: operation(null, function(from, to) {
|
|
2708
|
-
var doc = this.view.doc;
|
|
2709
|
-
extendSelection(this, clipPos(doc, from), to && clipPos(doc, to));
|
|
2710
|
-
}),
|
|
2711
|
-
|
|
2712
|
-
setExtending: function(val) {this.view.sel.extend = val;},
|
|
2713
|
-
|
|
2714
|
-
getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
|
|
2715
|
-
|
|
2716
|
-
getLineHandle: function(line) {
|
|
2717
|
-
var doc = this.view.doc;
|
|
2718
|
-
if (isLine(doc, line)) return getLine(doc, line);
|
|
2719
|
-
},
|
|
2720
|
-
|
|
2721
|
-
getLineNumber: function(line) {return lineNo(line);},
|
|
2722
|
-
|
|
2723
|
-
setLine: operation(null, function(line, text) {
|
|
2724
|
-
if (isLine(this.view.doc, line))
|
|
2725
|
-
replaceRange(this, text, {line: line, ch: 0}, {line: line, ch: getLine(this.view.doc, line).text.length});
|
|
2726
|
-
}),
|
|
2727
|
-
|
|
2728
|
-
removeLine: operation(null, function(line) {
|
|
2729
|
-
if (isLine(this.view.doc, line))
|
|
2730
|
-
replaceRange(this, "", {line: line, ch: 0}, clipPos(this.view.doc, {line: line+1, ch: 0}));
|
|
2731
|
-
}),
|
|
2732
|
-
|
|
2733
|
-
replaceRange: operation(null, function(code, from, to) {
|
|
2734
|
-
var doc = this.view.doc;
|
|
2735
|
-
from = clipPos(doc, from);
|
|
2736
|
-
to = to ? clipPos(doc, to) : from;
|
|
2737
|
-
return replaceRange(this, code, from, to);
|
|
2738
|
-
}),
|
|
2739
|
-
|
|
2740
|
-
getRange: function(from, to, lineSep) {
|
|
2741
|
-
var doc = this.view.doc;
|
|
2742
|
-
from = clipPos(doc, from); to = clipPos(doc, to);
|
|
2743
|
-
var l1 = from.line, l2 = to.line;
|
|
2744
|
-
if (l1 == l2) return getLine(doc, l1).text.slice(from.ch, to.ch);
|
|
2745
|
-
var code = [getLine(doc, l1).text.slice(from.ch)];
|
|
2746
|
-
doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
|
|
2747
|
-
code.push(getLine(doc, l2).text.slice(0, to.ch));
|
|
2748
|
-
return code.join(lineSep || "\n");
|
|
2943
|
+
findPosH: function(from, amount, unit, visually) {
|
|
2944
|
+
var dir = 1;
|
|
2945
|
+
if (amount < 0) { dir = -1; amount = -amount; }
|
|
2946
|
+
for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
|
|
2947
|
+
cur = findPosH(this.doc, cur, dir, unit, visually);
|
|
2948
|
+
if (cur.hitSide) break;
|
|
2949
|
+
}
|
|
2950
|
+
return cur;
|
|
2749
2951
|
},
|
|
2750
2952
|
|
|
2751
|
-
triggerOnKeyDown: operation(null, onKeyDown),
|
|
2752
|
-
|
|
2753
|
-
execCommand: function(cmd) {return commands[cmd](this);},
|
|
2754
|
-
|
|
2755
|
-
// Stuff used by commands, probably not much use to outside code.
|
|
2756
2953
|
moveH: operation(null, function(dir, unit) {
|
|
2757
|
-
var sel = this.
|
|
2954
|
+
var sel = this.doc.sel, pos;
|
|
2758
2955
|
if (sel.shift || sel.extend || posEq(sel.from, sel.to))
|
|
2759
|
-
pos = findPosH(this, dir, unit, this.options.rtlMoveVisually);
|
|
2760
|
-
|
|
2956
|
+
pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
|
|
2957
|
+
else
|
|
2958
|
+
pos = dir < 0 ? sel.from : sel.to;
|
|
2959
|
+
extendSelection(this.doc, pos, pos, dir);
|
|
2761
2960
|
}),
|
|
2762
2961
|
|
|
2763
2962
|
deleteH: operation(null, function(dir, unit) {
|
|
2764
|
-
var sel = this.
|
|
2765
|
-
if (!posEq(sel.from, sel.to)) replaceRange(this, "", sel.from, sel.to, "delete");
|
|
2766
|
-
else replaceRange(this, "", sel.from, findPosH(this, dir, unit, false), "delete");
|
|
2963
|
+
var sel = this.doc.sel;
|
|
2964
|
+
if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
|
|
2965
|
+
else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
|
|
2767
2966
|
this.curOp.userSelChange = true;
|
|
2768
2967
|
}),
|
|
2769
2968
|
|
|
2770
|
-
|
|
2771
|
-
var
|
|
2772
|
-
|
|
2773
|
-
var
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
|
|
2969
|
+
findPosV: function(from, amount, unit, goalColumn) {
|
|
2970
|
+
var dir = 1, x = goalColumn;
|
|
2971
|
+
if (amount < 0) { dir = -1; amount = -amount; }
|
|
2972
|
+
for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
|
|
2973
|
+
var coords = cursorCoords(this, cur, "div");
|
|
2974
|
+
if (x == null) x = coords.left;
|
|
2975
|
+
else coords.left = x;
|
|
2976
|
+
cur = findPosV(this, coords, dir, unit);
|
|
2977
|
+
if (cur.hitSide) break;
|
|
2780
2978
|
}
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
y += dir * 5;
|
|
2784
|
-
} while (target.outside && (dir < 0 ? y > 0 : y < doc.height));
|
|
2979
|
+
return cur;
|
|
2980
|
+
},
|
|
2785
2981
|
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2982
|
+
moveV: operation(null, function(dir, unit) {
|
|
2983
|
+
var sel = this.doc.sel;
|
|
2984
|
+
var pos = cursorCoords(this, sel.head, "div");
|
|
2985
|
+
if (sel.goalColumn != null) pos.left = sel.goalColumn;
|
|
2986
|
+
var target = findPosV(this, pos, dir, unit);
|
|
2987
|
+
|
|
2988
|
+
if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
|
|
2989
|
+
extendSelection(this.doc, target, target, dir);
|
|
2990
|
+
sel.goalColumn = pos.left;
|
|
2789
2991
|
}),
|
|
2790
2992
|
|
|
2791
2993
|
toggleOverwrite: function() {
|
|
2792
|
-
if (this.
|
|
2994
|
+
if (this.state.overwrite = !this.state.overwrite)
|
|
2793
2995
|
this.display.cursor.className += " CodeMirror-overwrite";
|
|
2794
2996
|
else
|
|
2795
2997
|
this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
|
|
2796
2998
|
},
|
|
2999
|
+
hasFocus: function() { return this.state.focused; },
|
|
2797
3000
|
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
var sz = line.text.length + 1;
|
|
2802
|
-
if (sz > off) { ch = off; return true; }
|
|
2803
|
-
off -= sz;
|
|
2804
|
-
++lineNo;
|
|
2805
|
-
});
|
|
2806
|
-
return clipPos(doc, {line: lineNo, ch: ch});
|
|
2807
|
-
},
|
|
2808
|
-
indexFromPos: function (coords) {
|
|
2809
|
-
coords = clipPos(this.view.doc, coords);
|
|
2810
|
-
var index = coords.ch;
|
|
2811
|
-
this.view.doc.iter(0, coords.line, function (line) {
|
|
2812
|
-
index += line.text.length + 1;
|
|
2813
|
-
});
|
|
2814
|
-
return index;
|
|
2815
|
-
},
|
|
2816
|
-
|
|
2817
|
-
scrollTo: function(x, y) {
|
|
2818
|
-
if (x != null) this.display.scrollbarH.scrollLeft = this.display.scroller.scrollLeft = x;
|
|
2819
|
-
if (y != null) this.display.scrollbarV.scrollTop = this.display.scroller.scrollTop = y;
|
|
2820
|
-
updateDisplay(this, []);
|
|
2821
|
-
},
|
|
3001
|
+
scrollTo: operation(null, function(x, y) {
|
|
3002
|
+
updateScrollPos(this, x, y);
|
|
3003
|
+
}),
|
|
2822
3004
|
getScrollInfo: function() {
|
|
2823
3005
|
var scroller = this.display.scroller, co = scrollerCutOff;
|
|
2824
3006
|
return {left: scroller.scrollLeft, top: scroller.scrollTop,
|
|
@@ -2826,15 +3008,19 @@ window.CodeMirror = (function() {
|
|
|
2826
3008
|
clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
|
|
2827
3009
|
},
|
|
2828
3010
|
|
|
2829
|
-
scrollIntoView: function(pos) {
|
|
2830
|
-
if (typeof pos == "number") pos =
|
|
3011
|
+
scrollIntoView: operation(null, function(pos, margin) {
|
|
3012
|
+
if (typeof pos == "number") pos = Pos(pos, 0);
|
|
3013
|
+
if (!margin) margin = 0;
|
|
3014
|
+
var coords = pos;
|
|
3015
|
+
|
|
2831
3016
|
if (!pos || pos.line != null) {
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
scrollIntoView(this, pos.left, pos.top, pos.right, pos.bottom);
|
|
3017
|
+
this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
|
|
3018
|
+
this.curOp.scrollToPosMargin = margin;
|
|
3019
|
+
coords = cursorCoords(this, this.curOp.scrollToPos);
|
|
2836
3020
|
}
|
|
2837
|
-
|
|
3021
|
+
var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
|
|
3022
|
+
updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
|
|
3023
|
+
}),
|
|
2838
3024
|
|
|
2839
3025
|
setSize: function(width, height) {
|
|
2840
3026
|
function interpret(val) {
|
|
@@ -2848,17 +3034,23 @@ window.CodeMirror = (function() {
|
|
|
2848
3034
|
on: function(type, f) {on(this, type, f);},
|
|
2849
3035
|
off: function(type, f) {off(this, type, f);},
|
|
2850
3036
|
|
|
2851
|
-
operation: function(f){return
|
|
3037
|
+
operation: function(f){return runInOp(this, f);},
|
|
2852
3038
|
|
|
2853
|
-
refresh: function() {
|
|
3039
|
+
refresh: operation(null, function() {
|
|
2854
3040
|
clearCaches(this);
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
3041
|
+
updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
|
|
3042
|
+
regChange(this);
|
|
3043
|
+
}),
|
|
3044
|
+
|
|
3045
|
+
swapDoc: operation(null, function(doc) {
|
|
3046
|
+
var old = this.doc;
|
|
3047
|
+
old.cm = null;
|
|
3048
|
+
attachDoc(this, doc);
|
|
3049
|
+
clearCaches(this);
|
|
3050
|
+
resetInput(this, true);
|
|
3051
|
+
updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
|
|
3052
|
+
return old;
|
|
3053
|
+
}),
|
|
2862
3054
|
|
|
2863
3055
|
getInputField: function(){return this.display.input;},
|
|
2864
3056
|
getWrapperElement: function(){return this.display.wrapper;},
|
|
@@ -2883,8 +3075,13 @@ window.CodeMirror = (function() {
|
|
|
2883
3075
|
|
|
2884
3076
|
// These two are, on init, called from the constructor because they
|
|
2885
3077
|
// have to be initialized before the editor can start at all.
|
|
2886
|
-
option("value", "", function(cm, val) {
|
|
2887
|
-
|
|
3078
|
+
option("value", "", function(cm, val) {
|
|
3079
|
+
cm.setValue(val);
|
|
3080
|
+
}, true);
|
|
3081
|
+
option("mode", null, function(cm, val) {
|
|
3082
|
+
cm.doc.modeOption = val;
|
|
3083
|
+
loadMode(cm);
|
|
3084
|
+
}, true);
|
|
2888
3085
|
|
|
2889
3086
|
option("indentUnit", 2, loadMode, true);
|
|
2890
3087
|
option("indentWithTabs", false);
|
|
@@ -2892,7 +3089,7 @@ window.CodeMirror = (function() {
|
|
|
2892
3089
|
option("tabSize", 4, function(cm) {
|
|
2893
3090
|
loadMode(cm);
|
|
2894
3091
|
clearCaches(cm);
|
|
2895
|
-
|
|
3092
|
+
regChange(cm);
|
|
2896
3093
|
}, true);
|
|
2897
3094
|
option("electricChars", true);
|
|
2898
3095
|
option("rtlMoveVisually", !windows);
|
|
@@ -2923,7 +3120,7 @@ window.CodeMirror = (function() {
|
|
|
2923
3120
|
option("firstLineNumber", 1, guttersChanged, true);
|
|
2924
3121
|
option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
|
|
2925
3122
|
option("showCursorWhenSelecting", false, updateSelection, true);
|
|
2926
|
-
|
|
3123
|
+
|
|
2927
3124
|
option("readOnly", false, function(cm, val) {
|
|
2928
3125
|
if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
|
|
2929
3126
|
else if (!val) resetInput(cm, true);
|
|
@@ -2936,8 +3133,13 @@ window.CodeMirror = (function() {
|
|
|
2936
3133
|
option("workDelay", 100);
|
|
2937
3134
|
option("flattenSpans", true);
|
|
2938
3135
|
option("pollInterval", 100);
|
|
2939
|
-
option("undoDepth", 40);
|
|
3136
|
+
option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
|
|
3137
|
+
option("historyEventDelay", 500);
|
|
2940
3138
|
option("viewportMargin", 10, function(cm){cm.refresh();}, true);
|
|
3139
|
+
option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
|
|
3140
|
+
option("moveInputWithCursor", true, function(cm, val) {
|
|
3141
|
+
if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
|
|
3142
|
+
});
|
|
2941
3143
|
|
|
2942
3144
|
option("tabindex", null, function(cm, val) {
|
|
2943
3145
|
cm.display.input.tabIndex = val || "";
|
|
@@ -2996,8 +3198,7 @@ window.CodeMirror = (function() {
|
|
|
2996
3198
|
var modeExtensions = CodeMirror.modeExtensions = {};
|
|
2997
3199
|
CodeMirror.extendMode = function(mode, properties) {
|
|
2998
3200
|
var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
|
|
2999
|
-
|
|
3000
|
-
exts[prop] = properties[prop];
|
|
3201
|
+
copyObj(properties, exts);
|
|
3001
3202
|
};
|
|
3002
3203
|
|
|
3003
3204
|
// EXTENSIONS
|
|
@@ -3005,7 +3206,9 @@ window.CodeMirror = (function() {
|
|
|
3005
3206
|
CodeMirror.defineExtension = function(name, func) {
|
|
3006
3207
|
CodeMirror.prototype[name] = func;
|
|
3007
3208
|
};
|
|
3008
|
-
|
|
3209
|
+
CodeMirror.defineDocExtension = function(name, func) {
|
|
3210
|
+
Doc.prototype[name] = func;
|
|
3211
|
+
};
|
|
3009
3212
|
CodeMirror.defineOption = option;
|
|
3010
3213
|
|
|
3011
3214
|
var initHooks = [];
|
|
@@ -3045,21 +3248,21 @@ window.CodeMirror = (function() {
|
|
|
3045
3248
|
// STANDARD COMMANDS
|
|
3046
3249
|
|
|
3047
3250
|
var commands = CodeMirror.commands = {
|
|
3048
|
-
selectAll: function(cm) {cm.setSelection(
|
|
3251
|
+
selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
|
|
3049
3252
|
killLine: function(cm) {
|
|
3050
3253
|
var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
|
|
3051
3254
|
if (!sel && cm.getLine(from.line).length == from.ch)
|
|
3052
|
-
cm.replaceRange("", from,
|
|
3053
|
-
else cm.replaceRange("", from, sel ? to :
|
|
3255
|
+
cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
|
|
3256
|
+
else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
|
|
3054
3257
|
},
|
|
3055
3258
|
deleteLine: function(cm) {
|
|
3056
3259
|
var l = cm.getCursor().line;
|
|
3057
|
-
cm.replaceRange("",
|
|
3260
|
+
cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
|
|
3058
3261
|
},
|
|
3059
3262
|
undo: function(cm) {cm.undo();},
|
|
3060
3263
|
redo: function(cm) {cm.redo();},
|
|
3061
|
-
goDocStart: function(cm) {cm.extendSelection(
|
|
3062
|
-
goDocEnd: function(cm) {cm.extendSelection(
|
|
3264
|
+
goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
|
|
3265
|
+
goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
|
|
3063
3266
|
goLineStart: function(cm) {
|
|
3064
3267
|
cm.extendSelection(lineStart(cm, cm.getCursor().line));
|
|
3065
3268
|
},
|
|
@@ -3070,12 +3273,20 @@ window.CodeMirror = (function() {
|
|
|
3070
3273
|
if (!order || order[0].level == 0) {
|
|
3071
3274
|
var firstNonWS = Math.max(0, line.text.search(/\S/));
|
|
3072
3275
|
var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
|
|
3073
|
-
cm.extendSelection(
|
|
3276
|
+
cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
|
|
3074
3277
|
} else cm.extendSelection(start);
|
|
3075
3278
|
},
|
|
3076
3279
|
goLineEnd: function(cm) {
|
|
3077
3280
|
cm.extendSelection(lineEnd(cm, cm.getCursor().line));
|
|
3078
3281
|
},
|
|
3282
|
+
goLineRight: function(cm) {
|
|
3283
|
+
var top = cm.charCoords(cm.getCursor(), "div").top + 5;
|
|
3284
|
+
cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
|
|
3285
|
+
},
|
|
3286
|
+
goLineLeft: function(cm) {
|
|
3287
|
+
var top = cm.charCoords(cm.getCursor(), "div").top + 5;
|
|
3288
|
+
cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
|
|
3289
|
+
},
|
|
3079
3290
|
goLineUp: function(cm) {cm.moveV(-1, "line");},
|
|
3080
3291
|
goLineDown: function(cm) {cm.moveV(1, "line");},
|
|
3081
3292
|
goPageUp: function(cm) {cm.moveV(-1, "page");},
|
|
@@ -3085,28 +3296,32 @@ window.CodeMirror = (function() {
|
|
|
3085
3296
|
goColumnLeft: function(cm) {cm.moveH(-1, "column");},
|
|
3086
3297
|
goColumnRight: function(cm) {cm.moveH(1, "column");},
|
|
3087
3298
|
goWordLeft: function(cm) {cm.moveH(-1, "word");},
|
|
3299
|
+
goGroupRight: function(cm) {cm.moveH(1, "group");},
|
|
3300
|
+
goGroupLeft: function(cm) {cm.moveH(-1, "group");},
|
|
3088
3301
|
goWordRight: function(cm) {cm.moveH(1, "word");},
|
|
3089
3302
|
delCharBefore: function(cm) {cm.deleteH(-1, "char");},
|
|
3090
3303
|
delCharAfter: function(cm) {cm.deleteH(1, "char");},
|
|
3091
3304
|
delWordBefore: function(cm) {cm.deleteH(-1, "word");},
|
|
3092
3305
|
delWordAfter: function(cm) {cm.deleteH(1, "word");},
|
|
3306
|
+
delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
|
|
3307
|
+
delGroupAfter: function(cm) {cm.deleteH(1, "group");},
|
|
3093
3308
|
indentAuto: function(cm) {cm.indentSelection("smart");},
|
|
3094
3309
|
indentMore: function(cm) {cm.indentSelection("add");},
|
|
3095
3310
|
indentLess: function(cm) {cm.indentSelection("subtract");},
|
|
3096
|
-
insertTab: function(cm) {cm.replaceSelection("\t", "end", "input");},
|
|
3311
|
+
insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
|
|
3097
3312
|
defaultTab: function(cm) {
|
|
3098
3313
|
if (cm.somethingSelected()) cm.indentSelection("add");
|
|
3099
|
-
else cm.replaceSelection("\t", "end", "input");
|
|
3314
|
+
else cm.replaceSelection("\t", "end", "+input");
|
|
3100
3315
|
},
|
|
3101
3316
|
transposeChars: function(cm) {
|
|
3102
3317
|
var cur = cm.getCursor(), line = cm.getLine(cur.line);
|
|
3103
3318
|
if (cur.ch > 0 && cur.ch < line.length - 1)
|
|
3104
3319
|
cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
|
|
3105
|
-
|
|
3320
|
+
Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
|
|
3106
3321
|
},
|
|
3107
3322
|
newlineAndIndent: function(cm) {
|
|
3108
3323
|
operation(cm, function() {
|
|
3109
|
-
cm.replaceSelection("\n", "end", "input");
|
|
3324
|
+
cm.replaceSelection("\n", "end", "+input");
|
|
3110
3325
|
cm.indentLine(cm.getCursor().line, null, true);
|
|
3111
3326
|
})();
|
|
3112
3327
|
},
|
|
@@ -3127,17 +3342,17 @@ window.CodeMirror = (function() {
|
|
|
3127
3342
|
keyMap.pcDefault = {
|
|
3128
3343
|
"Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
|
|
3129
3344
|
"Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
|
|
3130
|
-
"Ctrl-Left": "
|
|
3131
|
-
"Ctrl-Backspace": "
|
|
3345
|
+
"Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
|
|
3346
|
+
"Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
|
|
3132
3347
|
"Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
|
|
3133
3348
|
"Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
|
|
3134
3349
|
fallthrough: "basic"
|
|
3135
3350
|
};
|
|
3136
3351
|
keyMap.macDefault = {
|
|
3137
3352
|
"Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
|
|
3138
|
-
"Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "
|
|
3139
|
-
"Alt-Right": "
|
|
3140
|
-
"Ctrl-Alt-Backspace": "
|
|
3353
|
+
"Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
|
|
3354
|
+
"Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
|
|
3355
|
+
"Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
|
|
3141
3356
|
"Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
|
|
3142
3357
|
"Cmd-[": "indentLess", "Cmd-]": "indentMore",
|
|
3143
3358
|
fallthrough: ["basic", "emacsy"]
|
|
@@ -3157,37 +3372,47 @@ window.CodeMirror = (function() {
|
|
|
3157
3372
|
else return val;
|
|
3158
3373
|
}
|
|
3159
3374
|
|
|
3160
|
-
function lookupKey(name, maps, handle
|
|
3375
|
+
function lookupKey(name, maps, handle) {
|
|
3161
3376
|
function lookup(map) {
|
|
3162
3377
|
map = getKeyMap(map);
|
|
3163
3378
|
var found = map[name];
|
|
3164
|
-
if (found === false)
|
|
3165
|
-
if (stop) stop();
|
|
3166
|
-
return true;
|
|
3167
|
-
}
|
|
3379
|
+
if (found === false) return "stop";
|
|
3168
3380
|
if (found != null && handle(found)) return true;
|
|
3169
|
-
if (map.nofallthrough)
|
|
3170
|
-
|
|
3171
|
-
return true;
|
|
3172
|
-
}
|
|
3381
|
+
if (map.nofallthrough) return "stop";
|
|
3382
|
+
|
|
3173
3383
|
var fallthrough = map.fallthrough;
|
|
3174
3384
|
if (fallthrough == null) return false;
|
|
3175
3385
|
if (Object.prototype.toString.call(fallthrough) != "[object Array]")
|
|
3176
3386
|
return lookup(fallthrough);
|
|
3177
3387
|
for (var i = 0, e = fallthrough.length; i < e; ++i) {
|
|
3178
|
-
|
|
3388
|
+
var done = lookup(fallthrough[i]);
|
|
3389
|
+
if (done) return done;
|
|
3179
3390
|
}
|
|
3180
3391
|
return false;
|
|
3181
3392
|
}
|
|
3182
3393
|
|
|
3183
|
-
for (var i = 0; i < maps.length; ++i)
|
|
3184
|
-
|
|
3394
|
+
for (var i = 0; i < maps.length; ++i) {
|
|
3395
|
+
var done = lookup(maps[i]);
|
|
3396
|
+
if (done) return done;
|
|
3397
|
+
}
|
|
3185
3398
|
}
|
|
3186
3399
|
function isModifierKey(event) {
|
|
3187
|
-
var name = keyNames[
|
|
3400
|
+
var name = keyNames[event.keyCode];
|
|
3188
3401
|
return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
|
|
3189
3402
|
}
|
|
3403
|
+
function keyName(event, noShift) {
|
|
3404
|
+
if (opera && event.keyCode == 34 && event["char"]) return false;
|
|
3405
|
+
var name = keyNames[event.keyCode];
|
|
3406
|
+
if (name == null || event.altGraphKey) return false;
|
|
3407
|
+
if (event.altKey) name = "Alt-" + name;
|
|
3408
|
+
if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
|
|
3409
|
+
if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
|
|
3410
|
+
if (!noShift && event.shiftKey) name = "Shift-" + name;
|
|
3411
|
+
return name;
|
|
3412
|
+
}
|
|
3413
|
+
CodeMirror.lookupKey = lookupKey;
|
|
3190
3414
|
CodeMirror.isModifierKey = isModifierKey;
|
|
3415
|
+
CodeMirror.keyName = keyName;
|
|
3191
3416
|
|
|
3192
3417
|
// FROMTEXTAREA
|
|
3193
3418
|
|
|
@@ -3196,6 +3421,8 @@ window.CodeMirror = (function() {
|
|
|
3196
3421
|
options.value = textarea.value;
|
|
3197
3422
|
if (!options.tabindex && textarea.tabindex)
|
|
3198
3423
|
options.tabindex = textarea.tabindex;
|
|
3424
|
+
if (!options.placeholder && textarea.placeholder)
|
|
3425
|
+
options.placeholder = textarea.placeholder;
|
|
3199
3426
|
// Set autofocus to true if this textarea is focused, or if it has
|
|
3200
3427
|
// autofocus and no other element is focused.
|
|
3201
3428
|
if (options.autofocus == null) {
|
|
@@ -3208,17 +3435,19 @@ window.CodeMirror = (function() {
|
|
|
3208
3435
|
|
|
3209
3436
|
function save() {textarea.value = cm.getValue();}
|
|
3210
3437
|
if (textarea.form) {
|
|
3211
|
-
// Deplorable hack to make the submit method do the right thing.
|
|
3212
3438
|
on(textarea.form, "submit", save);
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
form
|
|
3216
|
-
|
|
3217
|
-
form.submit =
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3439
|
+
// Deplorable hack to make the submit method do the right thing.
|
|
3440
|
+
if (!options.leaveSubmitMethodAlone) {
|
|
3441
|
+
var form = textarea.form, realSubmit = form.submit;
|
|
3442
|
+
try {
|
|
3443
|
+
var wrappedSubmit = form.submit = function() {
|
|
3444
|
+
save();
|
|
3445
|
+
form.submit = realSubmit;
|
|
3446
|
+
form.submit();
|
|
3447
|
+
form.submit = wrappedSubmit;
|
|
3448
|
+
};
|
|
3449
|
+
} catch(e) {}
|
|
3450
|
+
}
|
|
3222
3451
|
}
|
|
3223
3452
|
|
|
3224
3453
|
textarea.style.display = "none";
|
|
@@ -3250,6 +3479,7 @@ window.CodeMirror = (function() {
|
|
|
3250
3479
|
this.pos = this.start = 0;
|
|
3251
3480
|
this.string = string;
|
|
3252
3481
|
this.tabSize = tabSize || 8;
|
|
3482
|
+
this.lastColumnPos = this.lastColumnValue = 0;
|
|
3253
3483
|
}
|
|
3254
3484
|
|
|
3255
3485
|
StringStream.prototype = {
|
|
@@ -3282,12 +3512,19 @@ window.CodeMirror = (function() {
|
|
|
3282
3512
|
if (found > -1) {this.pos = found; return true;}
|
|
3283
3513
|
},
|
|
3284
3514
|
backUp: function(n) {this.pos -= n;},
|
|
3285
|
-
column: function() {
|
|
3515
|
+
column: function() {
|
|
3516
|
+
if (this.lastColumnPos < this.start) {
|
|
3517
|
+
this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
|
|
3518
|
+
this.lastColumnPos = this.start;
|
|
3519
|
+
}
|
|
3520
|
+
return this.lastColumnValue;
|
|
3521
|
+
},
|
|
3286
3522
|
indentation: function() {return countColumn(this.string, null, this.tabSize);},
|
|
3287
3523
|
match: function(pattern, consume, caseInsensitive) {
|
|
3288
3524
|
if (typeof pattern == "string") {
|
|
3289
3525
|
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
|
3290
|
-
|
|
3526
|
+
var substr = this.string.substr(this.pos, pattern.length);
|
|
3527
|
+
if (cased(substr) == cased(pattern)) {
|
|
3291
3528
|
if (consume !== false) this.pos += pattern.length;
|
|
3292
3529
|
return true;
|
|
3293
3530
|
}
|
|
@@ -3304,17 +3541,18 @@ window.CodeMirror = (function() {
|
|
|
3304
3541
|
|
|
3305
3542
|
// TEXTMARKERS
|
|
3306
3543
|
|
|
3307
|
-
function TextMarker(
|
|
3544
|
+
function TextMarker(doc, type) {
|
|
3308
3545
|
this.lines = [];
|
|
3309
3546
|
this.type = type;
|
|
3310
|
-
this.
|
|
3547
|
+
this.doc = doc;
|
|
3311
3548
|
}
|
|
3312
3549
|
CodeMirror.TextMarker = TextMarker;
|
|
3313
3550
|
|
|
3314
3551
|
TextMarker.prototype.clear = function() {
|
|
3315
3552
|
if (this.explicitlyCleared) return;
|
|
3316
|
-
|
|
3317
|
-
|
|
3553
|
+
var cm = this.doc.cm, withOp = cm && !cm.curOp;
|
|
3554
|
+
if (withOp) startOperation(cm);
|
|
3555
|
+
var min = null, max = null;
|
|
3318
3556
|
for (var i = 0; i < this.lines.length; ++i) {
|
|
3319
3557
|
var line = this.lines[i];
|
|
3320
3558
|
var span = getMarkedSpanFor(line.markedSpans, this);
|
|
@@ -3322,27 +3560,27 @@ window.CodeMirror = (function() {
|
|
|
3322
3560
|
line.markedSpans = removeMarkedSpan(line.markedSpans, span);
|
|
3323
3561
|
if (span.from != null)
|
|
3324
3562
|
min = lineNo(line);
|
|
3325
|
-
else if (this.collapsed && !lineIsHidden(line))
|
|
3326
|
-
updateLineHeight(line, textHeight(
|
|
3327
|
-
}
|
|
3328
|
-
if (this.collapsed && !
|
|
3329
|
-
var visual = visualLine(
|
|
3330
|
-
if (len >
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3563
|
+
else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
|
|
3564
|
+
updateLineHeight(line, textHeight(cm.display));
|
|
3565
|
+
}
|
|
3566
|
+
if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
|
|
3567
|
+
var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
|
|
3568
|
+
if (len > cm.display.maxLineLength) {
|
|
3569
|
+
cm.display.maxLine = visual;
|
|
3570
|
+
cm.display.maxLineLength = len;
|
|
3571
|
+
cm.display.maxLineChanged = true;
|
|
3334
3572
|
}
|
|
3335
3573
|
}
|
|
3336
3574
|
|
|
3337
|
-
if (min != null) regChange(
|
|
3575
|
+
if (min != null && cm) regChange(cm, min, max + 1);
|
|
3338
3576
|
this.lines.length = 0;
|
|
3339
3577
|
this.explicitlyCleared = true;
|
|
3340
|
-
if (this.collapsed && this.
|
|
3341
|
-
this.
|
|
3342
|
-
reCheckSelection(
|
|
3578
|
+
if (this.collapsed && this.doc.cantEdit) {
|
|
3579
|
+
this.doc.cantEdit = false;
|
|
3580
|
+
if (cm) reCheckSelection(cm);
|
|
3343
3581
|
}
|
|
3344
|
-
endOperation(
|
|
3345
|
-
signalLater(this
|
|
3582
|
+
if (withOp) endOperation(cm);
|
|
3583
|
+
signalLater(this, "clear");
|
|
3346
3584
|
};
|
|
3347
3585
|
|
|
3348
3586
|
TextMarker.prototype.find = function() {
|
|
@@ -3352,8 +3590,8 @@ window.CodeMirror = (function() {
|
|
|
3352
3590
|
var span = getMarkedSpanFor(line.markedSpans, this);
|
|
3353
3591
|
if (span.from != null || span.to != null) {
|
|
3354
3592
|
var found = lineNo(line);
|
|
3355
|
-
if (span.from != null) from =
|
|
3356
|
-
if (span.to != null) to =
|
|
3593
|
+
if (span.from != null) from = Pos(found, span.from);
|
|
3594
|
+
if (span.to != null) to = Pos(found, span.to);
|
|
3357
3595
|
}
|
|
3358
3596
|
}
|
|
3359
3597
|
if (this.type == "bookmark") return from;
|
|
@@ -3366,28 +3604,48 @@ window.CodeMirror = (function() {
|
|
|
3366
3604
|
inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight,
|
|
3367
3605
|
atomic: this.atomic,
|
|
3368
3606
|
collapsed: this.collapsed,
|
|
3369
|
-
clearOnEnter: this.clearOnEnter,
|
|
3370
3607
|
replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl,
|
|
3371
3608
|
readOnly: this.readOnly,
|
|
3372
3609
|
startStyle: this.startStyle, endStyle: this.endStyle};
|
|
3373
3610
|
};
|
|
3374
3611
|
|
|
3375
|
-
function
|
|
3376
|
-
|
|
3377
|
-
|
|
3612
|
+
TextMarker.prototype.attachLine = function(line) {
|
|
3613
|
+
if (!this.lines.length && this.doc.cm) {
|
|
3614
|
+
var op = this.doc.cm.curOp;
|
|
3615
|
+
if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
|
|
3616
|
+
(op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
|
|
3617
|
+
}
|
|
3618
|
+
this.lines.push(line);
|
|
3619
|
+
};
|
|
3620
|
+
TextMarker.prototype.detachLine = function(line) {
|
|
3621
|
+
this.lines.splice(indexOf(this.lines, line), 1);
|
|
3622
|
+
if (!this.lines.length && this.doc.cm) {
|
|
3623
|
+
var op = this.doc.cm.curOp;
|
|
3624
|
+
(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
|
|
3625
|
+
}
|
|
3626
|
+
};
|
|
3627
|
+
|
|
3628
|
+
function markText(doc, from, to, options, type) {
|
|
3629
|
+
if (options && options.shared) return markTextShared(doc, from, to, options, type);
|
|
3630
|
+
if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
|
|
3631
|
+
|
|
3632
|
+
var marker = new TextMarker(doc, type);
|
|
3378
3633
|
if (type == "range" && !posLess(from, to)) return marker;
|
|
3379
|
-
if (options)
|
|
3380
|
-
marker[opt] = options[opt];
|
|
3634
|
+
if (options) copyObj(options, marker);
|
|
3381
3635
|
if (marker.replacedWith) {
|
|
3382
3636
|
marker.collapsed = true;
|
|
3383
3637
|
marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
|
|
3384
3638
|
}
|
|
3385
3639
|
if (marker.collapsed) sawCollapsedSpans = true;
|
|
3386
3640
|
|
|
3387
|
-
|
|
3641
|
+
if (marker.addToHistory)
|
|
3642
|
+
addToHistory(doc, {from: from, to: to, origin: "markText"},
|
|
3643
|
+
{head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
|
|
3644
|
+
|
|
3645
|
+
var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
|
|
3388
3646
|
doc.iter(curLine, to.line + 1, function(line) {
|
|
3389
|
-
if (marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.
|
|
3390
|
-
|
|
3647
|
+
if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
|
|
3648
|
+
updateMaxLine = true;
|
|
3391
3649
|
var span = {from: null, to: null, marker: marker};
|
|
3392
3650
|
size += line.text.length;
|
|
3393
3651
|
if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
|
|
@@ -3401,13 +3659,15 @@ window.CodeMirror = (function() {
|
|
|
3401
3659
|
++curLine;
|
|
3402
3660
|
});
|
|
3403
3661
|
if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
|
|
3404
|
-
if (lineIsHidden(line)) updateLineHeight(line, 0);
|
|
3662
|
+
if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
|
|
3405
3663
|
});
|
|
3406
3664
|
|
|
3665
|
+
if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
|
|
3666
|
+
|
|
3407
3667
|
if (marker.readOnly) {
|
|
3408
3668
|
sawReadOnlySpans = true;
|
|
3409
|
-
if (
|
|
3410
|
-
|
|
3669
|
+
if (doc.history.done.length || doc.history.undone.length)
|
|
3670
|
+
doc.clearHistory();
|
|
3411
3671
|
}
|
|
3412
3672
|
if (marker.collapsed) {
|
|
3413
3673
|
if (collapsedAtStart != collapsedAtEnd)
|
|
@@ -3415,12 +3675,58 @@ window.CodeMirror = (function() {
|
|
|
3415
3675
|
marker.size = size;
|
|
3416
3676
|
marker.atomic = true;
|
|
3417
3677
|
}
|
|
3418
|
-
if (
|
|
3419
|
-
|
|
3420
|
-
|
|
3678
|
+
if (cm) {
|
|
3679
|
+
if (updateMaxLine) cm.curOp.updateMaxLine = true;
|
|
3680
|
+
if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed)
|
|
3681
|
+
regChange(cm, from.line, to.line + 1);
|
|
3682
|
+
if (marker.atomic) reCheckSelection(cm);
|
|
3683
|
+
}
|
|
3421
3684
|
return marker;
|
|
3422
3685
|
}
|
|
3423
3686
|
|
|
3687
|
+
// SHARED TEXTMARKERS
|
|
3688
|
+
|
|
3689
|
+
function SharedTextMarker(markers, primary) {
|
|
3690
|
+
this.markers = markers;
|
|
3691
|
+
this.primary = primary;
|
|
3692
|
+
for (var i = 0, me = this; i < markers.length; ++i) {
|
|
3693
|
+
markers[i].parent = this;
|
|
3694
|
+
on(markers[i], "clear", function(){me.clear();});
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
CodeMirror.SharedTextMarker = SharedTextMarker;
|
|
3698
|
+
|
|
3699
|
+
SharedTextMarker.prototype.clear = function() {
|
|
3700
|
+
if (this.explicitlyCleared) return;
|
|
3701
|
+
this.explicitlyCleared = true;
|
|
3702
|
+
for (var i = 0; i < this.markers.length; ++i)
|
|
3703
|
+
this.markers[i].clear();
|
|
3704
|
+
signalLater(this, "clear");
|
|
3705
|
+
};
|
|
3706
|
+
SharedTextMarker.prototype.find = function() {
|
|
3707
|
+
return this.primary.find();
|
|
3708
|
+
};
|
|
3709
|
+
SharedTextMarker.prototype.getOptions = function(copyWidget) {
|
|
3710
|
+
var inner = this.primary.getOptions(copyWidget);
|
|
3711
|
+
inner.shared = true;
|
|
3712
|
+
return inner;
|
|
3713
|
+
};
|
|
3714
|
+
|
|
3715
|
+
function markTextShared(doc, from, to, options, type) {
|
|
3716
|
+
options = copyObj(options);
|
|
3717
|
+
options.shared = false;
|
|
3718
|
+
var markers = [markText(doc, from, to, options, type)], primary = markers[0];
|
|
3719
|
+
var widget = options.replacedWith;
|
|
3720
|
+
linkedDocs(doc, function(doc) {
|
|
3721
|
+
if (widget) options.replacedWith = widget.cloneNode(true);
|
|
3722
|
+
markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
|
|
3723
|
+
for (var i = 0; i < doc.linked.length; ++i)
|
|
3724
|
+
if (doc.linked[i].isParent) return;
|
|
3725
|
+
primary = lst(markers);
|
|
3726
|
+
});
|
|
3727
|
+
return new SharedTextMarker(markers, primary);
|
|
3728
|
+
}
|
|
3729
|
+
|
|
3424
3730
|
// TEXTMARKER SPANS
|
|
3425
3731
|
|
|
3426
3732
|
function getMarkedSpanFor(spans, marker) {
|
|
@@ -3436,14 +3742,14 @@ window.CodeMirror = (function() {
|
|
|
3436
3742
|
}
|
|
3437
3743
|
function addMarkedSpan(line, span) {
|
|
3438
3744
|
line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
|
|
3439
|
-
span.marker.
|
|
3745
|
+
span.marker.attachLine(line);
|
|
3440
3746
|
}
|
|
3441
3747
|
|
|
3442
|
-
function markedSpansBefore(old, startCh) {
|
|
3748
|
+
function markedSpansBefore(old, startCh, isInsert) {
|
|
3443
3749
|
if (old) for (var i = 0, nw; i < old.length; ++i) {
|
|
3444
3750
|
var span = old[i], marker = span.marker;
|
|
3445
3751
|
var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
|
|
3446
|
-
if (startsBefore || marker.type == "bookmark" && span.from == startCh) {
|
|
3752
|
+
if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
|
|
3447
3753
|
var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
|
|
3448
3754
|
(nw || (nw = [])).push({from: span.from,
|
|
3449
3755
|
to: endsAfter ? null : span.to,
|
|
@@ -3453,11 +3759,11 @@ window.CodeMirror = (function() {
|
|
|
3453
3759
|
return nw;
|
|
3454
3760
|
}
|
|
3455
3761
|
|
|
3456
|
-
function markedSpansAfter(old,
|
|
3762
|
+
function markedSpansAfter(old, endCh, isInsert) {
|
|
3457
3763
|
if (old) for (var i = 0, nw; i < old.length; ++i) {
|
|
3458
3764
|
var span = old[i], marker = span.marker;
|
|
3459
3765
|
var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
|
|
3460
|
-
if (endsAfter || marker.type == "bookmark" && span.from == endCh && span.
|
|
3766
|
+
if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
|
|
3461
3767
|
var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
|
|
3462
3768
|
(nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
|
|
3463
3769
|
to: span.to == null ? null : span.to - endCh,
|
|
@@ -3467,14 +3773,18 @@ window.CodeMirror = (function() {
|
|
|
3467
3773
|
return nw;
|
|
3468
3774
|
}
|
|
3469
3775
|
|
|
3470
|
-
function
|
|
3471
|
-
|
|
3776
|
+
function stretchSpansOverChange(doc, change) {
|
|
3777
|
+
var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
|
|
3778
|
+
var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
|
|
3779
|
+
if (!oldFirst && !oldLast) return null;
|
|
3780
|
+
|
|
3781
|
+
var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
|
|
3472
3782
|
// Get the spans that 'stick out' on both sides
|
|
3473
|
-
var first = markedSpansBefore(oldFirst, startCh);
|
|
3474
|
-
var last = markedSpansAfter(oldLast,
|
|
3783
|
+
var first = markedSpansBefore(oldFirst, startCh, isInsert);
|
|
3784
|
+
var last = markedSpansAfter(oldLast, endCh, isInsert);
|
|
3475
3785
|
|
|
3476
3786
|
// Next, merge those two ends
|
|
3477
|
-
var sameLine =
|
|
3787
|
+
var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
|
|
3478
3788
|
if (first) {
|
|
3479
3789
|
// Fix up .to properties of first
|
|
3480
3790
|
for (var i = 0; i < first.length; ++i) {
|
|
@@ -3504,21 +3814,43 @@ window.CodeMirror = (function() {
|
|
|
3504
3814
|
}
|
|
3505
3815
|
}
|
|
3506
3816
|
|
|
3507
|
-
var newMarkers = [
|
|
3817
|
+
var newMarkers = [first];
|
|
3508
3818
|
if (!sameLine) {
|
|
3509
3819
|
// Fill gap with whole-line-spans
|
|
3510
|
-
var gap =
|
|
3820
|
+
var gap = change.text.length - 2, gapMarkers;
|
|
3511
3821
|
if (gap > 0 && first)
|
|
3512
3822
|
for (var i = 0; i < first.length; ++i)
|
|
3513
3823
|
if (first[i].to == null)
|
|
3514
3824
|
(gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
|
|
3515
3825
|
for (var i = 0; i < gap; ++i)
|
|
3516
|
-
newMarkers.push(
|
|
3517
|
-
newMarkers.push(
|
|
3826
|
+
newMarkers.push(gapMarkers);
|
|
3827
|
+
newMarkers.push(last);
|
|
3518
3828
|
}
|
|
3519
3829
|
return newMarkers;
|
|
3520
3830
|
}
|
|
3521
3831
|
|
|
3832
|
+
function mergeOldSpans(doc, change) {
|
|
3833
|
+
var old = getOldSpans(doc, change);
|
|
3834
|
+
var stretched = stretchSpansOverChange(doc, change);
|
|
3835
|
+
if (!old) return stretched;
|
|
3836
|
+
if (!stretched) return old;
|
|
3837
|
+
|
|
3838
|
+
for (var i = 0; i < old.length; ++i) {
|
|
3839
|
+
var oldCur = old[i], stretchCur = stretched[i];
|
|
3840
|
+
if (oldCur && stretchCur) {
|
|
3841
|
+
spans: for (var j = 0; j < stretchCur.length; ++j) {
|
|
3842
|
+
var span = stretchCur[j];
|
|
3843
|
+
for (var k = 0; k < oldCur.length; ++k)
|
|
3844
|
+
if (oldCur[k].marker == span.marker) continue spans;
|
|
3845
|
+
oldCur.push(span);
|
|
3846
|
+
}
|
|
3847
|
+
} else if (stretchCur) {
|
|
3848
|
+
old[i] = stretchCur;
|
|
3849
|
+
}
|
|
3850
|
+
}
|
|
3851
|
+
return old;
|
|
3852
|
+
}
|
|
3853
|
+
|
|
3522
3854
|
function removeReadOnlyRanges(doc, from, to) {
|
|
3523
3855
|
var markers = null;
|
|
3524
3856
|
doc.iter(from.line, to.line + 1, function(line) {
|
|
@@ -3531,13 +3863,15 @@ window.CodeMirror = (function() {
|
|
|
3531
3863
|
if (!markers) return null;
|
|
3532
3864
|
var parts = [{from: from, to: to}];
|
|
3533
3865
|
for (var i = 0; i < markers.length; ++i) {
|
|
3534
|
-
var
|
|
3866
|
+
var mk = markers[i], m = mk.find();
|
|
3535
3867
|
for (var j = 0; j < parts.length; ++j) {
|
|
3536
3868
|
var p = parts[j];
|
|
3537
|
-
if (
|
|
3869
|
+
if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
|
|
3538
3870
|
var newParts = [j, 1];
|
|
3539
|
-
if (posLess(p.from, m.from)
|
|
3540
|
-
|
|
3871
|
+
if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
|
|
3872
|
+
newParts.push({from: p.from, to: m.from});
|
|
3873
|
+
if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
|
|
3874
|
+
newParts.push({from: m.to, to: p.to});
|
|
3541
3875
|
parts.splice.apply(parts, newParts);
|
|
3542
3876
|
j += newParts.length - 1;
|
|
3543
3877
|
}
|
|
@@ -3567,20 +3901,20 @@ window.CodeMirror = (function() {
|
|
|
3567
3901
|
return line;
|
|
3568
3902
|
}
|
|
3569
3903
|
|
|
3570
|
-
function lineIsHidden(line) {
|
|
3904
|
+
function lineIsHidden(doc, line) {
|
|
3571
3905
|
var sps = sawCollapsedSpans && line.markedSpans;
|
|
3572
3906
|
if (sps) for (var sp, i = 0; i < sps.length; ++i) {
|
|
3573
3907
|
sp = sps[i];
|
|
3574
3908
|
if (!sp.marker.collapsed) continue;
|
|
3575
3909
|
if (sp.from == null) return true;
|
|
3576
|
-
if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(line, sp))
|
|
3910
|
+
if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
|
|
3577
3911
|
return true;
|
|
3578
3912
|
}
|
|
3579
3913
|
}
|
|
3580
|
-
function lineIsHiddenInner(line, span) {
|
|
3914
|
+
function lineIsHiddenInner(doc, line, span) {
|
|
3581
3915
|
if (span.to == null) {
|
|
3582
|
-
var end = span.marker.find().to, endLine = getLine(
|
|
3583
|
-
return lineIsHiddenInner(endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
|
|
3916
|
+
var end = span.marker.find().to, endLine = getLine(doc, end.line);
|
|
3917
|
+
return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
|
|
3584
3918
|
}
|
|
3585
3919
|
if (span.marker.inclusiveRight && span.to == line.text.length)
|
|
3586
3920
|
return true;
|
|
@@ -3588,39 +3922,22 @@ window.CodeMirror = (function() {
|
|
|
3588
3922
|
sp = line.markedSpans[i];
|
|
3589
3923
|
if (sp.marker.collapsed && sp.from == span.to &&
|
|
3590
3924
|
(sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
|
|
3591
|
-
lineIsHiddenInner(line, sp)) return true;
|
|
3925
|
+
lineIsHiddenInner(doc, line, sp)) return true;
|
|
3592
3926
|
}
|
|
3593
3927
|
}
|
|
3594
3928
|
|
|
3595
|
-
// hl stands for history-line, a data structure that can be either a
|
|
3596
|
-
// string (line without markers) or a {text, markedSpans} object.
|
|
3597
|
-
function hlText(val) { return typeof val == "string" ? val : val.text; }
|
|
3598
|
-
function hlSpans(val) {
|
|
3599
|
-
if (typeof val == "string") return null;
|
|
3600
|
-
var spans = val.markedSpans, out = null;
|
|
3601
|
-
for (var i = 0; i < spans.length; ++i) {
|
|
3602
|
-
if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
|
|
3603
|
-
else if (out) out.push(spans[i]);
|
|
3604
|
-
}
|
|
3605
|
-
return !out ? spans : out.length ? out : null;
|
|
3606
|
-
}
|
|
3607
|
-
function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; }
|
|
3608
|
-
|
|
3609
3929
|
function detachMarkedSpans(line) {
|
|
3610
3930
|
var spans = line.markedSpans;
|
|
3611
3931
|
if (!spans) return;
|
|
3612
|
-
for (var i = 0; i < spans.length; ++i)
|
|
3613
|
-
|
|
3614
|
-
var ix = indexOf(lines, line);
|
|
3615
|
-
lines.splice(ix, 1);
|
|
3616
|
-
}
|
|
3932
|
+
for (var i = 0; i < spans.length; ++i)
|
|
3933
|
+
spans[i].marker.detachLine(line);
|
|
3617
3934
|
line.markedSpans = null;
|
|
3618
3935
|
}
|
|
3619
3936
|
|
|
3620
3937
|
function attachMarkedSpans(line, spans) {
|
|
3621
3938
|
if (!spans) return;
|
|
3622
3939
|
for (var i = 0; i < spans.length; ++i)
|
|
3623
|
-
spans[i].marker.
|
|
3940
|
+
spans[i].marker.attachLine(line);
|
|
3624
3941
|
line.markedSpans = spans;
|
|
3625
3942
|
}
|
|
3626
3943
|
|
|
@@ -3634,9 +3951,10 @@ window.CodeMirror = (function() {
|
|
|
3634
3951
|
};
|
|
3635
3952
|
function widgetOperation(f) {
|
|
3636
3953
|
return function() {
|
|
3637
|
-
|
|
3954
|
+
var withOp = !this.cm.curOp;
|
|
3955
|
+
if (withOp) startOperation(this.cm);
|
|
3638
3956
|
try {var result = f.apply(this, arguments);}
|
|
3639
|
-
finally {endOperation(this.cm);}
|
|
3957
|
+
finally {if (withOp) endOperation(this.cm);}
|
|
3640
3958
|
return result;
|
|
3641
3959
|
};
|
|
3642
3960
|
}
|
|
@@ -3644,6 +3962,7 @@ window.CodeMirror = (function() {
|
|
|
3644
3962
|
var ws = this.line.widgets, no = lineNo(this.line);
|
|
3645
3963
|
if (no == null || !ws) return;
|
|
3646
3964
|
for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
|
|
3965
|
+
if (!ws.length) this.line.widgets = null;
|
|
3647
3966
|
updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
|
|
3648
3967
|
regChange(this.cm, no, no + 1);
|
|
3649
3968
|
});
|
|
@@ -3670,11 +3989,10 @@ window.CodeMirror = (function() {
|
|
|
3670
3989
|
changeLine(cm, handle, function(line) {
|
|
3671
3990
|
(line.widgets || (line.widgets = [])).push(widget);
|
|
3672
3991
|
widget.line = line;
|
|
3673
|
-
if (!lineIsHidden(line) || widget.showIfHidden) {
|
|
3992
|
+
if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
|
|
3674
3993
|
var aboveVisible = heightAtLine(cm, line) < cm.display.scroller.scrollTop;
|
|
3675
3994
|
updateLineHeight(line, line.height + widgetHeight(widget));
|
|
3676
|
-
if (aboveVisible)
|
|
3677
|
-
setTimeout(function() {cm.display.scroller.scrollTop += widget.height;});
|
|
3995
|
+
if (aboveVisible) addToScrollPos(cm, 0, widget.height);
|
|
3678
3996
|
}
|
|
3679
3997
|
return true;
|
|
3680
3998
|
});
|
|
@@ -3685,23 +4003,22 @@ window.CodeMirror = (function() {
|
|
|
3685
4003
|
|
|
3686
4004
|
// Line objects. These hold state related to a line, including
|
|
3687
4005
|
// highlighting info (the styles array).
|
|
3688
|
-
function makeLine(text, markedSpans,
|
|
3689
|
-
var line = {text: text
|
|
4006
|
+
function makeLine(text, markedSpans, estimateHeight) {
|
|
4007
|
+
var line = {text: text};
|
|
3690
4008
|
attachMarkedSpans(line, markedSpans);
|
|
3691
|
-
|
|
4009
|
+
line.height = estimateHeight ? estimateHeight(line) : 1;
|
|
3692
4010
|
return line;
|
|
3693
4011
|
}
|
|
3694
4012
|
|
|
3695
|
-
function updateLine(
|
|
4013
|
+
function updateLine(line, text, markedSpans, estimateHeight) {
|
|
3696
4014
|
line.text = text;
|
|
3697
4015
|
if (line.stateAfter) line.stateAfter = null;
|
|
3698
4016
|
if (line.styles) line.styles = null;
|
|
3699
4017
|
if (line.order != null) line.order = null;
|
|
3700
4018
|
detachMarkedSpans(line);
|
|
3701
4019
|
attachMarkedSpans(line, markedSpans);
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
signalLater(cm, line, "change");
|
|
4020
|
+
var estHeight = estimateHeight ? estimateHeight(line) : 1;
|
|
4021
|
+
if (estHeight != line.height) updateLineHeight(line, estHeight);
|
|
3705
4022
|
}
|
|
3706
4023
|
|
|
3707
4024
|
function cleanUpLine(line) {
|
|
@@ -3713,17 +4030,19 @@ window.CodeMirror = (function() {
|
|
|
3713
4030
|
// array, which contains alternating fragments of text and CSS
|
|
3714
4031
|
// classes.
|
|
3715
4032
|
function runMode(cm, text, mode, state, f) {
|
|
3716
|
-
var flattenSpans =
|
|
4033
|
+
var flattenSpans = mode.flattenSpans;
|
|
4034
|
+
if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
|
|
3717
4035
|
var curText = "", curStyle = null;
|
|
3718
|
-
var stream = new StringStream(text, cm.options.tabSize);
|
|
4036
|
+
var stream = new StringStream(text, cm.options.tabSize), style;
|
|
3719
4037
|
if (text == "" && mode.blankLine) mode.blankLine(state);
|
|
3720
4038
|
while (!stream.eol()) {
|
|
3721
|
-
|
|
3722
|
-
if (stream.pos > 5000) {
|
|
4039
|
+
if (stream.pos > cm.options.maxHighlightLength) {
|
|
3723
4040
|
flattenSpans = false;
|
|
3724
4041
|
// Webkit seems to refuse to render text nodes longer than 57444 characters
|
|
3725
4042
|
stream.pos = Math.min(text.length, stream.start + 50000);
|
|
3726
4043
|
style = null;
|
|
4044
|
+
} else {
|
|
4045
|
+
style = mode.token(stream, state);
|
|
3727
4046
|
}
|
|
3728
4047
|
var substr = stream.current();
|
|
3729
4048
|
stream.start = stream.pos;
|
|
@@ -3738,13 +4057,13 @@ window.CodeMirror = (function() {
|
|
|
3738
4057
|
function highlightLine(cm, line, state) {
|
|
3739
4058
|
// A styles array always starts with a number identifying the
|
|
3740
4059
|
// mode/overlays that it is based on (for easy invalidation).
|
|
3741
|
-
var st = [cm.
|
|
4060
|
+
var st = [cm.state.modeGen];
|
|
3742
4061
|
// Compute the base array of styles
|
|
3743
|
-
runMode(cm, line.text, cm.
|
|
4062
|
+
runMode(cm, line.text, cm.doc.mode, state, function(txt, style) {st.push(txt, style);});
|
|
3744
4063
|
|
|
3745
4064
|
// Run overlays, adjust style array.
|
|
3746
|
-
for (var o = 0; o < cm.
|
|
3747
|
-
var overlay = cm.
|
|
4065
|
+
for (var o = 0; o < cm.state.overlays.length; ++o) {
|
|
4066
|
+
var overlay = cm.state.overlays[o], i = 1;
|
|
3748
4067
|
runMode(cm, line.text, overlay.mode, true, function(txt, style) {
|
|
3749
4068
|
var start = i, len = txt.length;
|
|
3750
4069
|
// Ensure there's a token end at the current position, and that i points at it
|
|
@@ -3775,7 +4094,7 @@ window.CodeMirror = (function() {
|
|
|
3775
4094
|
}
|
|
3776
4095
|
|
|
3777
4096
|
function getLineStyles(cm, line) {
|
|
3778
|
-
if (!line.styles || line.styles[0] != cm.
|
|
4097
|
+
if (!line.styles || line.styles[0] != cm.state.modeGen)
|
|
3779
4098
|
line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
|
|
3780
4099
|
return line.styles;
|
|
3781
4100
|
}
|
|
@@ -3783,10 +4102,10 @@ window.CodeMirror = (function() {
|
|
|
3783
4102
|
// Lightweight form of highlight -- proceed over this line and
|
|
3784
4103
|
// update state, but don't save a style array.
|
|
3785
4104
|
function processLine(cm, line, state) {
|
|
3786
|
-
var mode = cm.
|
|
4105
|
+
var mode = cm.doc.mode;
|
|
3787
4106
|
var stream = new StringStream(line.text, cm.options.tabSize);
|
|
3788
4107
|
if (line.text == "" && mode.blankLine) mode.blankLine(state);
|
|
3789
|
-
while (!stream.eol() && stream.pos <=
|
|
4108
|
+
while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
|
|
3790
4109
|
mode.token(stream, state);
|
|
3791
4110
|
stream.start = stream.pos;
|
|
3792
4111
|
}
|
|
@@ -3803,7 +4122,7 @@ window.CodeMirror = (function() {
|
|
|
3803
4122
|
var merged, line = realLine, lineBefore, sawBefore, simple = true;
|
|
3804
4123
|
while (merged = collapsedSpanAtStart(line)) {
|
|
3805
4124
|
simple = false;
|
|
3806
|
-
line = getLine(cm.
|
|
4125
|
+
line = getLine(cm.doc, merged.find().from.line);
|
|
3807
4126
|
if (!lineBefore) lineBefore = line;
|
|
3808
4127
|
}
|
|
3809
4128
|
|
|
@@ -3815,6 +4134,8 @@ window.CodeMirror = (function() {
|
|
|
3815
4134
|
builder.measure = line == realLine && measure;
|
|
3816
4135
|
builder.pos = 0;
|
|
3817
4136
|
builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
|
|
4137
|
+
if ((ie || webkit) && cm.getOption("lineWrapping"))
|
|
4138
|
+
builder.addToken = buildTokenSplitSpaces(builder.addToken);
|
|
3818
4139
|
if (measure && sawBefore && line != realLine && !builder.addedOne) {
|
|
3819
4140
|
measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
|
|
3820
4141
|
builder.addedOne = true;
|
|
@@ -3822,20 +4143,36 @@ window.CodeMirror = (function() {
|
|
|
3822
4143
|
var next = insertLineContent(line, builder, getLineStyles(cm, line));
|
|
3823
4144
|
sawBefore = line == lineBefore;
|
|
3824
4145
|
if (next) {
|
|
3825
|
-
line = getLine(cm.
|
|
4146
|
+
line = getLine(cm.doc, next.to.line);
|
|
3826
4147
|
simple = false;
|
|
3827
4148
|
}
|
|
3828
4149
|
} while (next);
|
|
3829
4150
|
|
|
3830
4151
|
if (measure && !builder.addedOne)
|
|
3831
4152
|
measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
|
|
3832
|
-
if (!builder.pre.firstChild && !lineIsHidden(realLine))
|
|
4153
|
+
if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
|
|
3833
4154
|
builder.pre.appendChild(document.createTextNode("\u00a0"));
|
|
3834
4155
|
|
|
4156
|
+
var order;
|
|
4157
|
+
// Work around problem with the reported dimensions of single-char
|
|
4158
|
+
// direction spans on IE (issue #1129). See also the comment in
|
|
4159
|
+
// cursorCoords.
|
|
4160
|
+
if (measure && ie && (order = getOrder(line))) {
|
|
4161
|
+
var l = order.length - 1;
|
|
4162
|
+
if (order[l].from == order[l].to) --l;
|
|
4163
|
+
var last = order[l], prev = order[l - 1];
|
|
4164
|
+
if (last.from + 1 == last.to && prev && last.level < prev.level) {
|
|
4165
|
+
var span = measure[builder.pos - 1];
|
|
4166
|
+
if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
|
|
4167
|
+
span.nextSibling);
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
|
|
4171
|
+
signal(cm, "renderLine", cm, realLine, builder.pre);
|
|
3835
4172
|
return builder.pre;
|
|
3836
4173
|
}
|
|
3837
4174
|
|
|
3838
|
-
var tokenSpecialChars = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;
|
|
4175
|
+
var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
|
|
3839
4176
|
function buildToken(builder, text, style, startStyle, endStyle) {
|
|
3840
4177
|
if (!text) return;
|
|
3841
4178
|
if (!tokenSpecialChars.test(text)) {
|
|
@@ -3875,18 +4212,42 @@ window.CodeMirror = (function() {
|
|
|
3875
4212
|
}
|
|
3876
4213
|
|
|
3877
4214
|
function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
|
|
4215
|
+
var wrapping = builder.cm.options.lineWrapping;
|
|
3878
4216
|
for (var i = 0; i < text.length; ++i) {
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
4217
|
+
var ch = text.charAt(i), start = i == 0;
|
|
4218
|
+
if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
|
|
4219
|
+
ch = text.slice(i, i + 2);
|
|
4220
|
+
++i;
|
|
4221
|
+
} else if (i && wrapping &&
|
|
4222
|
+
spanAffectsWrapping.test(text.slice(i - 1, i + 1))) {
|
|
3882
4223
|
builder.pre.appendChild(elt("wbr"));
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
4224
|
+
}
|
|
4225
|
+
var span = builder.measure[builder.pos] =
|
|
4226
|
+
buildToken(builder, ch, style,
|
|
4227
|
+
start && startStyle, i == text.length - 1 && endStyle);
|
|
4228
|
+
// In IE single-space nodes wrap differently than spaces
|
|
4229
|
+
// embedded in larger text nodes, except when set to
|
|
4230
|
+
// white-space: normal (issue #1268).
|
|
4231
|
+
if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
|
|
4232
|
+
i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
|
|
4233
|
+
span.style.whiteSpace = "normal";
|
|
4234
|
+
builder.pos += ch.length;
|
|
3886
4235
|
}
|
|
3887
4236
|
if (text.length) builder.addedOne = true;
|
|
3888
4237
|
}
|
|
3889
4238
|
|
|
4239
|
+
function buildTokenSplitSpaces(inner) {
|
|
4240
|
+
function split(old) {
|
|
4241
|
+
var out = " ";
|
|
4242
|
+
for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
|
|
4243
|
+
out += " ";
|
|
4244
|
+
return out;
|
|
4245
|
+
}
|
|
4246
|
+
return function(builder, text, style, startStyle, endStyle) {
|
|
4247
|
+
return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle);
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
|
|
3890
4251
|
function buildCollapsedSpan(builder, size, widget) {
|
|
3891
4252
|
if (widget) {
|
|
3892
4253
|
if (!builder.display) widget = widget.cloneNode(true);
|
|
@@ -3947,7 +4308,7 @@ window.CodeMirror = (function() {
|
|
|
3947
4308
|
var end = pos + text.length;
|
|
3948
4309
|
if (!collapsed) {
|
|
3949
4310
|
var tokenText = end > upto ? text.slice(0, upto - pos) : text;
|
|
3950
|
-
builder.addToken(builder, tokenText, style + spanStyle,
|
|
4311
|
+
builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
|
|
3951
4312
|
spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "");
|
|
3952
4313
|
}
|
|
3953
4314
|
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
|
|
@@ -3961,6 +4322,52 @@ window.CodeMirror = (function() {
|
|
|
3961
4322
|
|
|
3962
4323
|
// DOCUMENT DATA STRUCTURE
|
|
3963
4324
|
|
|
4325
|
+
function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
|
|
4326
|
+
function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
|
|
4327
|
+
function update(line, text, spans) {
|
|
4328
|
+
updateLine(line, text, spans, estimateHeight);
|
|
4329
|
+
signalLater(line, "change", line, change);
|
|
4330
|
+
}
|
|
4331
|
+
|
|
4332
|
+
var from = change.from, to = change.to, text = change.text;
|
|
4333
|
+
var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
|
|
4334
|
+
var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
|
|
4335
|
+
|
|
4336
|
+
// First adjust the line structure
|
|
4337
|
+
if (from.ch == 0 && to.ch == 0 && lastText == "") {
|
|
4338
|
+
// This is a whole-line replace. Treated specially to make
|
|
4339
|
+
// sure line objects move the way they are supposed to.
|
|
4340
|
+
for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
|
|
4341
|
+
added.push(makeLine(text[i], spansFor(i), estimateHeight));
|
|
4342
|
+
update(lastLine, lastLine.text, lastSpans);
|
|
4343
|
+
if (nlines) doc.remove(from.line, nlines);
|
|
4344
|
+
if (added.length) doc.insert(from.line, added);
|
|
4345
|
+
} else if (firstLine == lastLine) {
|
|
4346
|
+
if (text.length == 1) {
|
|
4347
|
+
update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
|
|
4348
|
+
} else {
|
|
4349
|
+
for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
|
|
4350
|
+
added.push(makeLine(text[i], spansFor(i), estimateHeight));
|
|
4351
|
+
added.push(makeLine(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
|
|
4352
|
+
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
|
|
4353
|
+
doc.insert(from.line + 1, added);
|
|
4354
|
+
}
|
|
4355
|
+
} else if (text.length == 1) {
|
|
4356
|
+
update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
|
|
4357
|
+
doc.remove(from.line + 1, nlines);
|
|
4358
|
+
} else {
|
|
4359
|
+
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
|
|
4360
|
+
update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
|
|
4361
|
+
for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
|
|
4362
|
+
added.push(makeLine(text[i], spansFor(i), estimateHeight));
|
|
4363
|
+
if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
|
|
4364
|
+
doc.insert(from.line + 1, added);
|
|
4365
|
+
}
|
|
4366
|
+
|
|
4367
|
+
signalLater(doc, "change", doc, change);
|
|
4368
|
+
setSelection(doc, selAfter.anchor, selAfter.head, null, true);
|
|
4369
|
+
}
|
|
4370
|
+
|
|
3964
4371
|
function LeafChunk(lines) {
|
|
3965
4372
|
this.lines = lines;
|
|
3966
4373
|
this.parent = null;
|
|
@@ -3973,19 +4380,19 @@ window.CodeMirror = (function() {
|
|
|
3973
4380
|
|
|
3974
4381
|
LeafChunk.prototype = {
|
|
3975
4382
|
chunkSize: function() { return this.lines.length; },
|
|
3976
|
-
|
|
4383
|
+
removeInner: function(at, n) {
|
|
3977
4384
|
for (var i = at, e = at + n; i < e; ++i) {
|
|
3978
4385
|
var line = this.lines[i];
|
|
3979
4386
|
this.height -= line.height;
|
|
3980
4387
|
cleanUpLine(line);
|
|
3981
|
-
signalLater(
|
|
4388
|
+
signalLater(line, "delete");
|
|
3982
4389
|
}
|
|
3983
4390
|
this.lines.splice(at, n);
|
|
3984
4391
|
},
|
|
3985
4392
|
collapse: function(lines) {
|
|
3986
4393
|
lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
|
|
3987
4394
|
},
|
|
3988
|
-
|
|
4395
|
+
insertInner: function(at, lines, height) {
|
|
3989
4396
|
this.height += height;
|
|
3990
4397
|
this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
|
|
3991
4398
|
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
|
|
@@ -4011,13 +4418,13 @@ window.CodeMirror = (function() {
|
|
|
4011
4418
|
|
|
4012
4419
|
BranchChunk.prototype = {
|
|
4013
4420
|
chunkSize: function() { return this.size; },
|
|
4014
|
-
|
|
4421
|
+
removeInner: function(at, n) {
|
|
4015
4422
|
this.size -= n;
|
|
4016
4423
|
for (var i = 0; i < this.children.length; ++i) {
|
|
4017
4424
|
var child = this.children[i], sz = child.chunkSize();
|
|
4018
4425
|
if (at < sz) {
|
|
4019
4426
|
var rm = Math.min(n, sz - at), oldHeight = child.height;
|
|
4020
|
-
child.
|
|
4427
|
+
child.removeInner(at, rm);
|
|
4021
4428
|
this.height -= oldHeight - child.height;
|
|
4022
4429
|
if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
|
|
4023
4430
|
if ((n -= rm) == 0) break;
|
|
@@ -4034,18 +4441,13 @@ window.CodeMirror = (function() {
|
|
|
4034
4441
|
collapse: function(lines) {
|
|
4035
4442
|
for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
|
|
4036
4443
|
},
|
|
4037
|
-
|
|
4038
|
-
var height = 0;
|
|
4039
|
-
for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
|
|
4040
|
-
this.insertHeight(at, lines, height);
|
|
4041
|
-
},
|
|
4042
|
-
insertHeight: function(at, lines, height) {
|
|
4444
|
+
insertInner: function(at, lines, height) {
|
|
4043
4445
|
this.size += lines.length;
|
|
4044
4446
|
this.height += height;
|
|
4045
4447
|
for (var i = 0, e = this.children.length; i < e; ++i) {
|
|
4046
4448
|
var child = this.children[i], sz = child.chunkSize();
|
|
4047
4449
|
if (at <= sz) {
|
|
4048
|
-
child.
|
|
4450
|
+
child.insertInner(at, lines, height);
|
|
4049
4451
|
if (child.lines && child.lines.length > 50) {
|
|
4050
4452
|
while (child.lines.length > 50) {
|
|
4051
4453
|
var spilled = child.lines.splice(child.lines.length - 25, 25);
|
|
@@ -4082,7 +4484,6 @@ window.CodeMirror = (function() {
|
|
|
4082
4484
|
} while (me.children.length > 10);
|
|
4083
4485
|
me.parent.maybeSpill();
|
|
4084
4486
|
},
|
|
4085
|
-
iter: function(from, to, op) { this.iterN(from, to - from, op); },
|
|
4086
4487
|
iterN: function(at, n, op) {
|
|
4087
4488
|
for (var i = 0, e = this.children.length; i < e; ++i) {
|
|
4088
4489
|
var child = this.children[i], sz = child.chunkSize();
|
|
@@ -4096,9 +4497,268 @@ window.CodeMirror = (function() {
|
|
|
4096
4497
|
}
|
|
4097
4498
|
};
|
|
4098
4499
|
|
|
4500
|
+
var nextDocId = 0;
|
|
4501
|
+
var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
|
|
4502
|
+
if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
|
|
4503
|
+
if (firstLine == null) firstLine = 0;
|
|
4504
|
+
|
|
4505
|
+
BranchChunk.call(this, [new LeafChunk([makeLine("", null)])]);
|
|
4506
|
+
this.first = firstLine;
|
|
4507
|
+
this.scrollTop = this.scrollLeft = 0;
|
|
4508
|
+
this.cantEdit = false;
|
|
4509
|
+
this.history = makeHistory();
|
|
4510
|
+
this.frontier = firstLine;
|
|
4511
|
+
var start = Pos(firstLine, 0);
|
|
4512
|
+
this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
|
|
4513
|
+
this.id = ++nextDocId;
|
|
4514
|
+
this.modeOption = mode;
|
|
4515
|
+
|
|
4516
|
+
if (typeof text == "string") text = splitLines(text);
|
|
4517
|
+
updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
|
|
4518
|
+
};
|
|
4519
|
+
|
|
4520
|
+
Doc.prototype = createObj(BranchChunk.prototype, {
|
|
4521
|
+
iter: function(from, to, op) {
|
|
4522
|
+
if (op) this.iterN(from - this.first, to - from, op);
|
|
4523
|
+
else this.iterN(this.first, this.first + this.size, from);
|
|
4524
|
+
},
|
|
4525
|
+
|
|
4526
|
+
insert: function(at, lines) {
|
|
4527
|
+
var height = 0;
|
|
4528
|
+
for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
|
|
4529
|
+
this.insertInner(at - this.first, lines, height);
|
|
4530
|
+
},
|
|
4531
|
+
remove: function(at, n) { this.removeInner(at - this.first, n); },
|
|
4532
|
+
|
|
4533
|
+
getValue: function(lineSep) {
|
|
4534
|
+
var lines = getLines(this, this.first, this.first + this.size);
|
|
4535
|
+
if (lineSep === false) return lines;
|
|
4536
|
+
return lines.join(lineSep || "\n");
|
|
4537
|
+
},
|
|
4538
|
+
setValue: function(code) {
|
|
4539
|
+
var top = Pos(this.first, 0), last = this.first + this.size - 1;
|
|
4540
|
+
makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
|
|
4541
|
+
text: splitLines(code), origin: "setValue"},
|
|
4542
|
+
{head: top, anchor: top}, true);
|
|
4543
|
+
},
|
|
4544
|
+
replaceRange: function(code, from, to, origin) {
|
|
4545
|
+
from = clipPos(this, from);
|
|
4546
|
+
to = to ? clipPos(this, to) : from;
|
|
4547
|
+
replaceRange(this, code, from, to, origin);
|
|
4548
|
+
},
|
|
4549
|
+
getRange: function(from, to, lineSep) {
|
|
4550
|
+
var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
|
|
4551
|
+
if (lineSep === false) return lines;
|
|
4552
|
+
return lines.join(lineSep || "\n");
|
|
4553
|
+
},
|
|
4554
|
+
|
|
4555
|
+
getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
|
|
4556
|
+
setLine: function(line, text) {
|
|
4557
|
+
if (isLine(this, line))
|
|
4558
|
+
replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
|
|
4559
|
+
},
|
|
4560
|
+
removeLine: function(line) {
|
|
4561
|
+
if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));
|
|
4562
|
+
else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));
|
|
4563
|
+
},
|
|
4564
|
+
|
|
4565
|
+
getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
|
|
4566
|
+
getLineNumber: function(line) {return lineNo(line);},
|
|
4567
|
+
|
|
4568
|
+
lineCount: function() {return this.size;},
|
|
4569
|
+
firstLine: function() {return this.first;},
|
|
4570
|
+
lastLine: function() {return this.first + this.size - 1;},
|
|
4571
|
+
|
|
4572
|
+
clipPos: function(pos) {return clipPos(this, pos);},
|
|
4573
|
+
|
|
4574
|
+
getCursor: function(start) {
|
|
4575
|
+
var sel = this.sel, pos;
|
|
4576
|
+
if (start == null || start == "head") pos = sel.head;
|
|
4577
|
+
else if (start == "anchor") pos = sel.anchor;
|
|
4578
|
+
else if (start == "end" || start === false) pos = sel.to;
|
|
4579
|
+
else pos = sel.from;
|
|
4580
|
+
return copyPos(pos);
|
|
4581
|
+
},
|
|
4582
|
+
somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
|
|
4583
|
+
|
|
4584
|
+
setCursor: docOperation(function(line, ch, extend) {
|
|
4585
|
+
var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
|
|
4586
|
+
if (extend) extendSelection(this, pos);
|
|
4587
|
+
else setSelection(this, pos, pos);
|
|
4588
|
+
}),
|
|
4589
|
+
setSelection: docOperation(function(anchor, head) {
|
|
4590
|
+
setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
|
|
4591
|
+
}),
|
|
4592
|
+
extendSelection: docOperation(function(from, to) {
|
|
4593
|
+
extendSelection(this, clipPos(this, from), to && clipPos(this, to));
|
|
4594
|
+
}),
|
|
4595
|
+
|
|
4596
|
+
getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
|
|
4597
|
+
replaceSelection: function(code, collapse, origin) {
|
|
4598
|
+
makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
|
|
4599
|
+
},
|
|
4600
|
+
undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
|
|
4601
|
+
redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
|
|
4602
|
+
|
|
4603
|
+
setExtending: function(val) {this.sel.extend = val;},
|
|
4604
|
+
|
|
4605
|
+
historySize: function() {
|
|
4606
|
+
var hist = this.history;
|
|
4607
|
+
return {undo: hist.done.length, redo: hist.undone.length};
|
|
4608
|
+
},
|
|
4609
|
+
clearHistory: function() {this.history = makeHistory();},
|
|
4610
|
+
|
|
4611
|
+
markClean: function() {
|
|
4612
|
+
this.history.dirtyCounter = 0;
|
|
4613
|
+
this.history.lastOp = this.history.lastOrigin = null;
|
|
4614
|
+
},
|
|
4615
|
+
isClean: function () {return this.history.dirtyCounter == 0;},
|
|
4616
|
+
|
|
4617
|
+
getHistory: function() {
|
|
4618
|
+
return {done: copyHistoryArray(this.history.done),
|
|
4619
|
+
undone: copyHistoryArray(this.history.undone)};
|
|
4620
|
+
},
|
|
4621
|
+
setHistory: function(histData) {
|
|
4622
|
+
var hist = this.history = makeHistory();
|
|
4623
|
+
hist.done = histData.done.slice(0);
|
|
4624
|
+
hist.undone = histData.undone.slice(0);
|
|
4625
|
+
},
|
|
4626
|
+
|
|
4627
|
+
markText: function(from, to, options) {
|
|
4628
|
+
return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
|
|
4629
|
+
},
|
|
4630
|
+
setBookmark: function(pos, options) {
|
|
4631
|
+
var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
|
|
4632
|
+
insertLeft: options && options.insertLeft};
|
|
4633
|
+
pos = clipPos(this, pos);
|
|
4634
|
+
return markText(this, pos, pos, realOpts, "bookmark");
|
|
4635
|
+
},
|
|
4636
|
+
findMarksAt: function(pos) {
|
|
4637
|
+
pos = clipPos(this, pos);
|
|
4638
|
+
var markers = [], spans = getLine(this, pos.line).markedSpans;
|
|
4639
|
+
if (spans) for (var i = 0; i < spans.length; ++i) {
|
|
4640
|
+
var span = spans[i];
|
|
4641
|
+
if ((span.from == null || span.from <= pos.ch) &&
|
|
4642
|
+
(span.to == null || span.to >= pos.ch))
|
|
4643
|
+
markers.push(span.marker.parent || span.marker);
|
|
4644
|
+
}
|
|
4645
|
+
return markers;
|
|
4646
|
+
},
|
|
4647
|
+
getAllMarks: function() {
|
|
4648
|
+
var markers = [];
|
|
4649
|
+
this.iter(function(line) {
|
|
4650
|
+
var sps = line.markedSpans;
|
|
4651
|
+
if (sps) for (var i = 0; i < sps.length; ++i)
|
|
4652
|
+
if (sps[i].from != null) markers.push(sps[i].marker);
|
|
4653
|
+
});
|
|
4654
|
+
return markers;
|
|
4655
|
+
},
|
|
4656
|
+
|
|
4657
|
+
posFromIndex: function(off) {
|
|
4658
|
+
var ch, lineNo = this.first;
|
|
4659
|
+
this.iter(function(line) {
|
|
4660
|
+
var sz = line.text.length + 1;
|
|
4661
|
+
if (sz > off) { ch = off; return true; }
|
|
4662
|
+
off -= sz;
|
|
4663
|
+
++lineNo;
|
|
4664
|
+
});
|
|
4665
|
+
return clipPos(this, Pos(lineNo, ch));
|
|
4666
|
+
},
|
|
4667
|
+
indexFromPos: function (coords) {
|
|
4668
|
+
coords = clipPos(this, coords);
|
|
4669
|
+
var index = coords.ch;
|
|
4670
|
+
if (coords.line < this.first || coords.ch < 0) return 0;
|
|
4671
|
+
this.iter(this.first, coords.line, function (line) {
|
|
4672
|
+
index += line.text.length + 1;
|
|
4673
|
+
});
|
|
4674
|
+
return index;
|
|
4675
|
+
},
|
|
4676
|
+
|
|
4677
|
+
copy: function(copyHistory) {
|
|
4678
|
+
var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
|
|
4679
|
+
doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
|
|
4680
|
+
doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
|
|
4681
|
+
shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
|
|
4682
|
+
if (copyHistory) {
|
|
4683
|
+
doc.history.undoDepth = this.history.undoDepth;
|
|
4684
|
+
doc.setHistory(this.getHistory());
|
|
4685
|
+
}
|
|
4686
|
+
return doc;
|
|
4687
|
+
},
|
|
4688
|
+
|
|
4689
|
+
linkedDoc: function(options) {
|
|
4690
|
+
if (!options) options = {};
|
|
4691
|
+
var from = this.first, to = this.first + this.size;
|
|
4692
|
+
if (options.from != null && options.from > from) from = options.from;
|
|
4693
|
+
if (options.to != null && options.to < to) to = options.to;
|
|
4694
|
+
var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
|
|
4695
|
+
if (options.sharedHist) copy.history = this.history;
|
|
4696
|
+
(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
|
|
4697
|
+
copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
|
|
4698
|
+
return copy;
|
|
4699
|
+
},
|
|
4700
|
+
unlinkDoc: function(other) {
|
|
4701
|
+
if (other instanceof CodeMirror) other = other.doc;
|
|
4702
|
+
if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
|
|
4703
|
+
var link = this.linked[i];
|
|
4704
|
+
if (link.doc != other) continue;
|
|
4705
|
+
this.linked.splice(i, 1);
|
|
4706
|
+
other.unlinkDoc(this);
|
|
4707
|
+
break;
|
|
4708
|
+
}
|
|
4709
|
+
// If the histories were shared, split them again
|
|
4710
|
+
if (other.history == this.history) {
|
|
4711
|
+
var splitIds = [other.id];
|
|
4712
|
+
linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
|
|
4713
|
+
other.history = makeHistory();
|
|
4714
|
+
other.history.done = copyHistoryArray(this.history.done, splitIds);
|
|
4715
|
+
other.history.undone = copyHistoryArray(this.history.undone, splitIds);
|
|
4716
|
+
}
|
|
4717
|
+
},
|
|
4718
|
+
iterLinkedDocs: function(f) {linkedDocs(this, f);},
|
|
4719
|
+
|
|
4720
|
+
getMode: function() {return this.mode;},
|
|
4721
|
+
getEditor: function() {return this.cm;}
|
|
4722
|
+
});
|
|
4723
|
+
|
|
4724
|
+
Doc.prototype.eachLine = Doc.prototype.iter;
|
|
4725
|
+
|
|
4726
|
+
// The Doc methods that should be available on CodeMirror instances
|
|
4727
|
+
var dontDelegate = "iter insert remove copy getEditor".split(" ");
|
|
4728
|
+
for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
|
|
4729
|
+
CodeMirror.prototype[prop] = (function(method) {
|
|
4730
|
+
return function() {return method.apply(this.doc, arguments);};
|
|
4731
|
+
})(Doc.prototype[prop]);
|
|
4732
|
+
|
|
4733
|
+
function linkedDocs(doc, f, sharedHistOnly) {
|
|
4734
|
+
function propagate(doc, skip, sharedHist) {
|
|
4735
|
+
if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
|
|
4736
|
+
var rel = doc.linked[i];
|
|
4737
|
+
if (rel.doc == skip) continue;
|
|
4738
|
+
var shared = sharedHist && rel.sharedHist;
|
|
4739
|
+
if (sharedHistOnly && !shared) continue;
|
|
4740
|
+
f(rel.doc, shared);
|
|
4741
|
+
propagate(rel.doc, doc, shared);
|
|
4742
|
+
}
|
|
4743
|
+
}
|
|
4744
|
+
propagate(doc, null, true);
|
|
4745
|
+
}
|
|
4746
|
+
|
|
4747
|
+
function attachDoc(cm, doc) {
|
|
4748
|
+
if (doc.cm) throw new Error("This document is already in use.");
|
|
4749
|
+
cm.doc = doc;
|
|
4750
|
+
doc.cm = cm;
|
|
4751
|
+
estimateLineHeights(cm);
|
|
4752
|
+
loadMode(cm);
|
|
4753
|
+
if (!cm.options.lineWrapping) computeMaxLength(cm);
|
|
4754
|
+
cm.options.mode = doc.modeOption;
|
|
4755
|
+
regChange(cm);
|
|
4756
|
+
}
|
|
4757
|
+
|
|
4099
4758
|
// LINE UTILITIES
|
|
4100
4759
|
|
|
4101
4760
|
function getLine(chunk, n) {
|
|
4761
|
+
n -= chunk.first;
|
|
4102
4762
|
while (!chunk.lines) {
|
|
4103
4763
|
for (var i = 0;; ++i) {
|
|
4104
4764
|
var child = chunk.children[i], sz = child.chunkSize();
|
|
@@ -4109,6 +4769,23 @@ window.CodeMirror = (function() {
|
|
|
4109
4769
|
return chunk.lines[n];
|
|
4110
4770
|
}
|
|
4111
4771
|
|
|
4772
|
+
function getBetween(doc, start, end) {
|
|
4773
|
+
var out = [], n = start.line;
|
|
4774
|
+
doc.iter(start.line, end.line + 1, function(line) {
|
|
4775
|
+
var text = line.text;
|
|
4776
|
+
if (n == end.line) text = text.slice(0, end.ch);
|
|
4777
|
+
if (n == start.line) text = text.slice(start.ch);
|
|
4778
|
+
out.push(text);
|
|
4779
|
+
++n;
|
|
4780
|
+
});
|
|
4781
|
+
return out;
|
|
4782
|
+
}
|
|
4783
|
+
function getLines(doc, from, to) {
|
|
4784
|
+
var out = [];
|
|
4785
|
+
doc.iter(from, to, function(line) { out.push(line.text); });
|
|
4786
|
+
return out;
|
|
4787
|
+
}
|
|
4788
|
+
|
|
4112
4789
|
function updateLineHeight(line, height) {
|
|
4113
4790
|
var diff = height - line.height;
|
|
4114
4791
|
for (var n = line; n; n = n.parent) n.height += diff;
|
|
@@ -4123,16 +4800,11 @@ window.CodeMirror = (function() {
|
|
|
4123
4800
|
no += chunk.children[i].chunkSize();
|
|
4124
4801
|
}
|
|
4125
4802
|
}
|
|
4126
|
-
return no;
|
|
4127
|
-
}
|
|
4128
|
-
|
|
4129
|
-
function lineDoc(line) {
|
|
4130
|
-
for (var d = line.parent; d.parent; d = d.parent) {}
|
|
4131
|
-
return d;
|
|
4803
|
+
return no + cur.first;
|
|
4132
4804
|
}
|
|
4133
4805
|
|
|
4134
4806
|
function lineAtHeight(chunk, h) {
|
|
4135
|
-
var n =
|
|
4807
|
+
var n = chunk.first;
|
|
4136
4808
|
outer: do {
|
|
4137
4809
|
for (var i = 0, e = chunk.children.length; i < e; ++i) {
|
|
4138
4810
|
var child = chunk.children[i], ch = child.height;
|
|
@@ -4151,7 +4823,7 @@ window.CodeMirror = (function() {
|
|
|
4151
4823
|
}
|
|
4152
4824
|
|
|
4153
4825
|
function heightAtLine(cm, lineObj) {
|
|
4154
|
-
lineObj = visualLine(cm.
|
|
4826
|
+
lineObj = visualLine(cm.doc, lineObj);
|
|
4155
4827
|
|
|
4156
4828
|
var h = 0, chunk = lineObj.parent;
|
|
4157
4829
|
for (var i = 0; i < chunk.lines.length; ++i) {
|
|
@@ -4182,7 +4854,7 @@ window.CodeMirror = (function() {
|
|
|
4182
4854
|
// Arrays of history events. Doing something adds an event to
|
|
4183
4855
|
// done and clears undo. Undoing moves events from done to
|
|
4184
4856
|
// undone, redoing moves them in the other direction.
|
|
4185
|
-
done: [], undone: [],
|
|
4857
|
+
done: [], undone: [], undoDepth: Infinity,
|
|
4186
4858
|
// Used to track when changes can be merged into a single undo
|
|
4187
4859
|
// event
|
|
4188
4860
|
lastTime: 0, lastOp: null, lastOrigin: null,
|
|
@@ -4191,47 +4863,152 @@ window.CodeMirror = (function() {
|
|
|
4191
4863
|
};
|
|
4192
4864
|
}
|
|
4193
4865
|
|
|
4194
|
-
function
|
|
4195
|
-
var
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4866
|
+
function attachLocalSpans(doc, change, from, to) {
|
|
4867
|
+
var existing = change["spans_" + doc.id], n = 0;
|
|
4868
|
+
doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
|
|
4869
|
+
if (line.markedSpans)
|
|
4870
|
+
(existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
|
|
4871
|
+
++n;
|
|
4872
|
+
});
|
|
4873
|
+
}
|
|
4874
|
+
|
|
4875
|
+
function historyChangeFromChange(doc, change) {
|
|
4876
|
+
var histChange = {from: change.from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
|
|
4877
|
+
attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
|
|
4878
|
+
linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
|
|
4879
|
+
return histChange;
|
|
4880
|
+
}
|
|
4881
|
+
|
|
4882
|
+
function addToHistory(doc, change, selAfter, opId) {
|
|
4883
|
+
var hist = doc.history;
|
|
4884
|
+
hist.undone.length = 0;
|
|
4885
|
+
var time = +new Date, cur = lst(hist.done);
|
|
4886
|
+
|
|
4199
4887
|
if (cur &&
|
|
4200
|
-
(
|
|
4201
|
-
|
|
4202
|
-
|
|
4888
|
+
(hist.lastOp == opId ||
|
|
4889
|
+
hist.lastOrigin == change.origin && change.origin &&
|
|
4890
|
+
((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||
|
|
4891
|
+
change.origin.charAt(0) == "*"))) {
|
|
4203
4892
|
// Merge this change into the last event
|
|
4204
|
-
var last = lst(cur.
|
|
4205
|
-
if (
|
|
4206
|
-
//
|
|
4207
|
-
|
|
4893
|
+
var last = lst(cur.changes);
|
|
4894
|
+
if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
|
|
4895
|
+
// Optimized case for simple insertion -- don't want to add
|
|
4896
|
+
// new changesets for every character typed
|
|
4897
|
+
last.to = changeEnd(change);
|
|
4208
4898
|
} else {
|
|
4209
|
-
//
|
|
4210
|
-
|
|
4211
|
-
endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
|
|
4212
|
-
for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
|
|
4213
|
-
for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
|
|
4214
|
-
if (startBefore) last.start = start;
|
|
4215
|
-
last.added += added - (old.length - startBefore - endAfter);
|
|
4899
|
+
// Add new sub-event
|
|
4900
|
+
cur.changes.push(historyChangeFromChange(doc, change));
|
|
4216
4901
|
}
|
|
4217
|
-
cur.
|
|
4902
|
+
cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
|
|
4218
4903
|
} else {
|
|
4219
4904
|
// Can not be merged, start a new event.
|
|
4220
|
-
cur = {
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4905
|
+
cur = {changes: [historyChangeFromChange(doc, change)],
|
|
4906
|
+
anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
|
|
4907
|
+
anchorAfter: selAfter.anchor, headAfter: selAfter.head};
|
|
4908
|
+
hist.done.push(cur);
|
|
4909
|
+
while (hist.done.length > hist.undoDepth)
|
|
4910
|
+
hist.done.shift();
|
|
4911
|
+
if (hist.dirtyCounter < 0)
|
|
4912
|
+
// The user has made a change after undoing past the last clean state.
|
|
4913
|
+
// We can never get back to a clean state now until markClean() is called.
|
|
4914
|
+
hist.dirtyCounter = NaN;
|
|
4229
4915
|
else
|
|
4230
|
-
|
|
4916
|
+
hist.dirtyCounter++;
|
|
4231
4917
|
}
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4918
|
+
hist.lastTime = time;
|
|
4919
|
+
hist.lastOp = opId;
|
|
4920
|
+
hist.lastOrigin = change.origin;
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4923
|
+
function removeClearedSpans(spans) {
|
|
4924
|
+
if (!spans) return null;
|
|
4925
|
+
for (var i = 0, out; i < spans.length; ++i) {
|
|
4926
|
+
if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
|
|
4927
|
+
else if (out) out.push(spans[i]);
|
|
4928
|
+
}
|
|
4929
|
+
return !out ? spans : out.length ? out : null;
|
|
4930
|
+
}
|
|
4931
|
+
|
|
4932
|
+
function getOldSpans(doc, change) {
|
|
4933
|
+
var found = change["spans_" + doc.id];
|
|
4934
|
+
if (!found) return null;
|
|
4935
|
+
for (var i = 0, nw = []; i < change.text.length; ++i)
|
|
4936
|
+
nw.push(removeClearedSpans(found[i]));
|
|
4937
|
+
return nw;
|
|
4938
|
+
}
|
|
4939
|
+
|
|
4940
|
+
// Used both to provide a JSON-safe object in .getHistory, and, when
|
|
4941
|
+
// detaching a document, to split the history in two
|
|
4942
|
+
function copyHistoryArray(events, newGroup) {
|
|
4943
|
+
for (var i = 0, copy = []; i < events.length; ++i) {
|
|
4944
|
+
var event = events[i], changes = event.changes, newChanges = [];
|
|
4945
|
+
copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
|
|
4946
|
+
anchorAfter: event.anchorAfter, headAfter: event.headAfter});
|
|
4947
|
+
for (var j = 0; j < changes.length; ++j) {
|
|
4948
|
+
var change = changes[j], m;
|
|
4949
|
+
newChanges.push({from: change.from, to: change.to, text: change.text});
|
|
4950
|
+
if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
|
|
4951
|
+
if (indexOf(newGroup, Number(m[1])) > -1) {
|
|
4952
|
+
lst(newChanges)[prop] = change[prop];
|
|
4953
|
+
delete change[prop];
|
|
4954
|
+
}
|
|
4955
|
+
}
|
|
4956
|
+
}
|
|
4957
|
+
}
|
|
4958
|
+
return copy;
|
|
4959
|
+
}
|
|
4960
|
+
|
|
4961
|
+
// Rebasing/resetting history to deal with externally-sourced changes
|
|
4962
|
+
|
|
4963
|
+
function rebaseHistSel(pos, from, to, diff) {
|
|
4964
|
+
if (to < pos.line) {
|
|
4965
|
+
pos.line += diff;
|
|
4966
|
+
} else if (from < pos.line) {
|
|
4967
|
+
pos.line = from;
|
|
4968
|
+
pos.ch = 0;
|
|
4969
|
+
}
|
|
4970
|
+
}
|
|
4971
|
+
|
|
4972
|
+
// Tries to rebase an array of history events given a change in the
|
|
4973
|
+
// document. If the change touches the same lines as the event, the
|
|
4974
|
+
// event, and everything 'behind' it, is discarded. If the change is
|
|
4975
|
+
// before the event, the event's positions are updated. Uses a
|
|
4976
|
+
// copy-on-write scheme for the positions, to avoid having to
|
|
4977
|
+
// reallocate them all on every rebase, but also avoid problems with
|
|
4978
|
+
// shared position objects being unsafely updated.
|
|
4979
|
+
function rebaseHistArray(array, from, to, diff) {
|
|
4980
|
+
for (var i = 0; i < array.length; ++i) {
|
|
4981
|
+
var sub = array[i], ok = true;
|
|
4982
|
+
for (var j = 0; j < sub.changes.length; ++j) {
|
|
4983
|
+
var cur = sub.changes[j];
|
|
4984
|
+
if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
|
|
4985
|
+
if (to < cur.from.line) {
|
|
4986
|
+
cur.from.line += diff;
|
|
4987
|
+
cur.to.line += diff;
|
|
4988
|
+
} else if (from <= cur.to.line) {
|
|
4989
|
+
ok = false;
|
|
4990
|
+
break;
|
|
4991
|
+
}
|
|
4992
|
+
}
|
|
4993
|
+
if (!sub.copied) {
|
|
4994
|
+
sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
|
|
4995
|
+
sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
|
|
4996
|
+
sub.copied = true;
|
|
4997
|
+
}
|
|
4998
|
+
if (!ok) {
|
|
4999
|
+
array.splice(0, i + 1);
|
|
5000
|
+
i = 0;
|
|
5001
|
+
} else {
|
|
5002
|
+
rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
|
|
5003
|
+
rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
|
|
5004
|
+
}
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
|
|
5008
|
+
function rebaseHist(hist, change) {
|
|
5009
|
+
var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
|
|
5010
|
+
rebaseHistArray(hist.done, from, to, diff);
|
|
5011
|
+
rebaseHistArray(hist.undone, from, to, diff);
|
|
4235
5012
|
}
|
|
4236
5013
|
|
|
4237
5014
|
// EVENT OPERATORS
|
|
@@ -4268,13 +5045,6 @@ window.CodeMirror = (function() {
|
|
|
4268
5045
|
return b;
|
|
4269
5046
|
}
|
|
4270
5047
|
|
|
4271
|
-
// Allow 3rd-party code to override event properties by adding an override
|
|
4272
|
-
// object to an event object.
|
|
4273
|
-
function e_prop(e, prop) {
|
|
4274
|
-
var overridden = e.override && e.override.hasOwnProperty(prop);
|
|
4275
|
-
return overridden ? e.override[prop] : e[prop];
|
|
4276
|
-
}
|
|
4277
|
-
|
|
4278
5048
|
// EVENT HANDLING
|
|
4279
5049
|
|
|
4280
5050
|
function on(emitter, type, f) {
|
|
@@ -4309,14 +5079,26 @@ window.CodeMirror = (function() {
|
|
|
4309
5079
|
for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
|
|
4310
5080
|
}
|
|
4311
5081
|
|
|
4312
|
-
|
|
5082
|
+
var delayedCallbacks, delayedCallbackDepth = 0;
|
|
5083
|
+
function signalLater(emitter, type /*, values...*/) {
|
|
4313
5084
|
var arr = emitter._handlers && emitter._handlers[type];
|
|
4314
5085
|
if (!arr) return;
|
|
4315
|
-
var args = Array.prototype.slice.call(arguments,
|
|
5086
|
+
var args = Array.prototype.slice.call(arguments, 2);
|
|
5087
|
+
if (!delayedCallbacks) {
|
|
5088
|
+
++delayedCallbackDepth;
|
|
5089
|
+
delayedCallbacks = [];
|
|
5090
|
+
setTimeout(fireDelayed, 0);
|
|
5091
|
+
}
|
|
4316
5092
|
function bnd(f) {return function(){f.apply(null, args);};};
|
|
4317
5093
|
for (var i = 0; i < arr.length; ++i)
|
|
4318
|
-
|
|
4319
|
-
|
|
5094
|
+
delayedCallbacks.push(bnd(arr[i]));
|
|
5095
|
+
}
|
|
5096
|
+
|
|
5097
|
+
function fireDelayed() {
|
|
5098
|
+
--delayedCallbackDepth;
|
|
5099
|
+
var delayed = delayedCallbacks;
|
|
5100
|
+
delayedCallbacks = null;
|
|
5101
|
+
for (var i = 0; i < delayed.length; ++i) delayed[i]();
|
|
4320
5102
|
}
|
|
4321
5103
|
|
|
4322
5104
|
function hasHandler(emitter, type) {
|
|
@@ -4340,12 +5122,12 @@ window.CodeMirror = (function() {
|
|
|
4340
5122
|
|
|
4341
5123
|
// Counts the column offset in a string, taking tabs into account.
|
|
4342
5124
|
// Used mostly to find indentation.
|
|
4343
|
-
function countColumn(string, end, tabSize) {
|
|
5125
|
+
function countColumn(string, end, tabSize, startIndex, startValue) {
|
|
4344
5126
|
if (end == null) {
|
|
4345
5127
|
end = string.search(/[^\s\u00a0]/);
|
|
4346
5128
|
if (end == -1) end = string.length;
|
|
4347
5129
|
}
|
|
4348
|
-
for (var i = 0, n = 0; i < end; ++i) {
|
|
5130
|
+
for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
|
|
4349
5131
|
if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
|
|
4350
5132
|
else ++n;
|
|
4351
5133
|
}
|
|
@@ -4376,6 +5158,20 @@ window.CodeMirror = (function() {
|
|
|
4376
5158
|
return -1;
|
|
4377
5159
|
}
|
|
4378
5160
|
|
|
5161
|
+
function createObj(base, props) {
|
|
5162
|
+
function Obj() {}
|
|
5163
|
+
Obj.prototype = base;
|
|
5164
|
+
var inst = new Obj();
|
|
5165
|
+
if (props) copyObj(props, inst);
|
|
5166
|
+
return inst;
|
|
5167
|
+
}
|
|
5168
|
+
|
|
5169
|
+
function copyObj(obj, target) {
|
|
5170
|
+
if (!target) target = {};
|
|
5171
|
+
for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
|
|
5172
|
+
return target;
|
|
5173
|
+
}
|
|
5174
|
+
|
|
4379
5175
|
function emptyArray(size) {
|
|
4380
5176
|
for (var a = [], i = 0; i < size; ++i) a.push(undefined);
|
|
4381
5177
|
return a;
|
|
@@ -4393,12 +5189,11 @@ window.CodeMirror = (function() {
|
|
|
4393
5189
|
}
|
|
4394
5190
|
|
|
4395
5191
|
function isEmpty(obj) {
|
|
4396
|
-
var
|
|
4397
|
-
|
|
4398
|
-
return !c;
|
|
5192
|
+
for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
|
|
5193
|
+
return true;
|
|
4399
5194
|
}
|
|
4400
5195
|
|
|
4401
|
-
var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F]/;
|
|
5196
|
+
var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
|
|
4402
5197
|
|
|
4403
5198
|
// DOM UTILITIES
|
|
4404
5199
|
|
|
@@ -4412,9 +5207,8 @@ window.CodeMirror = (function() {
|
|
|
4412
5207
|
}
|
|
4413
5208
|
|
|
4414
5209
|
function removeChildren(e) {
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
else while (e.firstChild) e.removeChild(e.firstChild);
|
|
5210
|
+
for (var count = e.childNodes.length; count > 0; --count)
|
|
5211
|
+
e.removeChild(e.firstChild);
|
|
4418
5212
|
return e;
|
|
4419
5213
|
}
|
|
4420
5214
|
|
|
@@ -4429,6 +5223,11 @@ window.CodeMirror = (function() {
|
|
|
4429
5223
|
} else e.textContent = str;
|
|
4430
5224
|
}
|
|
4431
5225
|
|
|
5226
|
+
function getRect(node) {
|
|
5227
|
+
return node.getBoundingClientRect();
|
|
5228
|
+
}
|
|
5229
|
+
CodeMirror.replaceGetRect = function(f) { getRect = f; };
|
|
5230
|
+
|
|
4432
5231
|
// FEATURE DETECTION
|
|
4433
5232
|
|
|
4434
5233
|
// Detect drag-and-drop
|
|
@@ -4449,8 +5248,8 @@ window.CodeMirror = (function() {
|
|
|
4449
5248
|
// various browsers.
|
|
4450
5249
|
var spanAffectsWrapping = /^$/; // Won't match any two-character string
|
|
4451
5250
|
if (gecko) spanAffectsWrapping = /$'/;
|
|
4452
|
-
else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
|
|
4453
|
-
else if (
|
|
5251
|
+
else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
|
|
5252
|
+
else if (webkit) spanAffectsWrapping = /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.]|\?[\w~`@#$%\^&*(_=+{[|><]/;
|
|
4454
5253
|
|
|
4455
5254
|
var knownScrollbarWidth;
|
|
4456
5255
|
function scrollbarWidth(measure) {
|
|
@@ -4553,20 +5352,20 @@ window.CodeMirror = (function() {
|
|
|
4553
5352
|
}
|
|
4554
5353
|
|
|
4555
5354
|
function lineStart(cm, lineN) {
|
|
4556
|
-
var line = getLine(cm.
|
|
4557
|
-
var visual = visualLine(cm.
|
|
5355
|
+
var line = getLine(cm.doc, lineN);
|
|
5356
|
+
var visual = visualLine(cm.doc, line);
|
|
4558
5357
|
if (visual != line) lineN = lineNo(visual);
|
|
4559
5358
|
var order = getOrder(visual);
|
|
4560
5359
|
var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
|
|
4561
|
-
return
|
|
5360
|
+
return Pos(lineN, ch);
|
|
4562
5361
|
}
|
|
4563
|
-
function lineEnd(cm,
|
|
5362
|
+
function lineEnd(cm, lineN) {
|
|
4564
5363
|
var merged, line;
|
|
4565
|
-
while (merged = collapsedSpanAtEnd(line = getLine(cm.
|
|
4566
|
-
|
|
5364
|
+
while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
|
|
5365
|
+
lineN = merged.find().to.line;
|
|
4567
5366
|
var order = getOrder(line);
|
|
4568
5367
|
var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
|
|
4569
|
-
return
|
|
5368
|
+
return Pos(lineN, ch);
|
|
4570
5369
|
}
|
|
4571
5370
|
|
|
4572
5371
|
// This is somewhat involved. It is needed in order to move
|
|
@@ -4658,7 +5457,7 @@ window.CodeMirror = (function() {
|
|
|
4658
5457
|
// Browsers seem to always treat the boundaries of block elements as being L.
|
|
4659
5458
|
var outerType = "L";
|
|
4660
5459
|
|
|
4661
|
-
return function
|
|
5460
|
+
return function(str) {
|
|
4662
5461
|
if (!bidiRE.test(str)) return false;
|
|
4663
5462
|
var len = str.length, types = [];
|
|
4664
5463
|
for (var i = 0, type; i < len; ++i)
|
|
@@ -4780,7 +5579,7 @@ window.CodeMirror = (function() {
|
|
|
4780
5579
|
|
|
4781
5580
|
// THE END
|
|
4782
5581
|
|
|
4783
|
-
CodeMirror.version = "3.
|
|
5582
|
+
CodeMirror.version = "3.12";
|
|
4784
5583
|
|
|
4785
5584
|
return CodeMirror;
|
|
4786
5585
|
})();
|