Subversion Repositories wimsdev

Rev

Rev 15332 | Rev 16859 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 15332 Rev 16493
Line 30... Line 30...
30
  var presto = /Opera\//.test(userAgent);
30
  var presto = /Opera\//.test(userAgent);
31
  var safari = /Apple Computer/.test(navigator.vendor);
31
  var safari = /Apple Computer/.test(navigator.vendor);
32
  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
32
  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
33
  var phantom = /PhantomJS/.test(userAgent);
33
  var phantom = /PhantomJS/.test(userAgent);
34
 
34
 
35
  var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
35
  var ios = safari && (/Mobile\/\w+/.test(userAgent) || navigator.maxTouchPoints > 2);
36
  var android = /Android/.test(userAgent);
36
  var android = /Android/.test(userAgent);
37
  // This is woefully incomplete. Suggestions for alternative methods welcome.
37
  // This is woefully incomplete. Suggestions for alternative methods welcome.
38
  var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
38
  var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
39
  var mac = ios || /Mac/.test(platform);
39
  var mac = ios || /Mac/.test(platform);
40
  var chromeOS = /\bCrOS\b/.test(userAgent);
40
  var chromeOS = /\bCrOS\b/.test(userAgent);
Line 1309... Line 1309...
1309
    if (spans) { for (var i = 0; i < spans.length; ++i) {
1309
    if (spans) { for (var i = 0; i < spans.length; ++i) {
1310
      var span = spans[i];
1310
      var span = spans[i];
1311
      if (span.marker == marker) { return span }
1311
      if (span.marker == marker) { return span }
1312
    } }
1312
    } }
1313
  }
1313
  }
-
 
1314
 
1314
  // Remove a span from an array, returning undefined if no spans are
1315
  // Remove a span from an array, returning undefined if no spans are
1315
  // left (we don't store arrays for lines without spans).
1316
  // left (we don't store arrays for lines without spans).
1316
  function removeMarkedSpan(spans, span) {
1317
  function removeMarkedSpan(spans, span) {
1317
    var r;
1318
    var r;
1318
    for (var i = 0; i < spans.length; ++i)
1319
    for (var i = 0; i < spans.length; ++i)
1319
      { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }
1320
      { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }
1320
    return r
1321
    return r
1321
  }
1322
  }
-
 
1323
 
1322
  // Add a span to a line.
1324
  // Add a span to a line.
1323
  function addMarkedSpan(line, span) {
1325
  function addMarkedSpan(line, span, op) {
-
 
1326
    var inThisOp = op && window.WeakSet && (op.markedSpans || (op.markedSpans = new WeakSet));
-
 
1327
    if (inThisOp && inThisOp.has(line.markedSpans)) {
-
 
1328
      line.markedSpans.push(span);
-
 
1329
    } else {
1324
    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
1330
      line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
-
 
1331
      if (inThisOp) { inThisOp.add(line.markedSpans); }
-
 
1332
    }
1325
    span.marker.attachLine(line);
1333
    span.marker.attachLine(line);
1326
  }
1334
  }
1327
 
1335
 
1328
  // Used for the algorithm that adjusts markers for a change in the
1336
  // Used for the algorithm that adjusts markers for a change in the
1329
  // document. These functions cut an array of spans at a given
1337
  // document. These functions cut an array of spans at a given
Line 1839... Line 1847...
1839
        builder.map.push(builder.pos, builder.pos + 1, txt$1);
1847
        builder.map.push(builder.pos, builder.pos + 1, txt$1);
1840
        builder.pos++;
1848
        builder.pos++;
1841
      }
1849
      }
1842
    }
1850
    }
1843
    builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;
1851
    builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;
1844
    if (style || startStyle || endStyle || mustWrap || css) {
1852
    if (style || startStyle || endStyle || mustWrap || css || attributes) {
1845
      var fullStyle = style || "";
1853
      var fullStyle = style || "";
1846
      if (startStyle) { fullStyle += startStyle; }
1854
      if (startStyle) { fullStyle += startStyle; }
1847
      if (endStyle) { fullStyle += endStyle; }
1855
      if (endStyle) { fullStyle += endStyle; }
1848
      var token = elt("span", [content], fullStyle, css);
1856
      var token = elt("span", [content], fullStyle, css);
1849
      if (attributes) {
1857
      if (attributes) {
Line 2184... Line 2192...
2184
    }
2192
    }
2185
    var markers = lineView.line.gutterMarkers;
2193
    var markers = lineView.line.gutterMarkers;
2186
    if (cm.options.lineNumbers || markers) {
2194
    if (cm.options.lineNumbers || markers) {
2187
      var wrap$1 = ensureLineWrapped(lineView);
2195
      var wrap$1 = ensureLineWrapped(lineView);
2188
      var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"));
2196
      var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"));
-
 
2197
      gutterWrap.setAttribute("aria-hidden", "true");
2189
      cm.display.input.setUneditable(gutterWrap);
2198
      cm.display.input.setUneditable(gutterWrap);
2190
      wrap$1.insertBefore(gutterWrap, lineView.text);
2199
      wrap$1.insertBefore(gutterWrap, lineView.text);
2191
      if (lineView.line.gutterClass)
2200
      if (lineView.line.gutterClass)
2192
        { gutterWrap.className += " " + lineView.line.gutterClass; }
2201
        { gutterWrap.className += " " + lineView.line.gutterClass; }
2193
      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
2202
      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
Line 2340... Line 2349...
2340
  // measurement cache for the given line number. (A line view might
2349
  // measurement cache for the given line number. (A line view might
2341
  // contain multiple lines when collapsed ranges are present.)
2350
  // contain multiple lines when collapsed ranges are present.)
2342
  function mapFromLineView(lineView, line, lineN) {
2351
  function mapFromLineView(lineView, line, lineN) {
2343
    if (lineView.line == line)
2352
    if (lineView.line == line)
2344
      { return {map: lineView.measure.map, cache: lineView.measure.cache} }
2353
      { return {map: lineView.measure.map, cache: lineView.measure.cache} }
-
 
2354
    if (lineView.rest) {
2345
    for (var i = 0; i < lineView.rest.length; i++)
2355
      for (var i = 0; i < lineView.rest.length; i++)
2346
      { if (lineView.rest[i] == line)
2356
        { if (lineView.rest[i] == line)
2347
        { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
2357
          { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
2348
    for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
2358
      for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
2349
      { if (lineNo(lineView.rest[i$1]) > lineN)
2359
        { if (lineNo(lineView.rest[i$1]) > lineN)
2350
        { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
2360
          { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
-
 
2361
    }
2351
  }
2362
  }
2352
 
2363
 
2353
  // Render a line into the hidden node display.externalMeasured. Used
2364
  // Render a line into the hidden node display.externalMeasured. Used
2354
  // when measurement is needed for a line that's not in the viewport.
2365
  // when measurement is needed for a line that's not in the viewport.
2355
  function updateExternalMeasurement(cm, line) {
2366
  function updateExternalMeasurement(cm, line) {
Line 2572... Line 2583...
2572
    if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) }
2583
    if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) }
2573
    return window.pageYOffset || (document.documentElement || document.body).scrollTop
2584
    return window.pageYOffset || (document.documentElement || document.body).scrollTop
2574
  }
2585
  }
2575
 
2586
 
2576
  function widgetTopHeight(lineObj) {
2587
  function widgetTopHeight(lineObj) {
-
 
2588
    var ref = visualLine(lineObj);
-
 
2589
    var widgets = ref.widgets;
2577
    var height = 0;
2590
    var height = 0;
2578
    if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above)
2591
    if (widgets) { for (var i = 0; i < widgets.length; ++i) { if (widgets[i].above)
2579
      { height += widgetHeight(lineObj.widgets[i]); } } }
2592
      { height += widgetHeight(widgets[i]); } } }
2580
    return height
2593
    return height
2581
  }
2594
  }
2582
 
2595
 
2583
  // Converts a {top, bottom, left, right} box from line-local
2596
  // Converts a {top, bottom, left, right} box from line-local
2584
  // coordinates into another coordinate system. Context may be one of
2597
  // coordinates into another coordinate system. Context may be one of
Line 3056... Line 3069...
3056
  function regLineChange(cm, line, type) {
3069
  function regLineChange(cm, line, type) {
3057
    cm.curOp.viewChanged = true;
3070
    cm.curOp.viewChanged = true;
3058
    var display = cm.display, ext = cm.display.externalMeasured;
3071
    var display = cm.display, ext = cm.display.externalMeasured;
3059
    if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
3072
    if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
3060
      { display.externalMeasured = null; }
3073
      { display.externalMeasured = null; }
3061
 
3074
 
3062
    if (line < display.viewFrom || line >= display.viewTo) { return }
3075
    if (line < display.viewFrom || line >= display.viewTo) { return }
3063
    var lineView = display.view[findViewIndex(cm, line)];
3076
    var lineView = display.view[findViewIndex(cm, line)];
3064
    if (lineView.node == null) { return }
3077
    if (lineView.node == null) { return }
3065
    var arr = lineView.changes || (lineView.changes = []);
3078
    var arr = lineView.changes || (lineView.changes = []);
3066
    if (indexOf(arr, type) == -1) { arr.push(type); }
3079
    if (indexOf(arr, type) == -1) { arr.push(type); }
Line 3069... Line 3082...
3069
  // Clear the view.
3082
  // Clear the view.
3070
  function resetView(cm) {
3083
  function resetView(cm) {
3071
    cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
3084
    cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
3072
    cm.display.view = [];
3085
    cm.display.view = [];
3073
    cm.display.viewOffset = 0;
3086
    cm.display.viewOffset = 0;
3074
  }
3087
  }
3075
 
3088
 
3076
  function viewCuttingPoint(cm, oldN, newN, dir) {
3089
  function viewCuttingPoint(cm, oldN, newN, dir) {
3077
    var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
3090
    var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
3078
    if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
3091
    if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
3079
      { return {index: index, lineN: newN} }
3092
      { return {index: index, lineN: newN} }
Line 3094... Line 3107...
3094
      if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
3107
      if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
3095
      newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
3108
      newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
3096
      index += dir;
3109
      index += dir;
3097
    }
3110
    }
3098
    return {index: index, lineN: newN}
3111
    return {index: index, lineN: newN}
3099
  }
3112
  }
3100
 
3113
 
3101
  // Force the view to cover a given range, adding empty view element
3114
  // Force the view to cover a given range, adding empty view element
3102
  // or clipping off existing ones as needed.
3115
  // or clipping off existing ones as needed.
3103
  function adjustView(cm, from, to) {
3116
  function adjustView(cm, from, to) {
3104
    var display = cm.display, view = display.view;
3117
    var display = cm.display, view = display.view;
Line 3139... Line 3152...
3139
 
3152
 
3140
    var doc = cm.doc, result = {};
3153
    var doc = cm.doc, result = {};
3141
    var curFragment = result.cursors = document.createDocumentFragment();
3154
    var curFragment = result.cursors = document.createDocumentFragment();
3142
    var selFragment = result.selection = document.createDocumentFragment();
3155
    var selFragment = result.selection = document.createDocumentFragment();
3143
 
3156
 
-
 
3157
    var customCursor = cm.options.$customCursor;
-
 
3158
    if (customCursor) { primary = true; }
3144
    for (var i = 0; i < doc.sel.ranges.length; i++) {
3159
    for (var i = 0; i < doc.sel.ranges.length; i++) {
3145
      if (!primary && i == doc.sel.primIndex) { continue }
3160
      if (!primary && i == doc.sel.primIndex) { continue }
3146
      var range = doc.sel.ranges[i];
3161
      var range = doc.sel.ranges[i];
3147
      if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
3162
      if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
3148
      var collapsed = range.empty();
3163
      var collapsed = range.empty();
-
 
3164
      if (customCursor) {
-
 
3165
        var head = customCursor(cm, range);
-
 
3166
        if (head) { drawSelectionCursor(cm, head, curFragment); }
3149
      if (collapsed || cm.options.showCursorWhenSelecting)
3167
      } else if (collapsed || cm.options.showCursorWhenSelecting) {
3150
        { drawSelectionCursor(cm, range.head, curFragment); }
3168
        drawSelectionCursor(cm, range.head, curFragment);
-
 
3169
      }
3151
      if (!collapsed)
3170
      if (!collapsed)
3152
        { drawSelectionRange(cm, range, selFragment); }
3171
        { drawSelectionRange(cm, range, selFragment); }
3153
    }
3172
    }
3154
    return result
3173
    return result
3155
  }
3174
  }
Line 3160... Line 3179...
3160
 
3179
 
3161
    var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
3180
    var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
3162
    cursor.style.left = pos.left + "px";
3181
    cursor.style.left = pos.left + "px";
3163
    cursor.style.top = pos.top + "px";
3182
    cursor.style.top = pos.top + "px";
3164
    cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
3183
    cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
-
 
3184
 
-
 
3185
    if (/\bcm-fat-cursor\b/.test(cm.getWrapperElement().className)) {
-
 
3186
      var charPos = charCoords(cm, head, "div", null, null);
-
 
3187
      var width = charPos.right - charPos.left;
-
 
3188
      cursor.style.width = (width > 0 ? width : cm.defaultCharWidth()) + "px";
-
 
3189
    }
3165
 
3190
 
3166
    if (pos.other) {
3191
    if (pos.other) {
3167
      // Secondary cursor, shown when on a 'jump' in bi-directional text
3192
      // Secondary cursor, shown when on a 'jump' in bi-directional text
3168
      var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
3193
      var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
3169
      otherCursor.style.display = "";
3194
      otherCursor.style.display = "";
Line 3274... Line 3299...
3274
    var display = cm.display;
3299
    var display = cm.display;
3275
    clearInterval(display.blinker);
3300
    clearInterval(display.blinker);
3276
    var on = true;
3301
    var on = true;
3277
    display.cursorDiv.style.visibility = "";
3302
    display.cursorDiv.style.visibility = "";
3278
    if (cm.options.cursorBlinkRate > 0)
3303
    if (cm.options.cursorBlinkRate > 0)
-
 
3304
      { display.blinker = setInterval(function () {
-
 
3305
        if (!cm.hasFocus()) { onBlur(cm); }
3279
      { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; },
3306
        display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
3280
        cm.options.cursorBlinkRate); }
3307
      }, cm.options.cursorBlinkRate); }
3281
    else if (cm.options.cursorBlinkRate < 0)
3308
    else if (cm.options.cursorBlinkRate < 0)
3282
      { display.cursorDiv.style.visibility = "hidden"; }
3309
      { display.cursorDiv.style.visibility = "hidden"; }
3283
  }
3310
  }
3284
 
3311
 
3285
  function ensureFocus(cm) {
3312
  function ensureFocus(cm) {
-
 
3313
    if (!cm.hasFocus()) {
-
 
3314
      cm.display.input.focus();
3286
    if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
3315
      if (!cm.state.focused) { onFocus(cm); }
-
 
3316
    }
3287
  }
3317
  }
3288
 
3318
 
3289
  function delayBlurEvent(cm) {
3319
  function delayBlurEvent(cm) {
3290
    cm.state.delayingBlurEvent = true;
3320
    cm.state.delayingBlurEvent = true;
3291
    setTimeout(function () { if (cm.state.delayingBlurEvent) {
3321
    setTimeout(function () { if (cm.state.delayingBlurEvent) {
3292
      cm.state.delayingBlurEvent = false;
3322
      cm.state.delayingBlurEvent = false;
3293
      onBlur(cm);
3323
      if (cm.state.focused) { onBlur(cm); }
3294
    } }, 100);
3324
    } }, 100);
3295
  }
3325
  }
3296
 
3326
 
3297
  function onFocus(cm, e) {
3327
  function onFocus(cm, e) {
3298
    if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; }
3328
    if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; }
3299
 
3329
 
3300
    if (cm.options.readOnly == "nocursor") { return }
3330
    if (cm.options.readOnly == "nocursor") { return }
3301
    if (!cm.state.focused) {
3331
    if (!cm.state.focused) {
3302
      signal(cm, "focus", cm, e);
3332
      signal(cm, "focus", cm, e);
3303
      cm.state.focused = true;
3333
      cm.state.focused = true;
Line 3328... Line 3358...
3328
  // Read the actual heights of the rendered lines, and update their
3358
  // Read the actual heights of the rendered lines, and update their
3329
  // stored heights to match.
3359
  // stored heights to match.
3330
  function updateHeightsInViewport(cm) {
3360
  function updateHeightsInViewport(cm) {
3331
    var display = cm.display;
3361
    var display = cm.display;
3332
    var prevBottom = display.lineDiv.offsetTop;
3362
    var prevBottom = display.lineDiv.offsetTop;
-
 
3363
    var viewTop = Math.max(0, display.scroller.getBoundingClientRect().top);
-
 
3364
    var oldHeight = display.lineDiv.getBoundingClientRect().top;
-
 
3365
    var mustScroll = 0;
3333
    for (var i = 0; i < display.view.length; i++) {
3366
    for (var i = 0; i < display.view.length; i++) {
3334
      var cur = display.view[i], wrapping = cm.options.lineWrapping;
3367
      var cur = display.view[i], wrapping = cm.options.lineWrapping;
3335
      var height = (void 0), width = 0;
3368
      var height = (void 0), width = 0;
3336
      if (cur.hidden) { continue }
3369
      if (cur.hidden) { continue }
-
 
3370
      oldHeight += cur.line.height;
3337
      if (ie && ie_version < 8) {
3371
      if (ie && ie_version < 8) {
3338
        var bot = cur.node.offsetTop + cur.node.offsetHeight;
3372
        var bot = cur.node.offsetTop + cur.node.offsetHeight;
3339
        height = bot - prevBottom;
3373
        height = bot - prevBottom;
3340
        prevBottom = bot;
3374
        prevBottom = bot;
3341
      } else {
3375
      } else {
Line 3346... Line 3380...
3346
        if (!wrapping && cur.text.firstChild)
3380
        if (!wrapping && cur.text.firstChild)
3347
          { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; }
3381
          { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; }
3348
      }
3382
      }
3349
      var diff = cur.line.height - height;
3383
      var diff = cur.line.height - height;
3350
      if (diff > .005 || diff < -.005) {
3384
      if (diff > .005 || diff < -.005) {
-
 
3385
        if (oldHeight < viewTop) { mustScroll -= diff; }
3351
        updateLineHeight(cur.line, height);
3386
        updateLineHeight(cur.line, height);
3352
        updateWidgetHeight(cur.line);
3387
        updateWidgetHeight(cur.line);
3353
        if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
3388
        if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
3354
          { updateWidgetHeight(cur.rest[j]); } }
3389
          { updateWidgetHeight(cur.rest[j]); } }
3355
      }
3390
      }
Line 3360... Line 3395...
3360
          cm.display.maxLine = cur.line;
3395
          cm.display.maxLine = cur.line;
3361
          cm.display.maxLineChanged = true;
3396
          cm.display.maxLineChanged = true;
3362
        }
3397
        }
3363
      }
3398
      }
3364
    }
3399
    }
-
 
3400
    if (Math.abs(mustScroll) > 2) { display.scroller.scrollTop += mustScroll; }
3365
  }
3401
  }
3366
 
3402
 
3367
  // Read and store the height of line widgets associated with the
3403
  // Read and store the height of line widgets associated with the
3368
  // given line.
3404
  // given line.
3369
  function updateWidgetHeight(line) {
3405
  function updateWidgetHeight(line) {
Line 3423... Line 3459...
3423
    var rect;
3459
    var rect;
3424
    if (!cm.options.lineWrapping && pos == end) {
3460
    if (!cm.options.lineWrapping && pos == end) {
3425
      // Set pos and end to the cursor positions around the character pos sticks to
3461
      // Set pos and end to the cursor positions around the character pos sticks to
3426
      // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch
3462
      // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch
3427
      // If pos == Pos(_, 0, "before"), pos and end are unchanged
3463
      // If pos == Pos(_, 0, "before"), pos and end are unchanged
3428
      pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
-
 
3429
      end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos;
3464
      end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos;
-
 
3465
      pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
3430
    }
3466
    }
3431
    for (var limit = 0; limit < 5; limit++) {
3467
    for (var limit = 0; limit < 5; limit++) {
3432
      var changed = false;
3468
      var changed = false;
3433
      var coords = cursorCoords(cm, pos);
3469
      var coords = cursorCoords(cm, pos);
3434
      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
3470
      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
Line 3475... Line 3511...
3475
    } else if (rect.bottom > screentop + screen) {
3511
    } else if (rect.bottom > screentop + screen) {
3476
      var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
3512
      var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
3477
      if (newTop != screentop) { result.scrollTop = newTop; }
3513
      if (newTop != screentop) { result.scrollTop = newTop; }
3478
    }
3514
    }
3479
 
3515
 
-
 
3516
    var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth;
3480
    var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
3517
    var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace;
3481
    var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
3518
    var screenw = displayWidth(cm) - display.gutters.offsetWidth;
3482
    var tooWide = rect.right - rect.left > screenw;
3519
    var tooWide = rect.right - rect.left > screenw;
3483
    if (tooWide) { rect.right = rect.left + screenw; }
3520
    if (tooWide) { rect.right = rect.left + screenw; }
3484
    if (rect.left < 10)
3521
    if (rect.left < 10)
3485
      { result.scrollLeft = 0; }
3522
      { result.scrollLeft = 0; }
3486
    else if (rect.left < screenleft)
3523
    else if (rect.left < screenleft)
3487
      { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); }
3524
      { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); }
3488
    else if (rect.right > screenw + screenleft - 3)
3525
    else if (rect.right > screenw + screenleft - 3)
3489
      { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
3526
      { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
3490
    return result
3527
    return result
3491
  }
3528
  }
3492
 
3529
 
Line 3619... Line 3656...
3619
      var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
3656
      var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
3620
      // A bug in IE8 can cause this value to be negative, so guard it.
3657
      // A bug in IE8 can cause this value to be negative, so guard it.
3621
      this.vert.firstChild.style.height =
3658
      this.vert.firstChild.style.height =
3622
        Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
3659
        Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
3623
    } else {
3660
    } else {
-
 
3661
      this.vert.scrollTop = 0;
3624
      this.vert.style.display = "";
3662
      this.vert.style.display = "";
3625
      this.vert.firstChild.style.height = "0";
3663
      this.vert.firstChild.style.height = "0";
3626
    }
3664
    }
3627
 
3665
 
3628
    if (needsH) {
3666
    if (needsH) {
Line 3774... Line 3812...
3774
      selectionChanged: false, // Whether the selection needs to be redrawn
3812
      selectionChanged: false, // Whether the selection needs to be redrawn
3775
      updateMaxLine: false,    // Set when the widest line needs to be determined anew
3813
      updateMaxLine: false,    // Set when the widest line needs to be determined anew
3776
      scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
3814
      scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
3777
      scrollToPos: null,       // Used to scroll to a specific position
3815
      scrollToPos: null,       // Used to scroll to a specific position
3778
      focus: false,
3816
      focus: false,
3779
      id: ++nextOpId           // Unique ID
3817
      id: ++nextOpId,          // Unique ID
-
 
3818
      markArrays: null         // Used by addMarkedSpan
3780
    };
3819
    };
3781
    pushOperation(cm.curOp);
3820
    pushOperation(cm.curOp);
3782
  }
3821
  }
3783
 
3822
 
3784
  // Finish an operation, updating the display and signalling delayed events
3823
  // Finish an operation, updating the display and signalling delayed events
Line 4227... Line 4266...
4227
  }
4266
  }
4228
 
4267
 
4229
  function updateGutterSpace(display) {
4268
  function updateGutterSpace(display) {
4230
    var width = display.gutters.offsetWidth;
4269
    var width = display.gutters.offsetWidth;
4231
    display.sizer.style.marginLeft = width + "px";
4270
    display.sizer.style.marginLeft = width + "px";
-
 
4271
    // Send an event to consumers responding to changes in gutter width.
-
 
4272
    signalLater(display, "gutterChanged", display);
4232
  }
4273
  }
4233
 
4274
 
4234
  function setDocumentHeight(cm, measure) {
4275
  function setDocumentHeight(cm, measure) {
4235
    cm.display.sizer.style.minHeight = measure.docHeight + "px";
4276
    cm.display.sizer.style.minHeight = measure.docHeight + "px";
4236
    cm.display.heightForcer.style.top = measure.docHeight + "px";
4277
    cm.display.heightForcer.style.top = measure.docHeight + "px";
Line 4365... Line 4406...
4365
    // Actual scrollable element.
4406
    // Actual scrollable element.
4366
    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
4407
    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
4367
    d.scroller.setAttribute("tabIndex", "-1");
4408
    d.scroller.setAttribute("tabIndex", "-1");
4368
    // The element in which the editor lives.
4409
    // The element in which the editor lives.
4369
    d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
4410
    d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
-
 
4411
 
-
 
4412
    // This attribute is respected by automatic translation systems such as Google Translate,
-
 
4413
    // and may also be respected by tools used by human translators.
-
 
4414
    d.wrapper.setAttribute('translate', 'no');
4370
 
4415
 
4371
    // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
4416
    // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
4372
    if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
4417
    if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
4373
    if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; }
4418
    if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; }
4374
 
4419
 
Line 4463... Line 4508...
4463
    return delta
4508
    return delta
4464
  }
4509
  }
4465
 
4510
 
4466
  function onScrollWheel(cm, e) {
4511
  function onScrollWheel(cm, e) {
4467
    var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
4512
    var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
-
 
4513
    var pixelsPerUnit = wheelPixelsPerUnit;
-
 
4514
    if (e.deltaMode === 0) {
-
 
4515
      dx = e.deltaX;
-
 
4516
      dy = e.deltaY;
-
 
4517
      pixelsPerUnit = 1;
-
 
4518
    }
4468
 
4519
 
4469
    var display = cm.display, scroll = display.scroller;
4520
    var display = cm.display, scroll = display.scroller;
4470
    // Quit if there's nothing to scroll here
4521
    // Quit if there's nothing to scroll here
4471
    var canScrollX = scroll.scrollWidth > scroll.clientWidth;
4522
    var canScrollX = scroll.scrollWidth > scroll.clientWidth;
4472
    var canScrollY = scroll.scrollHeight > scroll.clientHeight;
4523
    var canScrollY = scroll.scrollHeight > scroll.clientHeight;
Line 4491... Line 4542...
4491
    // happen before the gutter has been realigned, causing it to
4542
    // happen before the gutter has been realigned, causing it to
4492
    // wriggle around in a most unseemly way. When we have an
4543
    // wriggle around in a most unseemly way. When we have an
4493
    // estimated pixels/delta value, we just handle horizontal
4544
    // estimated pixels/delta value, we just handle horizontal
4494
    // scrolling entirely here. It'll be slightly off from native, but
4545
    // scrolling entirely here. It'll be slightly off from native, but
4495
    // better than glitching out.
4546
    // better than glitching out.
4496
    if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
4547
    if (dx && !gecko && !presto && pixelsPerUnit != null) {
4497
      if (dy && canScrollY)
4548
      if (dy && canScrollY)
4498
        { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); }
4549
        { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * pixelsPerUnit)); }
4499
      setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit));
4550
      setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * pixelsPerUnit));
4500
      // Only prevent default scrolling if vertical scrolling is
4551
      // Only prevent default scrolling if vertical scrolling is
4501
      // actually possible. Otherwise, it causes vertical scroll
4552
      // actually possible. Otherwise, it causes vertical scroll
4502
      // jitter on OSX trackpads when deltaX is small and deltaY
4553
      // jitter on OSX trackpads when deltaX is small and deltaY
4503
      // is large (issue #3579)
4554
      // is large (issue #3579)
4504
      if (!dy || (dy && canScrollY))
4555
      if (!dy || (dy && canScrollY))
Line 4507... Line 4558...
4507
      return
4558
      return
4508
    }
4559
    }
4509
 
4560
 
4510
    // 'Project' the visible viewport to cover the area that is being
4561
    // 'Project' the visible viewport to cover the area that is being
4511
    // scrolled into view (if we know enough to estimate it).
4562
    // scrolled into view (if we know enough to estimate it).
4512
    if (dy && wheelPixelsPerUnit != null) {
4563
    if (dy && pixelsPerUnit != null) {
4513
      var pixels = dy * wheelPixelsPerUnit;
4564
      var pixels = dy * pixelsPerUnit;
4514
      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
4565
      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
4515
      if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
4566
      if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
4516
      else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
4567
      else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
4517
      updateDisplaySimple(cm, {top: top, bottom: bot});
4568
      updateDisplaySimple(cm, {top: top, bottom: bot});
4518
    }
4569
    }
4519
 
4570
 
4520
    if (wheelSamples < 20) {
4571
    if (wheelSamples < 20 && e.deltaMode !== 0) {
4521
      if (display.wheelStartX == null) {
4572
      if (display.wheelStartX == null) {
4522
        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
4573
        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
4523
        display.wheelDX = dx; display.wheelDY = dy;
4574
        display.wheelDX = dx; display.wheelDY = dy;
4524
        setTimeout(function () {
4575
        setTimeout(function () {
4525
          if (display.wheelStartX == null) { return }
4576
          if (display.wheelStartX == null) { return }
Line 4774... Line 4825...
4774
    cm.doc = doc;
4825
    cm.doc = doc;
4775
    doc.cm = cm;
4826
    doc.cm = cm;
4776
    estimateLineHeights(cm);
4827
    estimateLineHeights(cm);
4777
    loadMode(cm);
4828
    loadMode(cm);
4778
    setDirectionClass(cm);
4829
    setDirectionClass(cm);
-
 
4830
    cm.options.direction = doc.direction;
4779
    if (!cm.options.lineWrapping) { findMaxLine(cm); }
4831
    if (!cm.options.lineWrapping) { findMaxLine(cm); }
4780
    cm.options.mode = doc.modeOption;
4832
    cm.options.mode = doc.modeOption;
4781
    regChange(cm);
4833
    regChange(cm);
4782
  }
4834
  }
4783
 
4835
 
Line 4790... Line 4842...
4790
      setDirectionClass(cm);
4842
      setDirectionClass(cm);
4791
      regChange(cm);
4843
      regChange(cm);
4792
    });
4844
    });
4793
  }
4845
  }
4794
 
4846
 
4795
  function History(startGen) {
4847
  function History(prev) {
4796
    // Arrays of change events and selections. Doing something adds an
4848
    // Arrays of change events and selections. Doing something adds an
4797
    // event to done and clears undo. Undoing moves events from done
4849
    // event to done and clears undo. Undoing moves events from done
4798
    // to undone, redoing moves them in the other direction.
4850
    // to undone, redoing moves them in the other direction.
4799
    this.done = []; this.undone = [];
4851
    this.done = []; this.undone = [];
4800
    this.undoDepth = Infinity;
4852
    this.undoDepth = prev ? prev.undoDepth : Infinity;
4801
    // Used to track when changes can be merged into a single undo
4853
    // Used to track when changes can be merged into a single undo
4802
    // event
4854
    // event
4803
    this.lastModTime = this.lastSelTime = 0;
4855
    this.lastModTime = this.lastSelTime = 0;
4804
    this.lastOp = this.lastSelOp = null;
4856
    this.lastOp = this.lastSelOp = null;
4805
    this.lastOrigin = this.lastSelOrigin = null;
4857
    this.lastOrigin = this.lastSelOrigin = null;
4806
    // Used by the isClean() method
4858
    // Used by the isClean() method
4807
    this.generation = this.maxGeneration = startGen || 1;
4859
    this.generation = this.maxGeneration = prev ? prev.maxGeneration : 1;
4808
  }
4860
  }
4809
 
4861
 
4810
  // Create a history change event from an updateDoc-style change
4862
  // Create a history change event from an updateDoc-style change
4811
  // object.
4863
  // object.
4812
  function historyChangeFromChange(doc, change) {
4864
  function historyChangeFromChange(doc, change) {
Line 5107... Line 5159...
5107
 
5159
 
5108
    var bias = options && options.bias ||
5160
    var bias = options && options.bias ||
5109
      (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
5161
      (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
5110
    setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
5162
    setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
5111
 
5163
 
5112
    if (!(options && options.scroll === false) && doc.cm)
5164
    if (!(options && options.scroll === false) && doc.cm && doc.cm.getOption("readOnly") != "nocursor")
5113
      { ensureCursorVisible(doc.cm); }
5165
      { ensureCursorVisible(doc.cm); }
5114
  }
5166
  }
5115
 
5167
 
5116
  function setSelectionInner(doc, sel) {
5168
  function setSelectionInner(doc, sel) {
5117
    if (sel.equals(doc.sel)) { return }
5169
    if (sel.equals(doc.sel)) { return }
Line 5764... Line 5816...
5764
    var cm = doc.cm;
5816
    var cm = doc.cm;
5765
    if (cm && widget.noHScroll) { cm.display.alignWidgets = true; }
5817
    if (cm && widget.noHScroll) { cm.display.alignWidgets = true; }
5766
    changeLine(doc, handle, "widget", function (line) {
5818
    changeLine(doc, handle, "widget", function (line) {
5767
      var widgets = line.widgets || (line.widgets = []);
5819
      var widgets = line.widgets || (line.widgets = []);
5768
      if (widget.insertAt == null) { widgets.push(widget); }
5820
      if (widget.insertAt == null) { widgets.push(widget); }
5769
      else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); }
5821
      else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); }
5770
      widget.line = line;
5822
      widget.line = line;
5771
      if (cm && !lineIsHidden(doc, line)) {
5823
      if (cm && !lineIsHidden(doc, line)) {
5772
        var aboveVisible = heightAtLine(line) < doc.scrollTop;
5824
        var aboveVisible = heightAtLine(line) < doc.scrollTop;
5773
        updateLineHeight(line, line.height + widgetHeight(widget));
5825
        updateLineHeight(line, line.height + widgetHeight(widget));
5774
        if (aboveVisible) { addToScrollTop(cm, widget.height); }
5826
        if (aboveVisible) { addToScrollTop(cm, widget.height); }
Line 5950... Line 6002...
5950
      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
6002
      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
5951
        { updateMaxLine = true; }
6003
        { updateMaxLine = true; }
5952
      if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }
6004
      if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }
5953
      addMarkedSpan(line, new MarkedSpan(marker,
6005
      addMarkedSpan(line, new MarkedSpan(marker,
5954
                                         curLine == from.line ? from.ch : null,
6006
                                         curLine == from.line ? from.ch : null,
5955
                                         curLine == to.line ? to.ch : null));
6007
                                         curLine == to.line ? to.ch : null), doc.cm && doc.cm.curOp);
5956
      ++curLine;
6008
      ++curLine;
5957
    });
6009
    });
5958
    // lineIsHidden depends on the presence of the spans, so needs a second pass
6010
    // lineIsHidden depends on the presence of the spans, so needs a second pass
5959
    if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
6011
    if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
5960
      if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); }
6012
      if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); }
Line 6122... Line 6174...
6122
      replaceRange(this, code, from, to, origin);
6174
      replaceRange(this, code, from, to, origin);
6123
    },
6175
    },
6124
    getRange: function(from, to, lineSep) {
6176
    getRange: function(from, to, lineSep) {
6125
      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
6177
      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
6126
      if (lineSep === false) { return lines }
6178
      if (lineSep === false) { return lines }
-
 
6179
      if (lineSep === '') { return lines.join('') }
6127
      return lines.join(lineSep || this.lineSeparator())
6180
      return lines.join(lineSep || this.lineSeparator())
6128
    },
6181
    },
6129
 
6182
 
6130
    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},
6183
    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},
6131
 
6184
 
Line 6173... Line 6226...
6173
    setSelections: docMethodOp(function(ranges, primary, options) {
6226
    setSelections: docMethodOp(function(ranges, primary, options) {
6174
      if (!ranges.length) { return }
6227
      if (!ranges.length) { return }
6175
      var out = [];
6228
      var out = [];
6176
      for (var i = 0; i < ranges.length; i++)
6229
      for (var i = 0; i < ranges.length; i++)
6177
        { out[i] = new Range(clipPos(this, ranges[i].anchor),
6230
        { out[i] = new Range(clipPos(this, ranges[i].anchor),
6178
                           clipPos(this, ranges[i].head)); }
6231
                           clipPos(this, ranges[i].head || ranges[i].anchor)); }
6179
      if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }
6232
      if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }
6180
      setSelection(this, normalizeSelection(this.cm, out, primary), options);
6233
      setSelection(this, normalizeSelection(this.cm, out, primary), options);
6181
    }),
6234
    }),
6182
    addSelection: docMethodOp(function(anchor, head, options) {
6235
    addSelection: docMethodOp(function(anchor, head, options) {
6183
      var ranges = this.sel.ranges.slice(0);
6236
      var ranges = this.sel.ranges.slice(0);
Line 6236... Line 6289...
6236
      return {undo: done, redo: undone}
6289
      return {undo: done, redo: undone}
6237
    },
6290
    },
6238
    clearHistory: function() {
6291
    clearHistory: function() {
6239
      var this$1 = this;
6292
      var this$1 = this;
6240
 
6293
 
6241
      this.history = new History(this.history.maxGeneration);
6294
      this.history = new History(this.history);
6242
      linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true);
6295
      linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true);
6243
    },
6296
    },
6244
 
6297
 
6245
    markClean: function() {
6298
    markClean: function() {
6246
      this.cleanGeneration = this.changeGeneration(true);
6299
      this.cleanGeneration = this.changeGeneration(true);
Line 6257... Line 6310...
6257
    getHistory: function() {
6310
    getHistory: function() {
6258
      return {done: copyHistoryArray(this.history.done),
6311
      return {done: copyHistoryArray(this.history.done),
6259
              undone: copyHistoryArray(this.history.undone)}
6312
              undone: copyHistoryArray(this.history.undone)}
6260
    },
6313
    },
6261
    setHistory: function(histData) {
6314
    setHistory: function(histData) {
6262
      var hist = this.history = new History(this.history.maxGeneration);
6315
      var hist = this.history = new History(this.history);
6263
      hist.done = copyHistoryArray(histData.done.slice(0), null, true);
6316
      hist.done = copyHistoryArray(histData.done.slice(0), null, true);
6264
      hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
6317
      hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
6265
    },
6318
    },
6266
 
6319
 
6267
    setGutterMarker: docMethodOp(function(line, gutterID, value) {
6320
    setGutterMarker: docMethodOp(function(line, gutterID, value) {
Line 6676... Line 6729...
6676
    "fallthrough": "basic"
6729
    "fallthrough": "basic"
6677
  };
6730
  };
6678
  // Very basic readline/emacs-style bindings, which are standard on Mac.
6731
  // Very basic readline/emacs-style bindings, which are standard on Mac.
6679
  keyMap.emacsy = {
6732
  keyMap.emacsy = {
6680
    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
6733
    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
6681
    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
6734
    "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp",
6682
    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
-
 
6683
    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
6735
    "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine",
6684
    "Ctrl-O": "openLine"
6736
    "Ctrl-T": "transposeChars", "Ctrl-O": "openLine"
6685
  };
6737
  };
6686
  keyMap.macDefault = {
6738
  keyMap.macDefault = {
6687
    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
6739
    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
6688
    "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
6740
    "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
6689
    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
6741
    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
Line 7000... Line 7052...
7000
    goColumnRight: function (cm) { return cm.moveH(1, "column"); },
7052
    goColumnRight: function (cm) { return cm.moveH(1, "column"); },
7001
    goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
7053
    goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
7002
    goGroupRight: function (cm) { return cm.moveH(1, "group"); },
7054
    goGroupRight: function (cm) { return cm.moveH(1, "group"); },
7003
    goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
7055
    goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
7004
    goWordRight: function (cm) { return cm.moveH(1, "word"); },
7056
    goWordRight: function (cm) { return cm.moveH(1, "word"); },
7005
    delCharBefore: function (cm) { return cm.deleteH(-1, "char"); },
7057
    delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); },
7006
    delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
7058
    delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
7007
    delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
7059
    delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
7008
    delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
7060
    delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
7009
    delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
7061
    delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
7010
    delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
7062
    delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
Line 7373... Line 7425...
7373
  function leftButtonStartDrag(cm, event, pos, behavior) {
7425
  function leftButtonStartDrag(cm, event, pos, behavior) {
7374
    var display = cm.display, moved = false;
7426
    var display = cm.display, moved = false;
7375
    var dragEnd = operation(cm, function (e) {
7427
    var dragEnd = operation(cm, function (e) {
7376
      if (webkit) { display.scroller.draggable = false; }
7428
      if (webkit) { display.scroller.draggable = false; }
7377
      cm.state.draggingText = false;
7429
      cm.state.draggingText = false;
-
 
7430
      if (cm.state.delayingBlurEvent) {
-
 
7431
        if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; }
-
 
7432
        else { delayBlurEvent(cm); }
-
 
7433
      }
7378
      off(display.wrapper.ownerDocument, "mouseup", dragEnd);
7434
      off(display.wrapper.ownerDocument, "mouseup", dragEnd);
7379
      off(display.wrapper.ownerDocument, "mousemove", mouseMove);
7435
      off(display.wrapper.ownerDocument, "mousemove", mouseMove);
7380
      off(display.scroller, "dragstart", dragStart);
7436
      off(display.scroller, "dragstart", dragStart);
7381
      off(display.scroller, "drop", dragEnd);
7437
      off(display.scroller, "drop", dragEnd);
7382
      if (!moved) {
7438
      if (!moved) {
Line 7396... Line 7452...
7396
    var dragStart = function () { return moved = true; };
7452
    var dragStart = function () { return moved = true; };
7397
    // Let the drag handler handle this.
7453
    // Let the drag handler handle this.
7398
    if (webkit) { display.scroller.draggable = true; }
7454
    if (webkit) { display.scroller.draggable = true; }
7399
    cm.state.draggingText = dragEnd;
7455
    cm.state.draggingText = dragEnd;
7400
    dragEnd.copy = !behavior.moveOnDrag;
7456
    dragEnd.copy = !behavior.moveOnDrag;
7401
    // IE's approach to draggable
-
 
7402
    if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
-
 
7403
    on(display.wrapper.ownerDocument, "mouseup", dragEnd);
7457
    on(display.wrapper.ownerDocument, "mouseup", dragEnd);
7404
    on(display.wrapper.ownerDocument, "mousemove", mouseMove);
7458
    on(display.wrapper.ownerDocument, "mousemove", mouseMove);
7405
    on(display.scroller, "dragstart", dragStart);
7459
    on(display.scroller, "dragstart", dragStart);
7406
    on(display.scroller, "drop", dragEnd);
7460
    on(display.scroller, "drop", dragEnd);
7407
 
7461
 
7408
    delayBlurEvent(cm);
7462
    cm.state.delayingBlurEvent = true;
7409
    setTimeout(function () { return display.input.focus(); }, 20);
7463
    setTimeout(function () { return display.input.focus(); }, 20);
-
 
7464
    // IE's approach to draggable
-
 
7465
    if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
7410
  }
7466
  }
7411
 
7467
 
7412
  function rangeForUnit(cm, pos, unit) {
7468
  function rangeForUnit(cm, pos, unit) {
7413
    if (unit == "char") { return new Range(pos, pos) }
7469
    if (unit == "char") { return new Range(pos, pos) }
7414
    if (unit == "word") { return cm.findWordAt(pos) }
7470
    if (unit == "word") { return cm.findWordAt(pos) }
Line 7417... Line 7473...
7417
    return new Range(result.from, result.to)
7473
    return new Range(result.from, result.to)
7418
  }
7474
  }
7419
 
7475
 
7420
  // Normal selection, as opposed to text dragging.
7476
  // Normal selection, as opposed to text dragging.
7421
  function leftButtonSelect(cm, event, start, behavior) {
7477
  function leftButtonSelect(cm, event, start, behavior) {
-
 
7478
    if (ie) { delayBlurEvent(cm); }
7422
    var display = cm.display, doc = cm.doc;
7479
    var display = cm.display, doc = cm.doc;
7423
    e_preventDefault(event);
7480
    e_preventDefault(event);
7424
 
7481
 
7425
    var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
7482
    var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
7426
    if (behavior.addNew && !behavior.extend) {
7483
    if (behavior.addNew && !behavior.extend) {
Line 7695... Line 7752...
7695
        lineNo++;
7752
        lineNo++;
7696
      });
7753
      });
7697
      for (var i = newBreaks.length - 1; i >= 0; i--)
7754
      for (var i = newBreaks.length - 1; i >= 0; i--)
7698
        { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
7755
        { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
7699
    });
7756
    });
7700
    option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
7757
    option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
7701
      cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
7758
      cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
7702
      if (old != Init) { cm.refresh(); }
7759
      if (old != Init) { cm.refresh(); }
7703
    });
7760
    });
7704
    option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true);
7761
    option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true);
7705
    option("electricChars", true);
7762
    option("electricChars", true);
Line 7875... Line 7932...
7875
    startOperation(this);
7932
    startOperation(this);
7876
    this.curOp.forceUpdate = true;
7933
    this.curOp.forceUpdate = true;
7877
    attachDoc(this, doc);
7934
    attachDoc(this, doc);
7878
 
7935
 
7879
    if ((options.autofocus && !mobile) || this.hasFocus())
7936
    if ((options.autofocus && !mobile) || this.hasFocus())
7880
      { setTimeout(bind(onFocus, this), 20); }
7937
      { setTimeout(function () {
-
 
7938
        if (this$1.hasFocus() && !this$1.state.focused) { onFocus(this$1); }
-
 
7939
      }, 20); }
7881
    else
7940
    else
7882
      { onBlur(this); }
7941
      { onBlur(this); }
7883
 
7942
 
7884
    for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
7943
    for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
7885
      { optionHandlers[opt](this, options[opt], Init); } }
7944
      { optionHandlers[opt](this, options[opt], Init); } }
Line 8184... Line 8243...
8184
    field.setAttribute("autocapitalize", autocapitalize ? "" : "off");
8243
    field.setAttribute("autocapitalize", autocapitalize ? "" : "off");
8185
    field.setAttribute("spellcheck", !!spellcheck);
8244
    field.setAttribute("spellcheck", !!spellcheck);
8186
  }
8245
  }
8187
 
8246
 
8188
  function hiddenTextarea() {
8247
  function hiddenTextarea() {
8189
    var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none");
8248
    var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none");
8190
    var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
8249
    var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
8191
    // The textarea is kept positioned near the cursor to prevent the
8250
    // The textarea is kept positioned near the cursor to prevent the
8192
    // fact that it'll be scrolled into view on input from scrolling
8251
    // fact that it'll be scrolled into view on input from scrolling
8193
    // our fake cursor out of view. On webkit, when wrap=off, paste is
8252
    // our fake cursor out of view. On webkit, when wrap=off, paste is
8194
    // very slow. So make the area wide instead.
8253
    // very slow. So make the area wide instead.
Line 8638... Line 8697...
8638
      helpers[type]._global.push({pred: predicate, val: value});
8697
      helpers[type]._global.push({pred: predicate, val: value});
8639
    };
8698
    };
8640
  }
8699
  }
8641
 
8700
 
8642
  // Used for horizontal relative motion. Dir is -1 or 1 (left or
8701
  // Used for horizontal relative motion. Dir is -1 or 1 (left or
8643
  // right), unit can be "char", "column" (like char, but doesn't
8702
  // right), unit can be "codepoint", "char", "column" (like char, but
8644
  // cross line boundaries), "word" (across next word), or "group" (to
8703
  // doesn't cross line boundaries), "word" (across next word), or
8645
  // the start of next group of word or non-word-non-whitespace
8704
  // "group" (to the start of next group of word or
8646
  // chars). The visually param controls whether, in right-to-left
8705
  // non-word-non-whitespace chars). The visually param controls
8647
  // text, direction 1 means to move towards the next index in the
8706
  // whether, in right-to-left text, direction 1 means to move towards
8648
  // string, or towards the character to the right of the current
8707
  // the next index in the string, or towards the character to the right
8649
  // position. The resulting position will have a hitSide=true
8708
  // of the current position. The resulting position will have a
8650
  // property if it reached the end of the document.
8709
  // hitSide=true property if it reached the end of the document.
8651
  function findPosH(doc, pos, dir, unit, visually) {
8710
  function findPosH(doc, pos, dir, unit, visually) {
8652
    var oldPos = pos;
8711
    var oldPos = pos;
8653
    var origDir = dir;
8712
    var origDir = dir;
8654
    var lineObj = getLine(doc, pos.line);
8713
    var lineObj = getLine(doc, pos.line);
8655
    var lineDir = visually && doc.direction == "rtl" ? -dir : dir;
8714
    var lineDir = visually && doc.direction == "rtl" ? -dir : dir;
Line 8659... Line 8718...
8659
      pos = new Pos(l, pos.ch, pos.sticky);
8718
      pos = new Pos(l, pos.ch, pos.sticky);
8660
      return lineObj = getLine(doc, l)
8719
      return lineObj = getLine(doc, l)
8661
    }
8720
    }
8662
    function moveOnce(boundToLine) {
8721
    function moveOnce(boundToLine) {
8663
      var next;
8722
      var next;
-
 
8723
      if (unit == "codepoint") {
-
 
8724
        var ch = lineObj.text.charCodeAt(pos.ch + (dir > 0 ? 0 : -1));
-
 
8725
        if (isNaN(ch)) {
-
 
8726
          next = null;
-
 
8727
        } else {
-
 
8728
          var astral = dir > 0 ? ch >= 0xD800 && ch < 0xDC00 : ch >= 0xDC00 && ch < 0xDFFF;
-
 
8729
          next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (astral ? 2 : 1))), -dir);
-
 
8730
        }
8664
      if (visually) {
8731
      } else if (visually) {
8665
        next = moveVisually(doc.cm, lineObj, pos, dir);
8732
        next = moveVisually(doc.cm, lineObj, pos, dir);
8666
      } else {
8733
      } else {
8667
        next = moveLogically(lineObj, pos, dir);
8734
        next = moveLogically(lineObj, pos, dir);
8668
      }
8735
      }
8669
      if (next == null) {
8736
      if (next == null) {
Line 8675... Line 8742...
8675
        pos = next;
8742
        pos = next;
8676
      }
8743
      }
8677
      return true
8744
      return true
8678
    }
8745
    }
8679
 
8746
 
8680
    if (unit == "char") {
8747
    if (unit == "char" || unit == "codepoint") {
8681
      moveOnce();
8748
      moveOnce();
8682
    } else if (unit == "column") {
8749
    } else if (unit == "column") {
8683
      moveOnce(true);
8750
      moveOnce(true);
8684
    } else if (unit == "word" || unit == "group") {
8751
    } else if (unit == "word" || unit == "group") {
8685
      var sawType = null, group = unit == "group";
8752
      var sawType = null, group = unit == "group";
Line 8743... Line 8810...
8743
  ContentEditableInput.prototype.init = function (display) {
8810
  ContentEditableInput.prototype.init = function (display) {
8744
      var this$1 = this;
8811
      var this$1 = this;
8745
 
8812
 
8746
    var input = this, cm = input.cm;
8813
    var input = this, cm = input.cm;
8747
    var div = input.div = display.lineDiv;
8814
    var div = input.div = display.lineDiv;
-
 
8815
    div.contentEditable = true;
8748
    disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize);
8816
    disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize);
8749
 
8817
 
8750
    function belongsToInput(e) {
8818
    function belongsToInput(e) {
8751
      for (var t = e.target; t; t = t.parentNode) {
8819
      for (var t = e.target; t; t = t.parentNode) {
8752
        if (t == div) { return true }
8820
        if (t == div) { return true }
Line 8809... Line 8877...
8809
      }
8877
      }
8810
      // Old-fashioned briefly-focus-a-textarea hack
8878
      // Old-fashioned briefly-focus-a-textarea hack
8811
      var kludge = hiddenTextarea(), te = kludge.firstChild;
8879
      var kludge = hiddenTextarea(), te = kludge.firstChild;
8812
      cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
8880
      cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
8813
      te.value = lastCopied.text.join("\n");
8881
      te.value = lastCopied.text.join("\n");
8814
      var hadFocus = document.activeElement;
8882
      var hadFocus = activeElt();
8815
      selectInput(te);
8883
      selectInput(te);
8816
      setTimeout(function () {
8884
      setTimeout(function () {
8817
        cm.display.lineSpace.removeChild(kludge);
8885
        cm.display.lineSpace.removeChild(kludge);
8818
        hadFocus.focus();
8886
        hadFocus.focus();
8819
        if (hadFocus == div) { input.showPrimarySelection(); }
8887
        if (hadFocus == div) { input.showPrimarySelection(); }
Line 8827... Line 8895...
8827
    // Label for screenreaders, accessibility
8895
    // Label for screenreaders, accessibility
8828
    if(label) {
8896
    if(label) {
8829
      this.div.setAttribute('aria-label', label);
8897
      this.div.setAttribute('aria-label', label);
8830
    } else {
8898
    } else {
8831
      this.div.removeAttribute('aria-label');
8899
      this.div.removeAttribute('aria-label');
8832
    }
8900
    }
8833
  };
8901
  };
8834
 
8902
 
8835
  ContentEditableInput.prototype.prepareSelection = function () {
8903
  ContentEditableInput.prototype.prepareSelection = function () {
8836
    var result = prepareSelection(this.cm, false);
8904
    var result = prepareSelection(this.cm, false);
8837
    result.focus = document.activeElement == this.div;
8905
    result.focus = activeElt() == this.div;
8838
    return result
8906
    return result
8839
  };
8907
  };
8840
 
8908
 
8841
  ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
8909
  ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
8842
    if (!info || !this.cm.display.view.length) { return }
8910
    if (!info || !this.cm.display.view.length) { return }
Line 8928... Line 8996...
8928
    return contains(this.div, node)
8996
    return contains(this.div, node)
8929
  };
8997
  };
8930
 
8998
 
8931
  ContentEditableInput.prototype.focus = function () {
8999
  ContentEditableInput.prototype.focus = function () {
8932
    if (this.cm.options.readOnly != "nocursor") {
9000
    if (this.cm.options.readOnly != "nocursor") {
8933
      if (!this.selectionInEditor() || document.activeElement != this.div)
9001
      if (!this.selectionInEditor() || activeElt() != this.div)
8934
        { this.showSelection(this.prepareSelection(), true); }
9002
        { this.showSelection(this.prepareSelection(), true); }
8935
      this.div.focus();
9003
      this.div.focus();
8936
    }
9004
    }
8937
  };
9005
  };
8938
  ContentEditableInput.prototype.blur = function () { this.div.blur(); };
9006
  ContentEditableInput.prototype.blur = function () { this.div.blur(); };
8939
  ContentEditableInput.prototype.getField = function () { return this.div };
9007
  ContentEditableInput.prototype.getField = function () { return this.div };
8940
 
9008
 
8941
  ContentEditableInput.prototype.supportsTouch = function () { return true };
9009
  ContentEditableInput.prototype.supportsTouch = function () { return true };
8942
 
9010
 
8943
  ContentEditableInput.prototype.receivedFocus = function () {
9011
  ContentEditableInput.prototype.receivedFocus = function () {
-
 
9012
      var this$1 = this;
-
 
9013
 
8944
    var input = this;
9014
    var input = this;
8945
    if (this.selectionInEditor())
9015
    if (this.selectionInEditor())
8946
      { this.pollSelection(); }
9016
      { setTimeout(function () { return this$1.pollSelection(); }, 20); }
8947
    else
9017
    else
8948
      { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }
9018
      { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }
8949
 
9019
 
8950
    function poll() {
9020
    function poll() {
8951
      if (input.cm.state.focused) {
9021
      if (input.cm.state.focused) {
Line 9619... Line 9689...
9619
  };
9689
  };
9620
 
9690
 
9621
  TextareaInput.prototype.readOnlyChanged = function (val) {
9691
  TextareaInput.prototype.readOnlyChanged = function (val) {
9622
    if (!val) { this.reset(); }
9692
    if (!val) { this.reset(); }
9623
    this.textarea.disabled = val == "nocursor";
9693
    this.textarea.disabled = val == "nocursor";
-
 
9694
    this.textarea.readOnly = !!val;
9624
  };
9695
  };
9625
 
9696
 
9626
  TextareaInput.prototype.setUneditable = function () {};
9697
  TextareaInput.prototype.setUneditable = function () {};
9627
 
9698
 
9628
  TextareaInput.prototype.needsContentAttribute = false;
9699
  TextareaInput.prototype.needsContentAttribute = false;
Line 9769... Line 9840...
9769
 
9840
 
9770
  CodeMirror.fromTextArea = fromTextArea;
9841
  CodeMirror.fromTextArea = fromTextArea;
9771
 
9842
 
9772
  addLegacyProps(CodeMirror);
9843
  addLegacyProps(CodeMirror);
9773
 
9844
 
9774
  CodeMirror.version = "5.57.0";
9845
  CodeMirror.version = "5.65.2";
9775
 
9846
 
9776
  return CodeMirror;
9847
  return CodeMirror;
9777
 
9848
 
9778
})));
9849
})));