SiteOrigin CSS - Version 1.1.3

Version Description

  • 31 January 2017 =
  • Removed leading slash in paths after plugin_dir_url().
  • Updated to latest CodeMirror.
  • Fixed padding issue that was causing problems with Firefox and the color picker.
Download this release

Release Info

Developer gpriday
Plugin Icon 128x128 SiteOrigin CSS
Version 1.1.3
Comparing to
See all releases

Code changes from version 1.1.2 to 1.1.3

css/admin.css CHANGED
@@ -335,7 +335,9 @@
335
  padding: 5px 8px;
336
  }
337
  #so-custom-css-properties .sections .fields-table .minicolors input {
338
- padding: 14px 0 14px 30px;
 
 
339
  }
340
  #so-custom-css-properties .sections .fields-table .select {
341
  display: block;
335
  padding: 5px 8px;
336
  }
337
  #so-custom-css-properties .sections .fields-table .minicolors input {
338
+ box-sizing: border-box;
339
+ height: 30px;
340
+ padding: 5px 0 5px 30px;
341
  }
342
  #so-custom-css-properties .sections .fields-table .select {
343
  display: block;
lib/codemirror/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
  of this software and associated documentation files (the "Software"), to deal
1
+ Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
  of this software and associated documentation files (the "Software"), to deal
lib/codemirror/addon/fold/brace-fold.js CHANGED
@@ -13,7 +13,7 @@
13
 
14
  CodeMirror.registerHelper("fold", "brace", function(cm, start) {
15
  var line = start.line, lineText = cm.getLine(line);
16
- var startCh, tokenType;
17
 
18
  function findOpening(openCh) {
19
  for (var at = start.ch, pass = 0;;) {
@@ -72,15 +72,15 @@ CodeMirror.registerHelper("fold", "import", function(cm, start) {
72
  }
73
  }
74
 
75
- var start = start.line, has = hasImport(start), prev;
76
- if (!has || hasImport(start - 1) || ((prev = hasImport(start - 2)) && prev.end.line == start - 1))
77
  return null;
78
  for (var end = has.end;;) {
79
  var next = hasImport(end.line + 1);
80
  if (next == null) break;
81
  end = next.end;
82
  }
83
- return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
84
  });
85
 
86
  CodeMirror.registerHelper("fold", "include", function(cm, start) {
@@ -91,14 +91,14 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) {
91
  if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
92
  }
93
 
94
- var start = start.line, has = hasInclude(start);
95
- if (has == null || hasInclude(start - 1) != null) return null;
96
- for (var end = start;;) {
97
  var next = hasInclude(end + 1);
98
  if (next == null) break;
99
  ++end;
100
  }
101
- return {from: CodeMirror.Pos(start, has + 1),
102
  to: cm.clipPos(CodeMirror.Pos(end))};
103
  });
104
 
13
 
14
  CodeMirror.registerHelper("fold", "brace", function(cm, start) {
15
  var line = start.line, lineText = cm.getLine(line);
16
+ var tokenType;
17
 
18
  function findOpening(openCh) {
19
  for (var at = start.ch, pass = 0;;) {
72
  }
73
  }
74
 
75
+ var startLine = start.line, has = hasImport(startLine), prev;
76
+ if (!has || hasImport(startLine - 1) || ((prev = hasImport(startLine - 2)) && prev.end.line == startLine - 1))
77
  return null;
78
  for (var end = has.end;;) {
79
  var next = hasImport(end.line + 1);
80
  if (next == null) break;
81
  end = next.end;
82
  }
83
+ return {from: cm.clipPos(CodeMirror.Pos(startLine, has.startCh + 1)), to: end};
84
  });
85
 
86
  CodeMirror.registerHelper("fold", "include", function(cm, start) {
91
  if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
92
  }
93
 
94
+ var startLine = start.line, has = hasInclude(startLine);
95
+ if (has == null || hasInclude(startLine - 1) != null) return null;
96
+ for (var end = startLine;;) {
97
  var next = hasInclude(end + 1);
98
  if (next == null) break;
99
  ++end;
100
  }
101
+ return {from: CodeMirror.Pos(startLine, has + 1),
102
  to: cm.clipPos(CodeMirror.Pos(end))};
103
  });
104
 
lib/codemirror/addon/fold/brace-fold.min.js CHANGED
@@ -1 +1 @@
1
- !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.registerHelper("fold","brace",function(r,n){function t(t){for(var i=n.ch,s=0;;){var u=i<=0?-1:f.lastIndexOf(t,i-1);if(u!=-1){if(1==s&&u<n.ch)break;if(o=r.getTokenTypeAt(e.Pos(l,u+1)),!/^(comment|string)/.test(o))return u+1;i=u-1}else{if(1==s)break;s=1,i=f.length}}}var i,o,l=n.line,f=r.getLine(l),s="{",u="}",i=t("{");if(null==i&&(s="[",u="]",i=t("[")),null!=i){var a,d,c=1,g=r.lastLine();e:for(var v=l;v<=g;++v)for(var p=r.getLine(v),m=v==l?i:0;;){var P=p.indexOf(s,m),k=p.indexOf(u,m);if(P<0&&(P=p.length),k<0&&(k=p.length),m=Math.min(P,k),m==p.length)break;if(r.getTokenTypeAt(e.Pos(v,m+1))==o)if(m==P)++c;else if(!--c){a=v,d=m;break e}++m}if(null!=a&&(l!=a||d!=i))return{from:e.Pos(l,i),to:e.Pos(a,d)}}}),e.registerHelper("fold","import",function(r,n){function t(n){if(n<r.firstLine()||n>r.lastLine())return null;var t=r.getTokenAt(e.Pos(n,1));if(/\S/.test(t.string)||(t=r.getTokenAt(e.Pos(n,t.end+1))),"keyword"!=t.type||"import"!=t.string)return null;for(var i=n,o=Math.min(r.lastLine(),n+10);i<=o;++i){var l=r.getLine(i),f=l.indexOf(";");if(f!=-1)return{startCh:t.end,end:e.Pos(i,f)}}}var i,n=n.line,o=t(n);if(!o||t(n-1)||(i=t(n-2))&&i.end.line==n-1)return null;for(var l=o.end;;){var f=t(l.line+1);if(null==f)break;l=f.end}return{from:r.clipPos(e.Pos(n,o.startCh+1)),to:l}}),e.registerHelper("fold","include",function(r,n){function t(n){if(n<r.firstLine()||n>r.lastLine())return null;var t=r.getTokenAt(e.Pos(n,1));return/\S/.test(t.string)||(t=r.getTokenAt(e.Pos(n,t.end+1))),"meta"==t.type&&"#include"==t.string.slice(0,8)?t.start+8:void 0}var n=n.line,i=t(n);if(null==i||null!=t(n-1))return null;for(var o=n;;){var l=t(o+1);if(null==l)break;++o}return{from:e.Pos(n,i+1),to:r.clipPos(e.Pos(o))}})});
1
+ !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.registerHelper("fold","brace",function(r,n){function t(t){for(var f=n.ch,s=0;;){var u=f<=0?-1:l.lastIndexOf(t,f-1);if(u!=-1){if(1==s&&u<n.ch)break;if(i=r.getTokenTypeAt(e.Pos(o,u+1)),!/^(comment|string)/.test(i))return u+1;f=u-1}else{if(1==s)break;s=1,f=l.length}}}var i,o=n.line,l=r.getLine(o),f="{",s="}",u=t("{");if(null==u&&(f="[",s="]",u=t("[")),null!=u){var a,d,c=1,g=r.lastLine();e:for(var v=o;v<=g;++v)for(var p=r.getLine(v),m=v==o?u:0;;){var P=p.indexOf(f,m),k=p.indexOf(s,m);if(P<0&&(P=p.length),k<0&&(k=p.length),m=Math.min(P,k),m==p.length)break;if(r.getTokenTypeAt(e.Pos(v,m+1))==i)if(m==P)++c;else if(!--c){a=v,d=m;break e}++m}if(null!=a&&(o!=a||d!=u))return{from:e.Pos(o,u),to:e.Pos(a,d)}}}),e.registerHelper("fold","import",function(r,n){function t(n){if(n<r.firstLine()||n>r.lastLine())return null;var t=r.getTokenAt(e.Pos(n,1));if(/\S/.test(t.string)||(t=r.getTokenAt(e.Pos(n,t.end+1))),"keyword"!=t.type||"import"!=t.string)return null;for(var i=n,o=Math.min(r.lastLine(),n+10);i<=o;++i){var l=r.getLine(i),f=l.indexOf(";");if(f!=-1)return{startCh:t.end,end:e.Pos(i,f)}}}var i,o=n.line,l=t(o);if(!l||t(o-1)||(i=t(o-2))&&i.end.line==o-1)return null;for(var f=l.end;;){var s=t(f.line+1);if(null==s)break;f=s.end}return{from:r.clipPos(e.Pos(o,l.startCh+1)),to:f}}),e.registerHelper("fold","include",function(r,n){function t(n){if(n<r.firstLine()||n>r.lastLine())return null;var t=r.getTokenAt(e.Pos(n,1));return/\S/.test(t.string)||(t=r.getTokenAt(e.Pos(n,t.end+1))),"meta"==t.type&&"#include"==t.string.slice(0,8)?t.start+8:void 0}var i=n.line,o=t(i);if(null==o||null!=t(i-1))return null;for(var l=i;;){var f=t(l+1);if(null==f)break;++l}return{from:e.Pos(i,o+1),to:r.clipPos(e.Pos(l))}})});
lib/codemirror/addon/fold/comment-fold.js CHANGED
@@ -29,7 +29,7 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
29
  }
30
  if (pass == 1 && found < start.ch) return;
31
  if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) &&
32
- (lineText.slice(found - endToken.length, found) == endToken ||
33
  !/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) {
34
  startCh = found + startToken.length;
35
  break;
29
  }
30
  if (pass == 1 && found < start.ch) return;
31
  if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) &&
32
+ (found == 0 || lineText.slice(found - endToken.length, found) == endToken ||
33
  !/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) {
34
  startCh = found + startToken.length;
35
  break;
lib/codemirror/addon/fold/comment-fold.min.js CHANGED
@@ -1 +1 @@
1
- !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.registerGlobalHelper("fold","comment",function(e){return e.blockCommentStart&&e.blockCommentEnd},function(t,n){var o=t.getModeAt(n),r=o.blockCommentStart,i=o.blockCommentEnd;if(r&&i){for(var f,l=n.line,c=t.getLine(l),m=n.ch,a=0;;){var d=m<=0?-1:c.lastIndexOf(r,m-1);if(d!=-1){if(1==a&&d<n.ch)return;if(/comment/.test(t.getTokenTypeAt(e.Pos(l,d+1)))&&(c.slice(d-i.length,d)==i||!/comment/.test(t.getTokenTypeAt(e.Pos(l,d))))){f=d+r.length;break}m=d-1}else{if(1==a)return;a=1,m=c.length}}var s,u,b=1,g=t.lastLine();e:for(var h=l;h<=g;++h)for(var k=t.getLine(h),p=h==l?f:0;;){var v=k.indexOf(r,p),y=k.indexOf(i,p);if(v<0&&(v=k.length),y<0&&(y=k.length),p=Math.min(v,y),p==k.length)break;if(p==v)++b;else if(!--b){s=h,u=p;break e}++p}if(null!=s&&(l!=s||u!=f))return{from:e.Pos(l,f),to:e.Pos(s,u)}}})});
1
+ !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.registerGlobalHelper("fold","comment",function(e){return e.blockCommentStart&&e.blockCommentEnd},function(t,n){var o=t.getModeAt(n),r=o.blockCommentStart,i=o.blockCommentEnd;if(r&&i){for(var f,l=n.line,c=t.getLine(l),m=n.ch,a=0;;){var d=m<=0?-1:c.lastIndexOf(r,m-1);if(d!=-1){if(1==a&&d<n.ch)return;if(/comment/.test(t.getTokenTypeAt(e.Pos(l,d+1)))&&(0==d||c.slice(d-i.length,d)==i||!/comment/.test(t.getTokenTypeAt(e.Pos(l,d))))){f=d+r.length;break}m=d-1}else{if(1==a)return;a=1,m=c.length}}var s,u,b=1,g=t.lastLine();e:for(var h=l;h<=g;++h)for(var k=t.getLine(h),p=h==l?f:0;;){var v=k.indexOf(r,p),y=k.indexOf(i,p);if(v<0&&(v=k.length),y<0&&(y=k.length),p=Math.min(v,y),p==k.length)break;if(p==v)++b;else if(!--b){s=h,u=p;break e}++p}if(null!=s&&(l!=s||u!=f))return{from:e.Pos(l,f),to:e.Pos(s,u)}}})});
lib/codemirror/addon/fold/foldcode.js CHANGED
@@ -49,7 +49,7 @@
49
  });
50
  var myRange = cm.markText(range.from, range.to, {
51
  replacedWith: myWidget,
52
- clearOnEnter: true,
53
  __isFold: true
54
  });
55
  myRange.on("clear", function(from, to) {
@@ -129,7 +129,8 @@
129
  rangeFinder: CodeMirror.fold.auto,
130
  widget: "\u2194",
131
  minFoldSize: 0,
132
- scanUp: false
 
133
  };
134
 
135
  CodeMirror.defineOption("foldOptions", null);
49
  });
50
  var myRange = cm.markText(range.from, range.to, {
51
  replacedWith: myWidget,
52
+ clearOnEnter: getOption(cm, options, "clearOnEnter"),
53
  __isFold: true
54
  });
55
  myRange.on("clear", function(from, to) {
129
  rangeFinder: CodeMirror.fold.auto,
130
  widget: "\u2194",
131
  minFoldSize: 0,
132
+ scanUp: false,
133
+ clearOnEnter: true
134
  };
135
 
136
  CodeMirror.defineOption("foldOptions", null);
lib/codemirror/addon/fold/foldcode.min.js CHANGED
@@ -1 +1 @@
1
- !function(n){"object"==typeof exports&&"object"==typeof module?n(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],n):n(CodeMirror)}(function(n){"use strict";function o(o,i,t,f){function l(n){var e=d(o,i);if(!e||e.to.line-e.from.line<u)return null;for(var r=o.findMarksAt(e.from),t=0;t<r.length;++t)if(r[t].__isFold&&"fold"!==f){if(!n)return null;e.cleared=!0,r[t].clear()}return e}if(t&&t.call){var d=t;t=null}else var d=r(o,t,"rangeFinder");"number"==typeof i&&(i=n.Pos(i,0));var u=r(o,t,"minFoldSize"),a=l(!0);if(r(o,t,"scanUp"))for(;!a&&i.line>o.firstLine();)i=n.Pos(i.line-1,0),a=l(!1);if(a&&!a.cleared&&"unfold"!==f){var c=e(o,t);n.on(c,"mousedown",function(o){s.clear(),n.e_preventDefault(o)});var s=o.markText(a.from,a.to,{replacedWith:c,clearOnEnter:!0,__isFold:!0});s.on("clear",function(e,r){n.signal(o,"unfold",o,e,r)}),n.signal(o,"fold",o,a.from,a.to)}}function e(n,o){var e=r(n,o,"widget");if("string"==typeof e){var i=document.createTextNode(e);e=document.createElement("span"),e.appendChild(i),e.className="CodeMirror-foldmarker"}return e}function r(n,o,e){if(o&&void 0!==o[e])return o[e];var r=n.options.foldOptions;return r&&void 0!==r[e]?r[e]:i[e]}n.newFoldFunction=function(n,e){return function(r,i){o(r,i,{rangeFinder:n,widget:e})}},n.defineExtension("foldCode",function(n,e,r){o(this,n,e,r)}),n.defineExtension("isFolded",function(n){for(var o=this.findMarksAt(n),e=0;e<o.length;++e)if(o[e].__isFold)return!0}),n.commands.toggleFold=function(n){n.foldCode(n.getCursor())},n.commands.fold=function(n){n.foldCode(n.getCursor(),null,"fold")},n.commands.unfold=function(n){n.foldCode(n.getCursor(),null,"unfold")},n.commands.foldAll=function(o){o.operation(function(){for(var e=o.firstLine(),r=o.lastLine();e<=r;e++)o.foldCode(n.Pos(e,0),null,"fold")})},n.commands.unfoldAll=function(o){o.operation(function(){for(var e=o.firstLine(),r=o.lastLine();e<=r;e++)o.foldCode(n.Pos(e,0),null,"unfold")})},n.registerHelper("fold","combine",function(){var n=Array.prototype.slice.call(arguments,0);return function(o,e){for(var r=0;r<n.length;++r){var i=n[r](o,e);if(i)return i}}}),n.registerHelper("fold","auto",function(n,o){for(var e=n.getHelpers(o,"fold"),r=0;r<e.length;r++){var i=e[r](n,o);if(i)return i}});var i={rangeFinder:n.fold.auto,widget:"↔",minFoldSize:0,scanUp:!1};n.defineOption("foldOptions",null),n.defineExtension("foldOption",function(n,o){return r(this,n,o)})});
1
+ !function(n){"object"==typeof exports&&"object"==typeof module?n(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],n):n(CodeMirror)}(function(n){"use strict";function o(o,i,t,l){function f(n){var e=d(o,i);if(!e||e.to.line-e.from.line<u)return null;for(var r=o.findMarksAt(e.from),t=0;t<r.length;++t)if(r[t].__isFold&&"fold"!==l){if(!n)return null;e.cleared=!0,r[t].clear()}return e}if(t&&t.call){var d=t;t=null}else var d=r(o,t,"rangeFinder");"number"==typeof i&&(i=n.Pos(i,0));var u=r(o,t,"minFoldSize"),a=f(!0);if(r(o,t,"scanUp"))for(;!a&&i.line>o.firstLine();)i=n.Pos(i.line-1,0),a=f(!1);if(a&&!a.cleared&&"unfold"!==l){var c=e(o,t);n.on(c,"mousedown",function(o){s.clear(),n.e_preventDefault(o)});var s=o.markText(a.from,a.to,{replacedWith:c,clearOnEnter:r(o,t,"clearOnEnter"),__isFold:!0});s.on("clear",function(e,r){n.signal(o,"unfold",o,e,r)}),n.signal(o,"fold",o,a.from,a.to)}}function e(n,o){var e=r(n,o,"widget");if("string"==typeof e){var i=document.createTextNode(e);e=document.createElement("span"),e.appendChild(i),e.className="CodeMirror-foldmarker"}return e}function r(n,o,e){if(o&&void 0!==o[e])return o[e];var r=n.options.foldOptions;return r&&void 0!==r[e]?r[e]:i[e]}n.newFoldFunction=function(n,e){return function(r,i){o(r,i,{rangeFinder:n,widget:e})}},n.defineExtension("foldCode",function(n,e,r){o(this,n,e,r)}),n.defineExtension("isFolded",function(n){for(var o=this.findMarksAt(n),e=0;e<o.length;++e)if(o[e].__isFold)return!0}),n.commands.toggleFold=function(n){n.foldCode(n.getCursor())},n.commands.fold=function(n){n.foldCode(n.getCursor(),null,"fold")},n.commands.unfold=function(n){n.foldCode(n.getCursor(),null,"unfold")},n.commands.foldAll=function(o){o.operation(function(){for(var e=o.firstLine(),r=o.lastLine();e<=r;e++)o.foldCode(n.Pos(e,0),null,"fold")})},n.commands.unfoldAll=function(o){o.operation(function(){for(var e=o.firstLine(),r=o.lastLine();e<=r;e++)o.foldCode(n.Pos(e,0),null,"unfold")})},n.registerHelper("fold","combine",function(){var n=Array.prototype.slice.call(arguments,0);return function(o,e){for(var r=0;r<n.length;++r){var i=n[r](o,e);if(i)return i}}}),n.registerHelper("fold","auto",function(n,o){for(var e=n.getHelpers(o,"fold"),r=0;r<e.length;r++){var i=e[r](n,o);if(i)return i}});var i={rangeFinder:n.fold.auto,widget:"↔",minFoldSize:0,scanUp:!1,clearOnEnter:!0};n.defineOption("foldOptions",null),n.defineExtension("foldOption",function(n,o){return r(this,n,o)})});
lib/codemirror/addon/fold/foldgutter.js CHANGED
@@ -20,7 +20,7 @@
20
  cm.off("viewportChange", onViewportChange);
21
  cm.off("fold", onFold);
22
  cm.off("unfold", onFold);
23
- cm.off("swapDoc", updateInViewport);
24
  }
25
  if (val) {
26
  cm.state.foldGutter = new State(parseOptions(val));
@@ -30,7 +30,7 @@
30
  cm.on("viewportChange", onViewportChange);
31
  cm.on("fold", onFold);
32
  cm.on("unfold", onFold);
33
- cm.on("swapDoc", updateInViewport);
34
  }
35
  });
36
 
@@ -50,7 +50,7 @@
50
  }
51
 
52
  function isFolded(cm, line) {
53
- var marks = cm.findMarksAt(Pos(line));
54
  for (var i = 0; i < marks.length; ++i)
55
  if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
56
  }
20
  cm.off("viewportChange", onViewportChange);
21
  cm.off("fold", onFold);
22
  cm.off("unfold", onFold);
23
+ cm.off("swapDoc", onChange);
24
  }
25
  if (val) {
26
  cm.state.foldGutter = new State(parseOptions(val));
30
  cm.on("viewportChange", onViewportChange);
31
  cm.on("fold", onFold);
32
  cm.on("unfold", onFold);
33
+ cm.on("swapDoc", onChange);
34
  }
35
  });
36
 
50
  }
51
 
52
  function isFolded(cm, line) {
53
+ var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
54
  for (var i = 0; i < marks.length; ++i)
55
  if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
56
  }
lib/codemirror/addon/fold/foldgutter.min.js CHANGED
@@ -1 +1 @@
1
- !function(o){"object"==typeof exports&&"object"==typeof module?o(require("../../lib/codemirror"),require("./foldcode")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./foldcode"],o):o(CodeMirror)}(function(o){"use strict";function t(o){this.options=o,this.from=this.to=0}function e(o){return o===!0&&(o={}),null==o.gutter&&(o.gutter="CodeMirror-foldgutter"),null==o.indicatorOpen&&(o.indicatorOpen="CodeMirror-foldgutter-open"),null==o.indicatorFolded&&(o.indicatorFolded="CodeMirror-foldgutter-folded"),o}function r(o,t){for(var e=o.findMarksAt(c(t)),r=0;r<e.length;++r)if(e[r].__isFold&&e[r].find().from.line==t)return e[r]}function n(o){if("string"==typeof o){var t=document.createElement("div");return t.className=o+" CodeMirror-guttermarker-subtle",t}return o.cloneNode(!0)}function i(o,t,e){var i=o.state.foldGutter.options,f=t,d=o.foldOption(i,"minFoldSize"),a=o.foldOption(i,"rangeFinder");o.eachLine(t,e,function(t){var e=null;if(r(o,f))e=n(i.indicatorFolded);else{var u=c(f,0),l=a&&a(o,u);l&&l.to.line-l.from.line>=d&&(e=n(i.indicatorOpen))}o.setGutterMarker(t,i.gutter,e),++f})}function f(o){var t=o.getViewport(),e=o.state.foldGutter;e&&(o.operation(function(){i(o,t.from,t.to)}),e.from=t.from,e.to=t.to)}function d(o,t,e){var n=o.state.foldGutter;if(n){var i=n.options;if(e==i.gutter){var f=r(o,t);f?f.clear():o.foldCode(c(t,0),i.rangeFinder)}}}function a(o){var t=o.state.foldGutter;if(t){var e=t.options;t.from=t.to=0,clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout(function(){f(o)},e.foldOnChangeTimeSpan||600)}}function u(o){var t=o.state.foldGutter;if(t){var e=t.options;clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout(function(){var e=o.getViewport();t.from==t.to||e.from-t.to>20||t.from-e.to>20?f(o):o.operation(function(){e.from<t.from&&(i(o,e.from,t.from),t.from=e.from),e.to>t.to&&(i(o,t.to,e.to),t.to=e.to)})},e.updateViewportTimeSpan||400)}}function l(o,t){var e=o.state.foldGutter;if(e){var r=t.line;r>=e.from&&r<e.to&&i(o,r,r+1)}}o.defineOption("foldGutter",!1,function(r,n,i){i&&i!=o.Init&&(r.clearGutter(r.state.foldGutter.options.gutter),r.state.foldGutter=null,r.off("gutterClick",d),r.off("change",a),r.off("viewportChange",u),r.off("fold",l),r.off("unfold",l),r.off("swapDoc",f)),n&&(r.state.foldGutter=new t(e(n)),f(r),r.on("gutterClick",d),r.on("change",a),r.on("viewportChange",u),r.on("fold",l),r.on("unfold",l),r.on("swapDoc",f))});var c=o.Pos});
1
+ !function(o){"object"==typeof exports&&"object"==typeof module?o(require("../../lib/codemirror"),require("./foldcode")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./foldcode"],o):o(CodeMirror)}(function(o){"use strict";function t(o){this.options=o,this.from=this.to=0}function e(o){return o===!0&&(o={}),null==o.gutter&&(o.gutter="CodeMirror-foldgutter"),null==o.indicatorOpen&&(o.indicatorOpen="CodeMirror-foldgutter-open"),null==o.indicatorFolded&&(o.indicatorFolded="CodeMirror-foldgutter-folded"),o}function r(o,t){for(var e=o.findMarks(c(t,0),c(t+1,0)),r=0;r<e.length;++r)if(e[r].__isFold&&e[r].find().from.line==t)return e[r]}function n(o){if("string"==typeof o){var t=document.createElement("div");return t.className=o+" CodeMirror-guttermarker-subtle",t}return o.cloneNode(!0)}function i(o,t,e){var i=o.state.foldGutter.options,f=t,d=o.foldOption(i,"minFoldSize"),a=o.foldOption(i,"rangeFinder");o.eachLine(t,e,function(t){var e=null;if(r(o,f))e=n(i.indicatorFolded);else{var u=c(f,0),l=a&&a(o,u);l&&l.to.line-l.from.line>=d&&(e=n(i.indicatorOpen))}o.setGutterMarker(t,i.gutter,e),++f})}function f(o){var t=o.getViewport(),e=o.state.foldGutter;e&&(o.operation(function(){i(o,t.from,t.to)}),e.from=t.from,e.to=t.to)}function d(o,t,e){var n=o.state.foldGutter;if(n){var i=n.options;if(e==i.gutter){var f=r(o,t);f?f.clear():o.foldCode(c(t,0),i.rangeFinder)}}}function a(o){var t=o.state.foldGutter;if(t){var e=t.options;t.from=t.to=0,clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout(function(){f(o)},e.foldOnChangeTimeSpan||600)}}function u(o){var t=o.state.foldGutter;if(t){var e=t.options;clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout(function(){var e=o.getViewport();t.from==t.to||e.from-t.to>20||t.from-e.to>20?f(o):o.operation(function(){e.from<t.from&&(i(o,e.from,t.from),t.from=e.from),e.to>t.to&&(i(o,t.to,e.to),t.to=e.to)})},e.updateViewportTimeSpan||400)}}function l(o,t){var e=o.state.foldGutter;if(e){var r=t.line;r>=e.from&&r<e.to&&i(o,r,r+1)}}o.defineOption("foldGutter",!1,function(r,n,i){i&&i!=o.Init&&(r.clearGutter(r.state.foldGutter.options.gutter),r.state.foldGutter=null,r.off("gutterClick",d),r.off("change",a),r.off("viewportChange",u),r.off("fold",l),r.off("unfold",l),r.off("swapDoc",a)),n&&(r.state.foldGutter=new t(e(n)),f(r),r.on("gutterClick",d),r.on("change",a),r.on("viewportChange",u),r.on("fold",l),r.on("unfold",l),r.on("swapDoc",a))});var c=o.Pos});
lib/codemirror/addon/fold/xml-fold.js CHANGED
@@ -21,8 +21,8 @@
21
  function Iter(cm, line, ch, range) {
22
  this.line = line; this.ch = ch;
23
  this.cm = cm; this.text = cm.getLine(line);
24
- this.min = range ? range.from : cm.firstLine();
25
- this.max = range ? range.to - 1 : cm.lastLine();
26
  }
27
 
28
  function tagAt(iter, ch) {
@@ -140,9 +140,9 @@
140
  var openTag = toNextTag(iter), end;
141
  if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
142
  if (!openTag[1] && end != "selfClose") {
143
- var start = Pos(iter.line, iter.ch);
144
- var close = findMatchingClose(iter, openTag[2]);
145
- return close && {from: start, to: close.from};
146
  }
147
  }
148
  });
21
  function Iter(cm, line, ch, range) {
22
  this.line = line; this.ch = ch;
23
  this.cm = cm; this.text = cm.getLine(line);
24
+ this.min = range ? Math.max(range.from, cm.firstLine()) : cm.firstLine();
25
+ this.max = range ? Math.min(range.to - 1, cm.lastLine()) : cm.lastLine();
26
  }
27
 
28
  function tagAt(iter, ch) {
140
  var openTag = toNextTag(iter), end;
141
  if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
142
  if (!openTag[1] && end != "selfClose") {
143
+ var startPos = Pos(iter.line, iter.ch);
144
+ var endPos = findMatchingClose(iter, openTag[2]);
145
+ return endPos && {from: startPos, to: endPos.from};
146
  }
147
  }
148
  });
lib/codemirror/addon/fold/xml-fold.min.js CHANGED
@@ -1 +1 @@
1
- !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";function n(e,n){return e.line-n.line||e.ch-n.ch}function t(e,n,t,i){this.line=n,this.ch=t,this.cm=e,this.text=e.getLine(n),this.min=i?i.from:e.firstLine(),this.max=i?i.to-1:e.lastLine()}function i(e,n){var t=e.cm.getTokenTypeAt(h(e.line,n));return t&&/\btag\b/.test(t)}function r(e){if(!(e.line>=e.max))return e.ch=0,e.text=e.cm.getLine(++e.line),!0}function f(e){if(!(e.line<=e.min))return e.text=e.cm.getLine(--e.line),e.ch=e.text.length,!0}function o(e){for(;;){var n=e.text.indexOf(">",e.ch);if(n==-1){if(r(e))continue;return}{if(i(e,n+1)){var t=e.text.lastIndexOf("/",n),f=t>-1&&!/\S/.test(e.text.slice(t+1,n));return e.ch=n+1,f?"selfClose":"regular"}e.ch=n+1}}}function u(e){for(;;){var n=e.ch?e.text.lastIndexOf("<",e.ch-1):-1;if(n==-1){if(f(e))continue;return}if(i(e,n+1)){v.lastIndex=n,e.ch=n;var t=v.exec(e.text);if(t&&t.index==n)return t}else e.ch=n}}function c(e){for(;;){v.lastIndex=e.ch;var n=v.exec(e.text);if(!n){if(r(e))continue;return}{if(i(e,n.index+1))return e.ch=n.index+n[0].length,n;e.ch=n.index+1}}}function l(e){for(;;){var n=e.ch?e.text.lastIndexOf(">",e.ch-1):-1;if(n==-1){if(f(e))continue;return}{if(i(e,n+1)){var t=e.text.lastIndexOf("/",n),r=t>-1&&!/\S/.test(e.text.slice(t+1,n));return e.ch=n+1,r?"selfClose":"regular"}e.ch=n}}}function a(e,n){for(var t=[];;){var i,r=c(e),f=e.line,u=e.ch-(r?r[0].length:0);if(!r||!(i=o(e)))return;if("selfClose"!=i)if(r[1]){for(var l=t.length-1;l>=0;--l)if(t[l]==r[2]){t.length=l;break}if(l<0&&(!n||n==r[2]))return{tag:r[2],from:h(f,u),to:h(e.line,e.ch)}}else t.push(r[2])}}function s(e,n){for(var t=[];;){var i=l(e);if(!i)return;if("selfClose"!=i){var r=e.line,f=e.ch,o=u(e);if(!o)return;if(o[1])t.push(o[2]);else{for(var c=t.length-1;c>=0;--c)if(t[c]==o[2]){t.length=c;break}if(c<0&&(!n||n==o[2]))return{tag:o[2],from:h(e.line,e.ch),to:h(r,f)}}}else u(e)}}var h=e.Pos,x="A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",g=x+"-:.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",v=new RegExp("<(/?)(["+x+"]["+g+"]*)","g");e.registerHelper("fold","xml",function(e,n){for(var i=new t(e,n.line,0);;){var r,f=c(i);if(!f||i.line!=n.line||!(r=o(i)))return;if(!f[1]&&"selfClose"!=r){var n=h(i.line,i.ch),u=a(i,f[2]);return u&&{from:n,to:u.from}}}}),e.findMatchingTag=function(e,i,r){var f=new t(e,i.line,i.ch,r);if(f.text.indexOf(">")!=-1||f.text.indexOf("<")!=-1){var c=o(f),l=c&&h(f.line,f.ch),x=c&&u(f);if(c&&x&&!(n(f,i)>0)){var g={from:h(f.line,f.ch),to:l,tag:x[2]};return"selfClose"==c?{open:g,close:null,at:"open"}:x[1]?{open:s(f,x[2]),close:g,at:"close"}:(f=new t(e,l.line,l.ch,r),{open:g,close:a(f,x[2]),at:"open"})}}},e.findEnclosingTag=function(e,n,i){for(var r=new t(e,n.line,n.ch,i);;){var f=s(r);if(!f)break;var o=new t(e,n.line,n.ch,i),u=a(o,f.tag);if(u)return{open:f,close:u}}},e.scanForClosingTag=function(e,n,i,r){var f=new t(e,n.line,n.ch,r?{from:0,to:r}:null);return a(f,i)}});
1
+ !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";function n(e,n){return e.line-n.line||e.ch-n.ch}function t(e,n,t,i){this.line=n,this.ch=t,this.cm=e,this.text=e.getLine(n),this.min=i?Math.max(i.from,e.firstLine()):e.firstLine(),this.max=i?Math.min(i.to-1,e.lastLine()):e.lastLine()}function i(e,n){var t=e.cm.getTokenTypeAt(h(e.line,n));return t&&/\btag\b/.test(t)}function r(e){if(!(e.line>=e.max))return e.ch=0,e.text=e.cm.getLine(++e.line),!0}function f(e){if(!(e.line<=e.min))return e.text=e.cm.getLine(--e.line),e.ch=e.text.length,!0}function o(e){for(;;){var n=e.text.indexOf(">",e.ch);if(n==-1){if(r(e))continue;return}{if(i(e,n+1)){var t=e.text.lastIndexOf("/",n),f=t>-1&&!/\S/.test(e.text.slice(t+1,n));return e.ch=n+1,f?"selfClose":"regular"}e.ch=n+1}}}function u(e){for(;;){var n=e.ch?e.text.lastIndexOf("<",e.ch-1):-1;if(n==-1){if(f(e))continue;return}if(i(e,n+1)){v.lastIndex=n,e.ch=n;var t=v.exec(e.text);if(t&&t.index==n)return t}else e.ch=n}}function l(e){for(;;){v.lastIndex=e.ch;var n=v.exec(e.text);if(!n){if(r(e))continue;return}{if(i(e,n.index+1))return e.ch=n.index+n[0].length,n;e.ch=n.index+1}}}function c(e){for(;;){var n=e.ch?e.text.lastIndexOf(">",e.ch-1):-1;if(n==-1){if(f(e))continue;return}{if(i(e,n+1)){var t=e.text.lastIndexOf("/",n),r=t>-1&&!/\S/.test(e.text.slice(t+1,n));return e.ch=n+1,r?"selfClose":"regular"}e.ch=n}}}function a(e,n){for(var t=[];;){var i,r=l(e),f=e.line,u=e.ch-(r?r[0].length:0);if(!r||!(i=o(e)))return;if("selfClose"!=i)if(r[1]){for(var c=t.length-1;c>=0;--c)if(t[c]==r[2]){t.length=c;break}if(c<0&&(!n||n==r[2]))return{tag:r[2],from:h(f,u),to:h(e.line,e.ch)}}else t.push(r[2])}}function s(e,n){for(var t=[];;){var i=c(e);if(!i)return;if("selfClose"!=i){var r=e.line,f=e.ch,o=u(e);if(!o)return;if(o[1])t.push(o[2]);else{for(var l=t.length-1;l>=0;--l)if(t[l]==o[2]){t.length=l;break}if(l<0&&(!n||n==o[2]))return{tag:o[2],from:h(e.line,e.ch),to:h(r,f)}}}else u(e)}}var h=e.Pos,x="A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",g=x+"-:.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",v=new RegExp("<(/?)(["+x+"]["+g+"]*)","g");e.registerHelper("fold","xml",function(e,n){for(var i=new t(e,n.line,0);;){var r,f=l(i);if(!f||i.line!=n.line||!(r=o(i)))return;if(!f[1]&&"selfClose"!=r){var u=h(i.line,i.ch),c=a(i,f[2]);return c&&{from:u,to:c.from}}}}),e.findMatchingTag=function(e,i,r){var f=new t(e,i.line,i.ch,r);if(f.text.indexOf(">")!=-1||f.text.indexOf("<")!=-1){var l=o(f),c=l&&h(f.line,f.ch),x=l&&u(f);if(l&&x&&!(n(f,i)>0)){var g={from:h(f.line,f.ch),to:c,tag:x[2]};return"selfClose"==l?{open:g,close:null,at:"open"}:x[1]?{open:s(f,x[2]),close:g,at:"close"}:(f=new t(e,c.line,c.ch,r),{open:g,close:a(f,x[2]),at:"open"})}}},e.findEnclosingTag=function(e,n,i){for(var r=new t(e,n.line,n.ch,i);;){var f=s(r);if(!f)break;var o=new t(e,n.line,n.ch,i),u=a(o,f.tag);if(u)return{open:f,close:u}}},e.scanForClosingTag=function(e,n,i,r){var f=new t(e,n.line,n.ch,r?{from:0,to:r}:null);return a(f,i)}});
lib/codemirror/addon/hint/javascript-hint.js CHANGED
@@ -97,6 +97,15 @@
97
  var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
98
  "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
99
 
 
 
 
 
 
 
 
 
 
100
  function getCompletions(token, context, keywords, options) {
101
  var found = [], start = token.string, global = options && options.globalScope || window;
102
  function maybeAdd(str) {
@@ -106,7 +115,7 @@
106
  if (typeof obj == "string") forEach(stringProps, maybeAdd);
107
  else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
108
  else if (obj instanceof Function) forEach(funcProps, maybeAdd);
109
- for (var name in obj) maybeAdd(name);
110
  }
111
 
112
  if (context && context.length) {
97
  var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
98
  "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
99
 
100
+ function forAllProps(obj, callback) {
101
+ if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {
102
+ for (var name in obj) callback(name)
103
+ } else {
104
+ for (var o = obj; o; o = Object.getPrototypeOf(o))
105
+ Object.getOwnPropertyNames(o).forEach(callback)
106
+ }
107
+ }
108
+
109
  function getCompletions(token, context, keywords, options) {
110
  var found = [], start = token.string, global = options && options.globalScope || window;
111
  function maybeAdd(str) {
115
  if (typeof obj == "string") forEach(stringProps, maybeAdd);
116
  else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
117
  else if (obj instanceof Function) forEach(funcProps, maybeAdd);
118
+ forAllProps(obj, maybeAdd)
119
  }
120
 
121
  if (context && context.length) {
lib/codemirror/addon/hint/javascript-hint.min.js CHANGED
@@ -1 +1 @@
1
- !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],t):t(CodeMirror)}(function(t){function e(t,e){for(var r=0,n=t.length;r<n;++r)e(t[r])}function r(t,e){if(!Array.prototype.indexOf){for(var r=t.length;r--;)if(t[r]===e)return!0;return!1}return t.indexOf(e)!=-1}function n(e,r,n,i){var o=e.getCursor(),s=n(e,o);if(!/\b(?:string|comment)\b/.test(s.type)){s.state=t.innerMode(e.getMode(),s.state).state,/^[\w$_]*$/.test(s.string)?s.end>o.ch&&(s.end=o.ch,s.string=s.string.slice(0,o.ch-s.start)):s={start:o.ch,end:o.ch,string:"",state:s.state,type:"."==s.string?"property":null};for(var f=s;"property"==f.type;){if(f=n(e,l(o.line,f.start)),"."!=f.string)return;if(f=n(e,l(o.line,f.start)),!c)var c=[];c.push(f)}return{list:a(s,c,r,i),from:l(o.line,s.start),to:l(o.line,s.end)}}}function i(t,e){return n(t,u,function(t,e){return t.getTokenAt(e)},e)}function o(t,e){var r=t.getTokenAt(e);return e.ch==r.start+1&&"."==r.string.charAt(0)?(r.end=r.start,r.string=".",r.type="property"):/^\.[\w$_]*$/.test(r.string)&&(r.type="property",r.start++,r.string=r.string.replace(/\./,"")),r}function s(t,e){return n(t,d,o,e)}function a(t,n,i,o){function s(t){0!=t.lastIndexOf(u,0)||r(l,t)||l.push(t)}function a(t){"string"==typeof t?e(f,s):t instanceof Array?e(c,s):t instanceof Function&&e(p,s);for(var r in t)s(r)}var l=[],u=t.string,d=o&&o.globalScope||window;if(n&&n.length){var g,h=n.pop();for(h.type&&0===h.type.indexOf("variable")?(o&&o.additionalContext&&(g=o.additionalContext[h.string]),o&&o.useGlobalScope===!1||(g=g||d[h.string])):"string"==h.type?g="":"atom"==h.type?g=1:"function"==h.type&&(null==d.jQuery||"$"!=h.string&&"jQuery"!=h.string||"function"!=typeof d.jQuery?null!=d._&&"_"==h.string&&"function"==typeof d._&&(g=d._()):g=d.jQuery());null!=g&&n.length;)g=g[n.pop().string];null!=g&&a(g)}else{for(var y=t.state.localVars;y;y=y.next)s(y.name);for(var y=t.state.globalVars;y;y=y.next)s(y.name);o&&o.useGlobalScope===!1||a(d),e(i,s)}return l}var l=t.Pos;t.registerHelper("hint","javascript",i),t.registerHelper("hint","coffeescript",s);var f="charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight toUpperCase toLowerCase split concat match replace search".split(" "),c="length concat join splice push pop shift unshift slice reverse sort indexOf lastIndexOf every some filter forEach map reduce reduceRight ".split(" "),p="prototype apply call bind".split(" "),u="break case catch continue debugger default delete do else false finally for function if in instanceof new null return switch throw true try typeof var void while with".split(" "),d="and break catch class continue delete do else extends false finally for if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes".split(" ")});
1
+ !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],t):t(CodeMirror)}(function(t){function e(t,e){for(var r=0,n=t.length;r<n;++r)e(t[r])}function r(t,e){if(!Array.prototype.indexOf){for(var r=t.length;r--;)if(t[r]===e)return!0;return!1}return t.indexOf(e)!=-1}function n(e,r,n,i){var o=e.getCursor(),s=n(e,o);if(!/\b(?:string|comment)\b/.test(s.type)){s.state=t.innerMode(e.getMode(),s.state).state,/^[\w$_]*$/.test(s.string)?s.end>o.ch&&(s.end=o.ch,s.string=s.string.slice(0,o.ch-s.start)):s={start:o.ch,end:o.ch,string:"",state:s.state,type:"."==s.string?"property":null};for(var a=s;"property"==a.type;){if(a=n(e,l(o.line,a.start)),"."!=a.string)return;if(a=n(e,l(o.line,a.start)),!c)var c=[];c.push(a)}return{list:f(s,c,r,i),from:l(o.line,s.start),to:l(o.line,s.end)}}}function i(t,e){return n(t,g,function(t,e){return t.getTokenAt(e)},e)}function o(t,e){var r=t.getTokenAt(e);return e.ch==r.start+1&&"."==r.string.charAt(0)?(r.end=r.start,r.string=".",r.type="property"):/^\.[\w$_]*$/.test(r.string)&&(r.type="property",r.start++,r.string=r.string.replace(/\./,"")),r}function s(t,e){return n(t,d,o,e)}function a(t,e){if(Object.getOwnPropertyNames&&Object.getPrototypeOf)for(var r=t;r;r=Object.getPrototypeOf(r))Object.getOwnPropertyNames(r).forEach(e);else for(var n in t)e(n)}function f(t,n,i,o){function s(t){0!=t.lastIndexOf(g,0)||r(l,t)||l.push(t)}function f(t){"string"==typeof t?e(c,s):t instanceof Array?e(p,s):t instanceof Function&&e(u,s),a(t,s)}var l=[],g=t.string,d=o&&o.globalScope||window;if(n&&n.length){var y,h=n.pop();for(h.type&&0===h.type.indexOf("variable")?(o&&o.additionalContext&&(y=o.additionalContext[h.string]),o&&o.useGlobalScope===!1||(y=y||d[h.string])):"string"==h.type?y="":"atom"==h.type?y=1:"function"==h.type&&(null==d.jQuery||"$"!=h.string&&"jQuery"!=h.string||"function"!=typeof d.jQuery?null!=d._&&"_"==h.string&&"function"==typeof d._&&(y=d._()):y=d.jQuery());null!=y&&n.length;)y=y[n.pop().string];null!=y&&f(y)}else{for(var b=t.state.localVars;b;b=b.next)s(b.name);for(var b=t.state.globalVars;b;b=b.next)s(b.name);o&&o.useGlobalScope===!1||f(d),e(i,s)}return l}var l=t.Pos;t.registerHelper("hint","javascript",i),t.registerHelper("hint","coffeescript",s);var c="charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight toUpperCase toLowerCase split concat match replace search".split(" "),p="length concat join splice push pop shift unshift slice reverse sort indexOf lastIndexOf every some filter forEach map reduce reduceRight ".split(" "),u="prototype apply call bind".split(" "),g="break case catch continue debugger default delete do else false finally for function if in instanceof new null return switch throw true try typeof var void while with".split(" "),d="and break catch class continue delete do else extends false finally for if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes".split(" ")});
lib/codemirror/addon/hint/show-hint.css CHANGED
@@ -25,8 +25,6 @@
25
  margin: 0;
26
  padding: 0 4px;
27
  border-radius: 2px;
28
- max-width: 19em;
29
- overflow: hidden;
30
  white-space: pre;
31
  color: black;
32
  cursor: pointer;
25
  margin: 0;
26
  padding: 0 4px;
27
  border-radius: 2px;
 
 
28
  white-space: pre;
29
  color: black;
30
  cursor: pointer;
lib/codemirror/addon/hint/show-hint.js CHANGED
@@ -108,24 +108,22 @@
108
  },
109
 
110
  update: function(first) {
111
- if (this.tick == null) return;
112
- if (!this.options.hint.async) {
113
- this.finishUpdate(this.options.hint(this.cm, this.options), first);
114
- } else {
115
- var myTick = ++this.tick, self = this;
116
- this.options.hint(this.cm, function(data) {
117
- if (self.tick == myTick) self.finishUpdate(data, first);
118
- }, this.options);
119
- }
120
  },
121
 
122
  finishUpdate: function(data, first) {
123
  if (this.data) CodeMirror.signal(this.data, "update");
124
- if (data && this.data && CodeMirror.cmpPos(data.from, this.data.from)) data = null;
125
- this.data = data;
126
 
127
  var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
128
  if (this.widget) this.widget.close();
 
 
 
 
129
  if (data && data.list.length) {
130
  if (picked && data.list.length == 1) {
131
  this.pick(data, 0);
@@ -137,6 +135,11 @@
137
  }
138
  };
139
 
 
 
 
 
 
140
  function parseOptions(cm, pos, options) {
141
  var editor = cm.options.hintOptions;
142
  var out = {};
@@ -226,6 +229,9 @@
226
  var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
227
  (completion.options.container || document.body).appendChild(hints);
228
  var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
 
 
 
229
  if (overlapY > 0) {
230
  var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
231
  if (curTop - height > 0) { // Fits above cursor
@@ -250,6 +256,8 @@
250
  }
251
  hints.style.left = (left = pos.left - overlapX) + "px";
252
  }
 
 
253
 
254
  cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
255
  moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
@@ -267,7 +275,6 @@
267
  cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
268
  }
269
 
270
- var startScroll = cm.getScrollInfo();
271
  cm.on("scroll", this.onScroll = function() {
272
  var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
273
  var newTop = top + startScroll.top - curScroll.top;
@@ -355,40 +362,31 @@
355
  return result
356
  }
357
 
 
 
 
 
 
 
 
 
 
 
358
  function resolveAutoHints(cm, pos) {
359
  var helpers = cm.getHelpers(pos, "hint"), words
360
  if (helpers.length) {
361
- var async = false, resolved
362
- for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true
363
- if (async) {
364
- resolved = function(cm, callback, options) {
365
- var app = applicableHelpers(cm, helpers)
366
- function run(i, result) {
367
- if (i == app.length) return callback(null)
368
- var helper = app[i]
369
- if (helper.async) {
370
- helper(cm, function(result) {
371
- if (result) callback(result)
372
- else run(i + 1)
373
- }, options)
374
- } else {
375
- var result = helper(cm, options)
376
- if (result) callback(result)
377
- else run(i + 1)
378
- }
379
- }
380
- run(0)
381
- }
382
- resolved.async = true
383
- } else {
384
- resolved = function(cm, options) {
385
- var app = applicableHelpers(cm, helpers)
386
- for (var i = 0; i < app.length; i++) {
387
- var cur = app[i](cm, options)
388
- if (cur && cur.list.length) return cur
389
- }
390
  }
 
391
  }
 
392
  resolved.supportsSelection = true
393
  return resolved
394
  } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
108
  },
109
 
110
  update: function(first) {
111
+ if (this.tick == null) return
112
+ var self = this, myTick = ++this.tick
113
+ fetchHints(this.options.hint, this.cm, this.options, function(data) {
114
+ if (self.tick == myTick) self.finishUpdate(data, first)
115
+ })
 
 
 
 
116
  },
117
 
118
  finishUpdate: function(data, first) {
119
  if (this.data) CodeMirror.signal(this.data, "update");
 
 
120
 
121
  var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
122
  if (this.widget) this.widget.close();
123
+
124
+ if (data && this.data && isNewCompletion(this.data, data)) return;
125
+ this.data = data;
126
+
127
  if (data && data.list.length) {
128
  if (picked && data.list.length == 1) {
129
  this.pick(data, 0);
135
  }
136
  };
137
 
138
+ function isNewCompletion(old, nw) {
139
+ var moved = CodeMirror.cmpPos(nw.from, old.from)
140
+ return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
141
+ }
142
+
143
  function parseOptions(cm, pos, options) {
144
  var editor = cm.options.hintOptions;
145
  var out = {};
229
  var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
230
  (completion.options.container || document.body).appendChild(hints);
231
  var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
232
+ var scrolls = hints.scrollHeight > hints.clientHeight + 1
233
+ var startScroll = cm.getScrollInfo();
234
+
235
  if (overlapY > 0) {
236
  var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
237
  if (curTop - height > 0) { // Fits above cursor
256
  }
257
  hints.style.left = (left = pos.left - overlapX) + "px";
258
  }
259
+ if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
260
+ node.style.paddingRight = cm.display.nativeBarWidth + "px"
261
 
262
  cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
263
  moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
275
  cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
276
  }
277
 
 
278
  cm.on("scroll", this.onScroll = function() {
279
  var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
280
  var newTop = top + startScroll.top - curScroll.top;
362
  return result
363
  }
364
 
365
+ function fetchHints(hint, cm, options, callback) {
366
+ if (hint.async) {
367
+ hint(cm, callback, options)
368
+ } else {
369
+ var result = hint(cm, options)
370
+ if (result && result.then) result.then(callback)
371
+ else callback(result)
372
+ }
373
+ }
374
+
375
  function resolveAutoHints(cm, pos) {
376
  var helpers = cm.getHelpers(pos, "hint"), words
377
  if (helpers.length) {
378
+ var resolved = function(cm, callback, options) {
379
+ var app = applicableHelpers(cm, helpers);
380
+ function run(i) {
381
+ if (i == app.length) return callback(null)
382
+ fetchHints(app[i], cm, options, function(result) {
383
+ if (result && result.list.length > 0) callback(result)
384
+ else run(i + 1)
385
+ })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  }
387
+ run(0)
388
  }
389
+ resolved.async = true
390
  resolved.supportsSelection = true
391
  return resolved
392
  } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
lib/codemirror/addon/hint/show-hint.min.js CHANGED
@@ -1 +1 @@
1
- !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],t):t(CodeMirror)}(function(t){"use strict";function i(t,i){this.cm=t,this.options=i,this.widget=null,this.debounce=0,this.tick=0,this.startPos=this.cm.getCursor("start"),this.startLen=this.cm.getLine(this.startPos.line).length-this.cm.getSelection().length;var e=this;t.on("cursorActivity",this.activityFunc=function(){e.cursorActivity()})}function e(t,i,e){var n=t.options.hintOptions,o={};for(var s in d)o[s]=d[s];if(n)for(var s in n)void 0!==n[s]&&(o[s]=n[s]);if(e)for(var s in e)void 0!==e[s]&&(o[s]=e[s]);return o.hint.resolve&&(o.hint=o.hint.resolve(t,i)),o}function n(t){return"string"==typeof t?t:t.text}function o(t,i){function e(t,e){var o;o="string"!=typeof e?function(t){return e(t,i)}:n.hasOwnProperty(e)?n[e]:e,s[t]=o}var n={Up:function(){i.moveFocus(-1)},Down:function(){i.moveFocus(1)},PageUp:function(){i.moveFocus(-i.menuSize()+1,!0)},PageDown:function(){i.moveFocus(i.menuSize()-1,!0)},Home:function(){i.setFocus(0)},End:function(){i.setFocus(i.length-1)},Enter:i.pick,Tab:i.pick,Esc:i.close},o=t.options.customKeys,s=o?{}:n;if(o)for(var c in o)o.hasOwnProperty(c)&&e(c,o[c]);var r=t.options.extraKeys;if(r)for(var c in r)r.hasOwnProperty(c)&&e(c,r[c]);return s}function s(t,i){for(;i&&i!=t;){if("LI"===i.nodeName.toUpperCase()&&i.parentNode==t)return i;i=i.parentNode}}function c(i,e){this.completion=i,this.data=e,this.picked=!1;var c=this,r=i.cm,h=this.hints=document.createElement("ul");h.className="CodeMirror-hints",this.selectedHint=e.selectedHint||0;for(var u=e.list,f=0;f<u.length;++f){var d=h.appendChild(document.createElement("li")),p=u[f],m=l+(f!=this.selectedHint?"":" "+a);null!=p.className&&(m=p.className+" "+m),d.className=m,p.render?p.render(d,e,p):d.appendChild(document.createTextNode(p.displayText||n(p))),d.hintId=f}var g=r.cursorCoords(i.options.alignWithWord?e.from:null),v=g.left,y=g.bottom,w=!0;h.style.left=v+"px",h.style.top=y+"px";var k=window.innerWidth||Math.max(document.body.offsetWidth,document.documentElement.offsetWidth),H=window.innerHeight||Math.max(document.body.offsetHeight,document.documentElement.offsetHeight);(i.options.container||document.body).appendChild(h);var C=h.getBoundingClientRect(),b=C.bottom-H;if(b>0){var A=C.bottom-C.top,x=g.top-(g.bottom-C.top);if(x-A>0)h.style.top=(y=g.top-A)+"px",w=!1;else if(A>H){h.style.height=H-5+"px",h.style.top=(y=g.bottom-C.top)+"px";var S=r.getCursor();e.from.ch!=S.ch&&(g=r.cursorCoords(S),h.style.left=(v=g.left)+"px",C=h.getBoundingClientRect())}}var T=C.right-k;if(T>0&&(C.right-C.left>k&&(h.style.width=k-5+"px",T-=C.right-C.left-k),h.style.left=(v=g.left-T)+"px"),r.addKeyMap(this.keyMap=o(i,{moveFocus:function(t,i){c.changeActive(c.selectedHint+t,i)},setFocus:function(t){c.changeActive(t)},menuSize:function(){return c.screenAmount()},length:u.length,close:function(){i.close()},pick:function(){c.pick()},data:e})),i.options.closeOnUnfocus){var M;r.on("blur",this.onBlur=function(){M=setTimeout(function(){i.close()},100)}),r.on("focus",this.onFocus=function(){clearTimeout(M)})}var F=r.getScrollInfo();return r.on("scroll",this.onScroll=function(){var t=r.getScrollInfo(),e=r.getWrapperElement().getBoundingClientRect(),n=y+F.top-t.top,o=n-(window.pageYOffset||(document.documentElement||document.body).scrollTop);return w||(o+=h.offsetHeight),o<=e.top||o>=e.bottom?i.close():(h.style.top=n+"px",void(h.style.left=v+F.left-t.left+"px"))}),t.on(h,"dblclick",function(t){var i=s(h,t.target||t.srcElement);i&&null!=i.hintId&&(c.changeActive(i.hintId),c.pick())}),t.on(h,"click",function(t){var e=s(h,t.target||t.srcElement);e&&null!=e.hintId&&(c.changeActive(e.hintId),i.options.completeOnSingleClick&&c.pick())}),t.on(h,"mousedown",function(){setTimeout(function(){r.focus()},20)}),t.signal(e,"select",u[0],h.firstChild),!0}function r(t,i){if(!t.somethingSelected())return i;for(var e=[],n=0;n<i.length;n++)i[n].supportsSelection&&e.push(i[n]);return e}function h(i,e){var n,o=i.getHelpers(e,"hint");if(o.length){for(var s,c=!1,h=0;h<o.length;h++)o[h].async&&(c=!0);return c?(s=function(t,i,e){function n(o,c){if(o==s.length)return i(null);var r=s[o];if(r.async)r(t,function(t){t?i(t):n(o+1)},e);else{var c=r(t,e);c?i(c):n(o+1)}}var s=r(t,o);n(0)},s.async=!0):s=function(t,i){for(var e=r(t,o),n=0;n<e.length;n++){var s=e[n](t,i);if(s&&s.list.length)return s}},s.supportsSelection=!0,s}return(n=i.getHelper(i.getCursor(),"hintWords"))?function(i){return t.hint.fromList(i,{words:n})}:t.hint.anyword?function(i,e){return t.hint.anyword(i,e)}:function(){}}var l="CodeMirror-hint",a="CodeMirror-hint-active";t.showHint=function(t,i,e){if(!i)return t.showHint(e);e&&e.async&&(i.async=!0);var n={hint:i};if(e)for(var o in e)n[o]=e[o];return t.showHint(n)},t.defineExtension("showHint",function(n){n=e(this,this.getCursor("start"),n);var o=this.listSelections();if(!(o.length>1)){if(this.somethingSelected()){if(!n.hint.supportsSelection)return;for(var s=0;s<o.length;s++)if(o[s].head.line!=o[s].anchor.line)return}this.state.completionActive&&this.state.completionActive.close();var c=this.state.completionActive=new i(this,n);c.options.hint&&(t.signal(this,"startCompletion",this),c.update(!0))}});var u=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},f=window.cancelAnimationFrame||clearTimeout;i.prototype={close:function(){this.active()&&(this.cm.state.completionActive=null,this.tick=null,this.cm.off("cursorActivity",this.activityFunc),this.widget&&this.data&&t.signal(this.data,"close"),this.widget&&this.widget.close(),t.signal(this.cm,"endCompletion",this.cm))},active:function(){return this.cm.state.completionActive==this},pick:function(i,e){var o=i.list[e];o.hint?o.hint(this.cm,i,o):this.cm.replaceRange(n(o),o.from||i.from,o.to||i.to,"complete"),t.signal(i,"pick",o),this.close()},cursorActivity:function(){this.debounce&&(f(this.debounce),this.debounce=0);var t=this.cm.getCursor(),i=this.cm.getLine(t.line);if(t.line!=this.startPos.line||i.length-t.ch!=this.startLen-this.startPos.ch||t.ch<this.startPos.ch||this.cm.somethingSelected()||t.ch&&this.options.closeCharacters.test(i.charAt(t.ch-1)))this.close();else{var e=this;this.debounce=u(function(){e.update()}),this.widget&&this.widget.disable()}},update:function(t){if(null!=this.tick)if(this.options.hint.async){var i=++this.tick,e=this;this.options.hint(this.cm,function(n){e.tick==i&&e.finishUpdate(n,t)},this.options)}else this.finishUpdate(this.options.hint(this.cm,this.options),t)},finishUpdate:function(i,e){this.data&&t.signal(this.data,"update"),i&&this.data&&t.cmpPos(i.from,this.data.from)&&(i=null),this.data=i;var n=this.widget&&this.widget.picked||e&&this.options.completeSingle;this.widget&&this.widget.close(),i&&i.list.length&&(n&&1==i.list.length?this.pick(i,0):(this.widget=new c(this,i),t.signal(i,"shown")))}},c.prototype={close:function(){if(this.completion.widget==this){this.completion.widget=null,this.hints.parentNode.removeChild(this.hints),this.completion.cm.removeKeyMap(this.keyMap);var t=this.completion.cm;this.completion.options.closeOnUnfocus&&(t.off("blur",this.onBlur),t.off("focus",this.onFocus)),t.off("scroll",this.onScroll)}},disable:function(){this.completion.cm.removeKeyMap(this.keyMap);var t=this;this.keyMap={Enter:function(){t.picked=!0}},this.completion.cm.addKeyMap(this.keyMap)},pick:function(){this.completion.pick(this.data,this.selectedHint)},changeActive:function(i,e){if(i>=this.data.list.length?i=e?this.data.list.length-1:0:i<0&&(i=e?0:this.data.list.length-1),this.selectedHint!=i){var n=this.hints.childNodes[this.selectedHint];n.className=n.className.replace(" "+a,""),n=this.hints.childNodes[this.selectedHint=i],n.className+=" "+a,n.offsetTop<this.hints.scrollTop?this.hints.scrollTop=n.offsetTop-3:n.offsetTop+n.offsetHeight>this.hints.scrollTop+this.hints.clientHeight&&(this.hints.scrollTop=n.offsetTop+n.offsetHeight-this.hints.clientHeight+3),t.signal(this.data,"select",this.data.list[this.selectedHint],n)}},screenAmount:function(){return Math.floor(this.hints.clientHeight/this.hints.firstChild.offsetHeight)||1}},t.registerHelper("hint","auto",{resolve:h}),t.registerHelper("hint","fromList",function(i,e){var n=i.getCursor(),o=i.getTokenAt(n),s=t.Pos(n.line,o.end);if(o.string&&/\w/.test(o.string[o.string.length-1]))var c=o.string,r=t.Pos(n.line,o.start);else var c="",r=s;for(var h=[],l=0;l<e.words.length;l++){var a=e.words[l];a.slice(0,c.length)==c&&h.push(a)}if(h.length)return{list:h,from:r,to:s}}),t.commands.autocomplete=t.showHint;var d={hint:t.hint.auto,completeSingle:!0,alignWithWord:!0,closeCharacters:/[\s()\[\]{};:>,]/,closeOnUnfocus:!0,completeOnSingleClick:!0,container:null,customKeys:null,extraKeys:null};t.defineOption("hintOptions",null)});
1
+ !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],t):t(CodeMirror)}(function(t){"use strict";function i(t,i){this.cm=t,this.options=i,this.widget=null,this.debounce=0,this.tick=0,this.startPos=this.cm.getCursor("start"),this.startLen=this.cm.getLine(this.startPos.line).length-this.cm.getSelection().length;var e=this;t.on("cursorActivity",this.activityFunc=function(){e.cursorActivity()})}function e(i,e){var n=t.cmpPos(e.from,i.from);return n>0&&i.to.ch-i.from.ch!=e.to.ch-e.from.ch}function n(t,i,e){var n=t.options.hintOptions,o={};for(var s in m)o[s]=m[s];if(n)for(var s in n)void 0!==n[s]&&(o[s]=n[s]);if(e)for(var s in e)void 0!==e[s]&&(o[s]=e[s]);return o.hint.resolve&&(o.hint=o.hint.resolve(t,i)),o}function o(t){return"string"==typeof t?t:t.text}function s(t,i){function e(t,e){var o;o="string"!=typeof e?function(t){return e(t,i)}:n.hasOwnProperty(e)?n[e]:e,s[t]=o}var n={Up:function(){i.moveFocus(-1)},Down:function(){i.moveFocus(1)},PageUp:function(){i.moveFocus(-i.menuSize()+1,!0)},PageDown:function(){i.moveFocus(i.menuSize()-1,!0)},Home:function(){i.setFocus(0)},End:function(){i.setFocus(i.length-1)},Enter:i.pick,Tab:i.pick,Esc:i.close},o=t.options.customKeys,s=o?{}:n;if(o)for(var c in o)o.hasOwnProperty(c)&&e(c,o[c]);var r=t.options.extraKeys;if(r)for(var c in r)r.hasOwnProperty(c)&&e(c,r[c]);return s}function c(t,i){for(;i&&i!=t;){if("LI"===i.nodeName.toUpperCase()&&i.parentNode==t)return i;i=i.parentNode}}function r(i,e){this.completion=i,this.data=e,this.picked=!1;var n=this,r=i.cm,h=this.hints=document.createElement("ul");h.className="CodeMirror-hints",this.selectedHint=e.selectedHint||0;for(var l=e.list,a=0;a<l.length;++a){var d=h.appendChild(document.createElement("li")),p=l[a],m=u+(a!=this.selectedHint?"":" "+f);null!=p.className&&(m=p.className+" "+m),d.className=m,p.render?p.render(d,e,p):d.appendChild(document.createTextNode(p.displayText||o(p))),d.hintId=a}var g=r.cursorCoords(i.options.alignWithWord?e.from:null),v=g.left,y=g.bottom,w=!0;h.style.left=v+"px",h.style.top=y+"px";var H=window.innerWidth||Math.max(document.body.offsetWidth,document.documentElement.offsetWidth),k=window.innerHeight||Math.max(document.body.offsetHeight,document.documentElement.offsetHeight);(i.options.container||document.body).appendChild(h);var C=h.getBoundingClientRect(),b=C.bottom-k,x=h.scrollHeight>h.clientHeight+1,A=r.getScrollInfo();if(b>0){var S=C.bottom-C.top,T=g.top-(g.bottom-C.top);if(T-S>0)h.style.top=(y=g.top-S)+"px",w=!1;else if(S>k){h.style.height=k-5+"px",h.style.top=(y=g.bottom-C.top)+"px";var M=r.getCursor();e.from.ch!=M.ch&&(g=r.cursorCoords(M),h.style.left=(v=g.left)+"px",C=h.getBoundingClientRect())}}var F=C.right-H;if(F>0&&(C.right-C.left>H&&(h.style.width=H-5+"px",F-=C.right-C.left-H),h.style.left=(v=g.left-F)+"px"),x)for(var N=h.firstChild;N;N=N.nextSibling)N.style.paddingRight=r.display.nativeBarWidth+"px";if(r.addKeyMap(this.keyMap=s(i,{moveFocus:function(t,i){n.changeActive(n.selectedHint+t,i)},setFocus:function(t){n.changeActive(t)},menuSize:function(){return n.screenAmount()},length:l.length,close:function(){i.close()},pick:function(){n.pick()},data:e})),i.options.closeOnUnfocus){var E;r.on("blur",this.onBlur=function(){E=setTimeout(function(){i.close()},100)}),r.on("focus",this.onFocus=function(){clearTimeout(E)})}return r.on("scroll",this.onScroll=function(){var t=r.getScrollInfo(),e=r.getWrapperElement().getBoundingClientRect(),n=y+A.top-t.top,o=n-(window.pageYOffset||(document.documentElement||document.body).scrollTop);return w||(o+=h.offsetHeight),o<=e.top||o>=e.bottom?i.close():(h.style.top=n+"px",void(h.style.left=v+A.left-t.left+"px"))}),t.on(h,"dblclick",function(t){var i=c(h,t.target||t.srcElement);i&&null!=i.hintId&&(n.changeActive(i.hintId),n.pick())}),t.on(h,"click",function(t){var e=c(h,t.target||t.srcElement);e&&null!=e.hintId&&(n.changeActive(e.hintId),i.options.completeOnSingleClick&&n.pick())}),t.on(h,"mousedown",function(){setTimeout(function(){r.focus()},20)}),t.signal(e,"select",l[0],h.firstChild),!0}function h(t,i){if(!t.somethingSelected())return i;for(var e=[],n=0;n<i.length;n++)i[n].supportsSelection&&e.push(i[n]);return e}function l(t,i,e,n){if(t.async)t(i,n,e);else{var o=t(i,e);o&&o.then?o.then(n):n(o)}}function a(i,e){var n,o=i.getHelpers(e,"hint");if(o.length){var s=function(t,i,e){function n(o){return o==s.length?i(null):void l(s[o],t,e,function(t){t&&t.list.length>0?i(t):n(o+1)})}var s=h(t,o);n(0)};return s.async=!0,s.supportsSelection=!0,s}return(n=i.getHelper(i.getCursor(),"hintWords"))?function(i){return t.hint.fromList(i,{words:n})}:t.hint.anyword?function(i,e){return t.hint.anyword(i,e)}:function(){}}var u="CodeMirror-hint",f="CodeMirror-hint-active";t.showHint=function(t,i,e){if(!i)return t.showHint(e);e&&e.async&&(i.async=!0);var n={hint:i};if(e)for(var o in e)n[o]=e[o];return t.showHint(n)},t.defineExtension("showHint",function(e){e=n(this,this.getCursor("start"),e);var o=this.listSelections();if(!(o.length>1)){if(this.somethingSelected()){if(!e.hint.supportsSelection)return;for(var s=0;s<o.length;s++)if(o[s].head.line!=o[s].anchor.line)return}this.state.completionActive&&this.state.completionActive.close();var c=this.state.completionActive=new i(this,e);c.options.hint&&(t.signal(this,"startCompletion",this),c.update(!0))}});var d=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},p=window.cancelAnimationFrame||clearTimeout;i.prototype={close:function(){this.active()&&(this.cm.state.completionActive=null,this.tick=null,this.cm.off("cursorActivity",this.activityFunc),this.widget&&this.data&&t.signal(this.data,"close"),this.widget&&this.widget.close(),t.signal(this.cm,"endCompletion",this.cm))},active:function(){return this.cm.state.completionActive==this},pick:function(i,e){var n=i.list[e];n.hint?n.hint(this.cm,i,n):this.cm.replaceRange(o(n),n.from||i.from,n.to||i.to,"complete"),t.signal(i,"pick",n),this.close()},cursorActivity:function(){this.debounce&&(p(this.debounce),this.debounce=0);var t=this.cm.getCursor(),i=this.cm.getLine(t.line);if(t.line!=this.startPos.line||i.length-t.ch!=this.startLen-this.startPos.ch||t.ch<this.startPos.ch||this.cm.somethingSelected()||t.ch&&this.options.closeCharacters.test(i.charAt(t.ch-1)))this.close();else{var e=this;this.debounce=d(function(){e.update()}),this.widget&&this.widget.disable()}},update:function(t){if(null!=this.tick){var i=this,e=++this.tick;l(this.options.hint,this.cm,this.options,function(n){i.tick==e&&i.finishUpdate(n,t)})}},finishUpdate:function(i,n){this.data&&t.signal(this.data,"update");var o=this.widget&&this.widget.picked||n&&this.options.completeSingle;this.widget&&this.widget.close(),i&&this.data&&e(this.data,i)||(this.data=i,i&&i.list.length&&(o&&1==i.list.length?this.pick(i,0):(this.widget=new r(this,i),t.signal(i,"shown"))))}},r.prototype={close:function(){if(this.completion.widget==this){this.completion.widget=null,this.hints.parentNode.removeChild(this.hints),this.completion.cm.removeKeyMap(this.keyMap);var t=this.completion.cm;this.completion.options.closeOnUnfocus&&(t.off("blur",this.onBlur),t.off("focus",this.onFocus)),t.off("scroll",this.onScroll)}},disable:function(){this.completion.cm.removeKeyMap(this.keyMap);var t=this;this.keyMap={Enter:function(){t.picked=!0}},this.completion.cm.addKeyMap(this.keyMap)},pick:function(){this.completion.pick(this.data,this.selectedHint)},changeActive:function(i,e){if(i>=this.data.list.length?i=e?this.data.list.length-1:0:i<0&&(i=e?0:this.data.list.length-1),this.selectedHint!=i){var n=this.hints.childNodes[this.selectedHint];n.className=n.className.replace(" "+f,""),n=this.hints.childNodes[this.selectedHint=i],n.className+=" "+f,n.offsetTop<this.hints.scrollTop?this.hints.scrollTop=n.offsetTop-3:n.offsetTop+n.offsetHeight>this.hints.scrollTop+this.hints.clientHeight&&(this.hints.scrollTop=n.offsetTop+n.offsetHeight-this.hints.clientHeight+3),t.signal(this.data,"select",this.data.list[this.selectedHint],n)}},screenAmount:function(){return Math.floor(this.hints.clientHeight/this.hints.firstChild.offsetHeight)||1}},t.registerHelper("hint","auto",{resolve:a}),t.registerHelper("hint","fromList",function(i,e){var n=i.getCursor(),o=i.getTokenAt(n),s=t.Pos(n.line,o.end);if(o.string&&/\w/.test(o.string[o.string.length-1]))var c=o.string,r=t.Pos(n.line,o.start);else var c="",r=s;for(var h=[],l=0;l<e.words.length;l++){var a=e.words[l];a.slice(0,c.length)==c&&h.push(a)}if(h.length)return{list:h,from:r,to:s}}),t.commands.autocomplete=t.showHint;var m={hint:t.hint.auto,completeSingle:!0,alignWithWord:!0,closeCharacters:/[\s()\[\]{};:>,]/,closeOnUnfocus:!0,completeOnSingleClick:!0,container:null,customKeys:null,extraKeys:null};t.defineOption("hintOptions",null)});
lib/codemirror/addon/hint/sql-hint.js CHANGED
@@ -18,7 +18,9 @@
18
  QUERY_DIV: ";",
19
  ALIAS_KEYWORD: "AS"
20
  };
21
- var Pos = CodeMirror.Pos;
 
 
22
 
23
  function getKeywords(editor) {
24
  var mode = editor.doc.modeOption;
@@ -30,10 +32,28 @@
30
  return typeof item == "string" ? item : item.text;
31
  }
32
 
33
- function getItem(list, item) {
34
- if (!list.slice) return list[item];
35
- for (var i = list.length - 1; i >= 0; i--) if (getText(list[i]) == item)
36
- return list[i];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
 
39
  function shallowClone(object) {
@@ -50,11 +70,18 @@
50
  }
51
 
52
  function addMatches(result, search, wordlist, formatter) {
53
- for (var word in wordlist) {
54
- if (!wordlist.hasOwnProperty(word)) continue;
55
- if (wordlist.slice) word = wordlist[word];
56
-
57
- if (match(search, word)) result.push(formatter(word));
 
 
 
 
 
 
 
58
  }
59
  }
60
 
@@ -78,7 +105,7 @@
78
  }
79
 
80
  function nameCompletion(cur, token, result, editor) {
81
- // Try to complete table, colunm names and return start position of completion
82
  var useBacktick = false;
83
  var nameParts = [];
84
  var start = token.start;
@@ -115,13 +142,13 @@
115
  var alias = false;
116
  var aliasTable = table;
117
  // Check if table is available. If not, find table by Alias
118
- if (!getItem(tables, table)) {
119
  var oldTable = table;
120
  table = findTableByAlias(table, editor);
121
  if (table !== oldTable) alias = true;
122
  }
123
 
124
- var columns = getItem(tables, table);
125
  if (columns && columns.columns)
126
  columns = columns.columns;
127
 
@@ -151,15 +178,6 @@
151
  }
152
  }
153
 
154
- function convertCurToNumber(cur) {
155
- // max characters of a line is 999,999.
156
- return cur.line + cur.ch / Math.pow(10, 6);
157
- }
158
-
159
- function convertNumberToCur(num) {
160
- return Pos(Math.floor(num), +num.toString().split('.').pop());
161
- }
162
-
163
  function findTableByAlias(alias, editor) {
164
  var doc = editor.doc;
165
  var fullQuery = doc.getValue();
@@ -182,15 +200,14 @@
182
  separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
183
 
184
  //find valid range
185
- var prevItem = 0;
186
- var current = convertCurToNumber(editor.getCursor());
187
- for (var i=0; i< separator.length; i++) {
188
- var _v = convertCurToNumber(separator[i]);
189
- if (current > prevItem && current <= _v) {
190
- validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
191
  break;
192
  }
193
- prevItem = _v;
194
  }
195
 
196
  var query = doc.getRange(validRange.start, validRange.end, false);
@@ -199,7 +216,7 @@
199
  var lineText = query[i];
200
  eachWord(lineText, function(word) {
201
  var wordUpperCase = word.toUpperCase();
202
- if (wordUpperCase === aliasUpperCase && getItem(tables, previousWord))
203
  table = previousWord;
204
  if (wordUpperCase !== CONS.ALIAS_KEYWORD)
205
  previousWord = word;
@@ -210,11 +227,11 @@
210
  }
211
 
212
  CodeMirror.registerHelper("hint", "sql", function(editor, options) {
213
- tables = (options && options.tables) || {};
214
  var defaultTableName = options && options.defaultTable;
215
  var disableKeywords = options && options.disableKeywords;
216
- defaultTable = defaultTableName && getItem(tables, defaultTableName);
217
- keywords = keywords || getKeywords(editor);
218
 
219
  if (defaultTableName && !defaultTable)
220
  defaultTable = findTableByAlias(defaultTableName, editor);
18
  QUERY_DIV: ";",
19
  ALIAS_KEYWORD: "AS"
20
  };
21
+ var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
22
+
23
+ function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
24
 
25
  function getKeywords(editor) {
26
  var mode = editor.doc.modeOption;
32
  return typeof item == "string" ? item : item.text;
33
  }
34
 
35
+ function wrapTable(name, value) {
36
+ if (isArray(value)) value = {columns: value}
37
+ if (!value.text) value.text = name
38
+ return value
39
+ }
40
+
41
+ function parseTables(input) {
42
+ var result = {}
43
+ if (isArray(input)) {
44
+ for (var i = input.length - 1; i >= 0; i--) {
45
+ var item = input[i]
46
+ result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
47
+ }
48
+ } else if (input) {
49
+ for (var name in input)
50
+ result[name.toUpperCase()] = wrapTable(name, input[name])
51
+ }
52
+ return result
53
+ }
54
+
55
+ function getTable(name) {
56
+ return tables[name.toUpperCase()]
57
  }
58
 
59
  function shallowClone(object) {
70
  }
71
 
72
  function addMatches(result, search, wordlist, formatter) {
73
+ if (isArray(wordlist)) {
74
+ for (var i = 0; i < wordlist.length; i++)
75
+ if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
76
+ } else {
77
+ for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
78
+ var val = wordlist[word]
79
+ if (!val || val === true)
80
+ val = word
81
+ else
82
+ val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
83
+ if (match(search, val)) result.push(formatter(val))
84
+ }
85
  }
86
  }
87
 
105
  }
106
 
107
  function nameCompletion(cur, token, result, editor) {
108
+ // Try to complete table, column names and return start position of completion
109
  var useBacktick = false;
110
  var nameParts = [];
111
  var start = token.start;
142
  var alias = false;
143
  var aliasTable = table;
144
  // Check if table is available. If not, find table by Alias
145
+ if (!getTable(table)) {
146
  var oldTable = table;
147
  table = findTableByAlias(table, editor);
148
  if (table !== oldTable) alias = true;
149
  }
150
 
151
+ var columns = getTable(table);
152
  if (columns && columns.columns)
153
  columns = columns.columns;
154
 
178
  }
179
  }
180
 
 
 
 
 
 
 
 
 
 
181
  function findTableByAlias(alias, editor) {
182
  var doc = editor.doc;
183
  var fullQuery = doc.getValue();
200
  separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
201
 
202
  //find valid range
203
+ var prevItem = null;
204
+ var current = editor.getCursor()
205
+ for (var i = 0; i < separator.length; i++) {
206
+ if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
207
+ validRange = {start: prevItem, end: separator[i]};
 
208
  break;
209
  }
210
+ prevItem = separator[i];
211
  }
212
 
213
  var query = doc.getRange(validRange.start, validRange.end, false);
216
  var lineText = query[i];
217
  eachWord(lineText, function(word) {
218
  var wordUpperCase = word.toUpperCase();
219
+ if (wordUpperCase === aliasUpperCase && getTable(previousWord))
220
  table = previousWord;
221
  if (wordUpperCase !== CONS.ALIAS_KEYWORD)
222
  previousWord = word;
227
  }
228
 
229
  CodeMirror.registerHelper("hint", "sql", function(editor, options) {
230
+ tables = parseTables(options && options.tables)
231
  var defaultTableName = options && options.defaultTable;
232
  var disableKeywords = options && options.disableKeywords;
233
+ defaultTable = defaultTableName && getTable(defaultTableName);
234
+ keywords = getKeywords(editor);
235
 
236
  if (defaultTableName && !defaultTable)
237
  defaultTable = findTableByAlias(defaultTableName, editor);
lib/codemirror/addon/hint/sql-hint.min.js CHANGED
@@ -1 +1 @@
1
- !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror"),require("../../mode/sql/sql")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../../mode/sql/sql"],t):t(CodeMirror)}(function(t){"use strict";function r(r){var n=r.doc.modeOption;return"sql"===n&&(n="text/x-sql"),t.resolveMode(n).keywords}function n(t){return"string"==typeof t?t:t.text}function e(t,r){if(!t.slice)return t[r];for(var e=t.length-1;e>=0;e--)if(n(t[e])==r)return t[e]}function o(t){var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);return r}function i(t,r){var e=t.length,o=n(r).substr(0,e);return t.toUpperCase()===o.toUpperCase()}function s(t,r,n,e){for(var o in n)n.hasOwnProperty(o)&&(n.slice&&(o=n[o]),i(r,o)&&t.push(e(o)))}function a(t){return"."==t.charAt(0)&&(t=t.substr(1)),t.replace(/`/g,"")}function u(t){for(var r=n(t).split("."),e=0;e<r.length;e++)r[e]="`"+r[e]+"`";var i=r.join(".");return"string"==typeof t?i:(t=o(t),t.text=i,t)}function f(t,r,n,i){for(var f=!1,c=[],l=r.start,p=!0;p;)p="."==r.string.charAt(0),f=f||"`"==r.string.charAt(0),l=r.start,c.unshift(a(r.string)),r=i.getTokenAt(A(t.line,r.start)),"."==r.string&&(p=!0,r=i.getTokenAt(A(t.line,r.start)));var v=c.join(".");s(n,v,d,function(t){return f?u(t):t}),s(n,v,h,function(t){return f?u(t):t}),v=c.pop();var m=c.join("."),b=!1,x=m;if(!e(d,m)){var y=m;m=g(m,i),m!==y&&(b=!0)}var q=e(d,m);return q&&q.columns&&(q=q.columns),q&&s(n,v,q,function(t){var r=m;return 1==b&&(r=x),"string"==typeof t?t=r+"."+t:(t=o(t),t.text=r+"."+t.text),f?u(t):t}),l}function c(t,r){if(t)for(var n=/[,;]/g,e=t.split(" "),o=0;o<e.length;o++)r(e[o]?e[o].replace(n,""):"")}function l(t){return t.line+t.ch/Math.pow(10,6)}function p(t){return A(Math.floor(t),+t.toString().split(".").pop())}function g(t,r){for(var n=r.doc,o=n.getValue(),i=t.toUpperCase(),s="",a="",u=[],f={start:A(0,0),end:A(r.lastLine(),r.getLineHandle(r.lastLine()).length)},g=o.indexOf(m.QUERY_DIV);g!=-1;)u.push(n.posFromIndex(g)),g=o.indexOf(m.QUERY_DIV,g+1);u.unshift(A(0,0)),u.push(A(r.lastLine(),r.getLineHandle(r.lastLine()).text.length));for(var h=0,v=l(r.getCursor()),b=0;b<u.length;b++){var x=l(u[b]);if(v>h&&v<=x){f={start:p(h),end:p(x)};break}h=x}for(var y=n.getRange(f.start,f.end,!1),b=0;b<y.length;b++){var q=y[b];if(c(q,function(t){var r=t.toUpperCase();r===i&&e(d,s)&&(a=s),r!==m.ALIAS_KEYWORD&&(s=t)}),a)break}return a}var d,h,v,m={QUERY_DIV:";",ALIAS_KEYWORD:"AS"},A=t.Pos;t.registerHelper("hint","sql",function(t,n){d=n&&n.tables||{};var o=n&&n.defaultTable,i=n&&n.disableKeywords;h=o&&e(d,o),v=v||r(t),o&&!h&&(h=g(o,t)),h=h||[],h.columns&&(h=h.columns);var a,u,c,l=t.getCursor(),p=[],m=t.getTokenAt(l);return m.end>l.ch&&(m.end=l.ch,m.string=m.string.slice(0,l.ch-m.start)),m.string.match(/^[.`\w@]\w*$/)?(c=m.string,a=m.start,u=m.end):(a=u=l.ch,c=""),"."==c.charAt(0)||"`"==c.charAt(0)?a=f(l,m,p,t):(s(p,c,d,function(t){return t}),s(p,c,h,function(t){return t}),i||s(p,c,v,function(t){return t.toUpperCase()})),{list:p,from:A(l.line,a),to:A(l.line,u)}})});
1
+ !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror"),require("../../mode/sql/sql")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../../mode/sql/sql"],t):t(CodeMirror)}(function(t){"use strict";function r(t){return"[object Array]"==Object.prototype.toString.call(t)}function e(r){var e=r.doc.modeOption;return"sql"===e&&(e="text/x-sql"),t.resolveMode(e).keywords}function n(t){return"string"==typeof t?t:t.text}function o(t,e){return r(e)&&(e={columns:e}),e.text||(e.text=t),e}function i(t){var e={};if(r(t))for(var i=t.length-1;i>=0;i--){var s=t[i];e[n(s).toUpperCase()]=o(n(s),s)}else if(t)for(var a in t)e[a.toUpperCase()]=o(a,t[a]);return e}function s(t){return v[t.toUpperCase()]}function a(t){var r={};for(var e in t)t.hasOwnProperty(e)&&(r[e]=t[e]);return r}function u(t,r){var e=t.length,o=n(r).substr(0,e);return t.toUpperCase()===o.toUpperCase()}function f(t,e,n,o){if(r(n))for(var i=0;i<n.length;i++)u(e,n[i])&&t.push(o(n[i]));else for(var s in n)if(n.hasOwnProperty(s)){var a=n[s];a=a&&a!==!0?a.displayText?{text:a.text,displayText:a.displayText}:a.text:s,u(e,a)&&t.push(o(a))}}function l(t){return"."==t.charAt(0)&&(t=t.substr(1)),t.replace(/`/g,"")}function c(t){for(var r=n(t).split("."),e=0;e<r.length;e++)r[e]="`"+r[e]+"`";var o=r.join(".");return"string"==typeof t?o:(t=a(t),t.text=o,t)}function p(t,r,e,n){for(var o=!1,i=[],u=r.start,p=!0;p;)p="."==r.string.charAt(0),o=o||"`"==r.string.charAt(0),u=r.start,i.unshift(l(r.string)),r=n.getTokenAt(y(t.line,r.start)),"."==r.string&&(p=!0,r=n.getTokenAt(y(t.line,r.start)));var g=i.join(".");f(e,g,v,function(t){return o?c(t):t}),f(e,g,h,function(t){return o?c(t):t}),g=i.pop();var x=i.join("."),m=!1,A=x;if(!s(x)){var b=x;x=d(x,n),x!==b&&(m=!0)}var C=s(x);return C&&C.columns&&(C=C.columns),C&&f(e,g,C,function(t){var r=x;return 1==m&&(r=A),"string"==typeof t?t=r+"."+t:(t=a(t),t.text=r+"."+t.text),o?c(t):t}),u}function g(t,r){if(t)for(var e=/[,;]/g,n=t.split(" "),o=0;o<n.length;o++)r(n[o]?n[o].replace(e,""):"")}function d(t,r){for(var e=r.doc,n=e.getValue(),o=t.toUpperCase(),i="",a="",u=[],f={start:y(0,0),end:y(r.lastLine(),r.getLineHandle(r.lastLine()).length)},l=n.indexOf(m.QUERY_DIV);l!=-1;)u.push(e.posFromIndex(l)),l=n.indexOf(m.QUERY_DIV,l+1);u.unshift(y(0,0)),u.push(y(r.lastLine(),r.getLineHandle(r.lastLine()).text.length));for(var c=null,p=r.getCursor(),d=0;d<u.length;d++){if((null==c||A(p,c)>0)&&A(p,u[d])<=0){f={start:c,end:u[d]};break}c=u[d]}for(var v=e.getRange(f.start,f.end,!1),d=0;d<v.length;d++){var h=v[d];if(g(h,function(t){var r=t.toUpperCase();r===o&&s(i)&&(a=i),r!==m.ALIAS_KEYWORD&&(i=t)}),a)break}return a}var v,h,x,m={QUERY_DIV:";",ALIAS_KEYWORD:"AS"},y=t.Pos,A=t.cmpPos;t.registerHelper("hint","sql",function(t,r){v=i(r&&r.tables);var n=r&&r.defaultTable,o=r&&r.disableKeywords;h=n&&s(n),x=e(t),n&&!h&&(h=d(n,t)),h=h||[],h.columns&&(h=h.columns);var a,u,l,c=t.getCursor(),g=[],m=t.getTokenAt(c);return m.end>c.ch&&(m.end=c.ch,m.string=m.string.slice(0,c.ch-m.start)),m.string.match(/^[.`\w@]\w*$/)?(l=m.string,a=m.start,u=m.end):(a=u=c.ch,l=""),"."==l.charAt(0)||"`"==l.charAt(0)?a=p(c,m,g,t):(f(g,l,v,function(t){return t}),f(g,l,h,function(t){return t}),o||f(g,l,x,function(t){return t.toUpperCase()})),{list:g,from:y(c.line,a),to:y(c.line,u)}})});
lib/codemirror/addon/lint/css-lint.js CHANGED
@@ -26,7 +26,7 @@ CodeMirror.registerHelper("lint", "css", function(text) {
26
  "empty-rules": 1,
27
  "known-properties": 1
28
  }), messages = results.messages, message = null;
29
-
30
  for ( var i = 0; i < messages.length; i++) {
31
  message = messages[i];
32
  var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;
26
  "empty-rules": 1,
27
  "known-properties": 1
28
  }), messages = results.messages, message = null;
29
+
30
  for ( var i = 0; i < messages.length; i++) {
31
  message = messages[i];
32
  var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;
lib/codemirror/addon/lint/lint.css CHANGED
@@ -4,10 +4,10 @@
4
  }
5
 
6
  .CodeMirror-lint-tooltip {
7
- background-color: infobackground;
8
  border: 1px solid black;
9
  border-radius: 4px 4px 4px 4px;
10
- color: infotext;
11
  font-family: monospace;
12
  font-size: 10pt;
13
  overflow: hidden;
4
  }
5
 
6
  .CodeMirror-lint-tooltip {
7
+ background-color: #ffd;
8
  border: 1px solid black;
9
  border-radius: 4px 4px 4px 4px;
10
+ color: black;
11
  font-family: monospace;
12
  font-size: 10pt;
13
  overflow: hidden;
lib/codemirror/addon/lint/lint.js CHANGED
@@ -186,9 +186,14 @@
186
  state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
187
  }
188
 
189
- function popupSpanTooltip(ann, e) {
190
  var target = e.target || e.srcElement;
191
- showTooltipFor(e, annotationTooltip(ann), target);
 
 
 
 
 
192
  }
193
 
194
  function onMouseOver(cm, e) {
@@ -196,10 +201,13 @@
196
  if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
197
  var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
198
  var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
 
 
199
  for (var i = 0; i < spans.length; ++i) {
200
  var ann = spans[i].__annotation;
201
- if (ann) return popupSpanTooltip(ann, e);
202
  }
 
203
  }
204
 
205
  CodeMirror.defineOption("lint", false, function(cm, val, old) {
@@ -218,7 +226,7 @@
218
  var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
219
  if (state.options.lintOnChange !== false)
220
  cm.on("change", onChange);
221
- if (state.options.tooltips != false)
222
  CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
223
 
224
  startLinting(cm);
186
  state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
187
  }
188
 
189
+ function popupTooltips(annotations, e) {
190
  var target = e.target || e.srcElement;
191
+ var tooltip = document.createDocumentFragment();
192
+ for (var i = 0; i < annotations.length; i++) {
193
+ var ann = annotations[i];
194
+ tooltip.appendChild(annotationTooltip(ann));
195
+ }
196
+ showTooltipFor(e, tooltip, target);
197
  }
198
 
199
  function onMouseOver(cm, e) {
201
  if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
202
  var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
203
  var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
204
+
205
+ var annotations = [];
206
  for (var i = 0; i < spans.length; ++i) {
207
  var ann = spans[i].__annotation;
208
+ if (ann) annotations.push(ann);
209
  }
210
+ if (annotations.length) popupTooltips(annotations, e);
211
  }
212
 
213
  CodeMirror.defineOption("lint", false, function(cm, val, old) {
226
  var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
227
  if (state.options.lintOnChange !== false)
228
  cm.on("change", onChange);
229
+ if (state.options.tooltips != false && state.options.tooltips != "gutter")
230
  CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
231
 
232
  startLinting(cm);
lib/codemirror/addon/lint/lint.min.js CHANGED
@@ -1 +1 @@
1
- !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],t):t(CodeMirror)}(function(t){"use strict";function e(e,n){function o(e){return r.parentNode?(r.style.top=Math.max(0,e.clientY-r.offsetHeight-5)+"px",void(r.style.left=e.clientX+5+"px")):t.off(document,"mousemove",o)}var r=document.createElement("div");return r.className="CodeMirror-lint-tooltip",r.appendChild(n.cloneNode(!0)),document.body.appendChild(r),t.on(document,"mousemove",o),o(e),null!=r.style.opacity&&(r.style.opacity=1),r}function n(t){t.parentNode&&t.parentNode.removeChild(t)}function o(t){t.parentNode&&(null==t.style.opacity&&n(t),t.style.opacity=0,setTimeout(function(){n(t)},600))}function r(n,r,i){function a(){t.off(i,"mouseout",a),l&&(o(l),l=null)}var l=e(n,r),s=setInterval(function(){if(l)for(var t=i;;t=t.parentNode){if(t&&11==t.nodeType&&(t=t.host),t==document.body)return;if(!t){a();break}}if(!l)return clearInterval(s)},400);t.on(i,"mouseout",a)}function i(t,e,n){this.marked=[],this.options=e,this.timeout=null,this.hasGutter=n,this.onMouseOver=function(e){g(t,e)},this.waitingFor=0}function a(t,e){return e instanceof Function?{getAnnotations:e}:(e&&e!==!0||(e={}),e)}function l(t){var e=t.state.lint;e.hasGutter&&t.clearGutter(y);for(var n=0;n<e.marked.length;++n)e.marked[n].clear();e.marked.length=0}function s(e,n,o,i){var a=document.createElement("div"),l=a;return a.className="CodeMirror-lint-marker-"+n,o&&(l=a.appendChild(document.createElement("div")),l.className="CodeMirror-lint-marker-multiple"),0!=i&&t.on(l,"mouseover",function(t){r(t,e,l)}),a}function u(t,e){return"error"==t?t:e}function c(t){for(var e=[],n=0;n<t.length;++n){var o=t[n],r=o.from.line;(e[r]||(e[r]=[])).push(o)}return e}function f(t){var e=t.severity;e||(e="error");var n=document.createElement("div");return n.className="CodeMirror-lint-message-"+e,n.appendChild(document.createTextNode(t.message)),n}function m(e,n,o){function r(){a=-1,e.off("change",r)}var i=e.state.lint,a=++i.waitingFor;e.on("change",r),n(e.getValue(),function(n,o){e.off("change",r),i.waitingFor==a&&(o&&n instanceof t&&(n=o),p(e,n))},o,e)}function d(e){var n=e.state.lint,o=n.options,r=o.options||o,i=o.getAnnotations||e.getHelper(t.Pos(0,0),"lint");i&&(o.async||i.async?m(e,i,r):p(e,i(e.getValue(),r,e)))}function p(t,e){l(t);for(var n=t.state.lint,o=n.options,r=c(e),i=0;i<r.length;++i){var a=r[i];if(a){for(var m=null,d=n.hasGutter&&document.createDocumentFragment(),p=0;p<a.length;++p){var v=a[p],h=v.severity;h||(h="error"),m=u(m,h),o.formatAnnotation&&(v=o.formatAnnotation(v)),n.hasGutter&&d.appendChild(f(v)),v.to&&n.marked.push(t.markText(v.from,v.to,{className:"CodeMirror-lint-mark-"+h,__annotation:v}))}n.hasGutter&&t.setGutterMarker(i,y,s(d,m,a.length>1,n.options.tooltips))}}o.onUpdateLinting&&o.onUpdateLinting(e,r,t)}function v(t){var e=t.state.lint;e&&(clearTimeout(e.timeout),e.timeout=setTimeout(function(){d(t)},e.options.delay||500))}function h(t,e){var n=e.target||e.srcElement;r(e,f(t),n)}function g(t,e){var n=e.target||e.srcElement;if(/\bCodeMirror-lint-mark-/.test(n.className))for(var o=n.getBoundingClientRect(),r=(o.left+o.right)/2,i=(o.top+o.bottom)/2,a=t.findMarksAt(t.coordsChar({left:r,top:i},"client")),l=0;l<a.length;++l){var s=a[l].__annotation;if(s)return h(s,e)}}var y="CodeMirror-lint-markers";t.defineOption("lint",!1,function(e,n,o){if(o&&o!=t.Init&&(l(e),e.state.lint.options.lintOnChange!==!1&&e.off("change",v),t.off(e.getWrapperElement(),"mouseover",e.state.lint.onMouseOver),clearTimeout(e.state.lint.timeout),delete e.state.lint),n){for(var r=e.getOption("gutters"),s=!1,u=0;u<r.length;++u)r[u]==y&&(s=!0);var c=e.state.lint=new i(e,a(e,n),s);c.options.lintOnChange!==!1&&e.on("change",v),0!=c.options.tooltips&&t.on(e.getWrapperElement(),"mouseover",c.onMouseOver),d(e)}}),t.defineExtension("performLint",function(){this.state.lint&&d(this)})});
1
+ !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],t):t(CodeMirror)}(function(t){"use strict";function e(e,n){function o(e){return r.parentNode?(r.style.top=Math.max(0,e.clientY-r.offsetHeight-5)+"px",void(r.style.left=e.clientX+5+"px")):t.off(document,"mousemove",o)}var r=document.createElement("div");return r.className="CodeMirror-lint-tooltip",r.appendChild(n.cloneNode(!0)),document.body.appendChild(r),t.on(document,"mousemove",o),o(e),null!=r.style.opacity&&(r.style.opacity=1),r}function n(t){t.parentNode&&t.parentNode.removeChild(t)}function o(t){t.parentNode&&(null==t.style.opacity&&n(t),t.style.opacity=0,setTimeout(function(){n(t)},600))}function r(n,r,i){function a(){t.off(i,"mouseout",a),l&&(o(l),l=null)}var l=e(n,r),s=setInterval(function(){if(l)for(var t=i;;t=t.parentNode){if(t&&11==t.nodeType&&(t=t.host),t==document.body)return;if(!t){a();break}}if(!l)return clearInterval(s)},400);t.on(i,"mouseout",a)}function i(t,e,n){this.marked=[],this.options=e,this.timeout=null,this.hasGutter=n,this.onMouseOver=function(e){g(t,e)},this.waitingFor=0}function a(t,e){return e instanceof Function?{getAnnotations:e}:(e&&e!==!0||(e={}),e)}function l(t){var e=t.state.lint;e.hasGutter&&t.clearGutter(y);for(var n=0;n<e.marked.length;++n)e.marked[n].clear();e.marked.length=0}function s(e,n,o,i){var a=document.createElement("div"),l=a;return a.className="CodeMirror-lint-marker-"+n,o&&(l=a.appendChild(document.createElement("div")),l.className="CodeMirror-lint-marker-multiple"),0!=i&&t.on(l,"mouseover",function(t){r(t,e,l)}),a}function u(t,e){return"error"==t?t:e}function c(t){for(var e=[],n=0;n<t.length;++n){var o=t[n],r=o.from.line;(e[r]||(e[r]=[])).push(o)}return e}function f(t){var e=t.severity;e||(e="error");var n=document.createElement("div");return n.className="CodeMirror-lint-message-"+e,n.appendChild(document.createTextNode(t.message)),n}function m(e,n,o){function r(){a=-1,e.off("change",r)}var i=e.state.lint,a=++i.waitingFor;e.on("change",r),n(e.getValue(),function(n,o){e.off("change",r),i.waitingFor==a&&(o&&n instanceof t&&(n=o),p(e,n))},o,e)}function d(e){var n=e.state.lint,o=n.options,r=o.options||o,i=o.getAnnotations||e.getHelper(t.Pos(0,0),"lint");i&&(o.async||i.async?m(e,i,r):p(e,i(e.getValue(),r,e)))}function p(t,e){l(t);for(var n=t.state.lint,o=n.options,r=c(e),i=0;i<r.length;++i){var a=r[i];if(a){for(var m=null,d=n.hasGutter&&document.createDocumentFragment(),p=0;p<a.length;++p){var h=a[p],v=h.severity;v||(v="error"),m=u(m,v),o.formatAnnotation&&(h=o.formatAnnotation(h)),n.hasGutter&&d.appendChild(f(h)),h.to&&n.marked.push(t.markText(h.from,h.to,{className:"CodeMirror-lint-mark-"+v,__annotation:h}))}n.hasGutter&&t.setGutterMarker(i,y,s(d,m,a.length>1,n.options.tooltips))}}o.onUpdateLinting&&o.onUpdateLinting(e,r,t)}function h(t){var e=t.state.lint;e&&(clearTimeout(e.timeout),e.timeout=setTimeout(function(){d(t)},e.options.delay||500))}function v(t,e){for(var n=e.target||e.srcElement,o=document.createDocumentFragment(),i=0;i<t.length;i++){var a=t[i];o.appendChild(f(a))}r(e,o,n)}function g(t,e){var n=e.target||e.srcElement;if(/\bCodeMirror-lint-mark-/.test(n.className)){for(var o=n.getBoundingClientRect(),r=(o.left+o.right)/2,i=(o.top+o.bottom)/2,a=t.findMarksAt(t.coordsChar({left:r,top:i},"client")),l=[],s=0;s<a.length;++s){var u=a[s].__annotation;u&&l.push(u)}l.length&&v(l,e)}}var y="CodeMirror-lint-markers";t.defineOption("lint",!1,function(e,n,o){if(o&&o!=t.Init&&(l(e),e.state.lint.options.lintOnChange!==!1&&e.off("change",h),t.off(e.getWrapperElement(),"mouseover",e.state.lint.onMouseOver),clearTimeout(e.state.lint.timeout),delete e.state.lint),n){for(var r=e.getOption("gutters"),s=!1,u=0;u<r.length;++u)r[u]==y&&(s=!0);var c=e.state.lint=new i(e,a(e,n),s);c.options.lintOnChange!==!1&&e.on("change",h),0!=c.options.tooltips&&"gutter"!=c.options.tooltips&&t.on(e.getWrapperElement(),"mouseover",c.onMouseOver),d(e)}}),t.defineExtension("performLint",function(){this.state.lint&&d(this)})});
lib/codemirror/addon/merge/merge.css CHANGED
@@ -60,6 +60,7 @@
60
  position: absolute;
61
  cursor: pointer;
62
  color: #44c;
 
63
  }
64
 
65
  .CodeMirror-merge-copy-reverse {
60
  position: absolute;
61
  cursor: pointer;
62
  color: #44c;
63
+ z-index: 3;
64
  }
65
 
66
  .CodeMirror-merge-copy-reverse {
lib/codemirror/addon/merge/merge.js CHANGED
@@ -40,12 +40,17 @@
40
  (this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);
41
  this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
42
  this.orig.state.diffViews = [this];
 
 
 
43
 
44
  this.diff = getDiff(asString(orig), asString(options.value));
45
  this.chunks = getChunks(this.diff);
46
  this.diffOutOfDate = this.dealigned = false;
47
 
48
  this.showDifferences = options.showDifferences !== false;
 
 
49
  this.forceUpdate = registerUpdate(this);
50
  setScrollLock(this, true, false);
51
  registerScroll(this);
@@ -88,10 +93,11 @@
88
  updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
89
  updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
90
  }
91
- makeConnections(dv);
92
 
93
  if (dv.mv.options.connect == "align")
94
  alignChunks(dv);
 
 
95
  updating = false;
96
  }
97
  function setDealign(fast) {
@@ -113,8 +119,14 @@
113
  // Update faster when a line was added/removed
114
  setDealign(change.text.length - 1 != change.to.line - change.from.line);
115
  }
 
 
 
 
116
  dv.edit.on("change", change);
117
  dv.orig.on("change", change);
 
 
118
  dv.edit.on("markerAdded", setDealign);
119
  dv.edit.on("markerCleared", setDealign);
120
  dv.orig.on("markerAdded", setDealign);
@@ -191,16 +203,22 @@
191
 
192
  // Updating the marks for editor content
193
 
 
 
 
 
 
 
 
 
 
194
  function clearMarks(editor, arr, classes) {
195
  for (var i = 0; i < arr.length; ++i) {
196
  var mark = arr[i];
197
- if (mark instanceof CodeMirror.TextMarker) {
198
  mark.clear();
199
- } else if (mark.parent) {
200
- editor.removeLineClass(mark, "background", classes.chunk);
201
- editor.removeLineClass(mark, "background", classes.start);
202
- editor.removeLineClass(mark, "background", classes.end);
203
- }
204
  }
205
  arr.length = 0;
206
  }
@@ -226,24 +244,30 @@
226
  });
227
  }
228
 
 
 
 
 
 
 
 
 
 
 
229
  function markChanges(editor, diff, type, marks, from, to, classes) {
230
  var pos = Pos(0, 0);
231
  var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
232
  var cls = type == DIFF_DELETE ? classes.del : classes.insert;
233
  function markChunk(start, end) {
234
  var bfrom = Math.max(from, start), bto = Math.min(to, end);
235
- for (var i = bfrom; i < bto; ++i) {
236
- var line = editor.addLineClass(i, "background", classes.chunk);
237
- if (i == start) editor.addLineClass(line, "background", classes.start);
238
- if (i == end - 1) editor.addLineClass(line, "background", classes.end);
239
- marks.push(line);
240
- }
241
  // When the chunk is empty, make sure a horizontal line shows up
242
  if (start == end && bfrom == end && bto == end) {
243
  if (bfrom)
244
- marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
245
  else
246
- marks.push(editor.addLineClass(bfrom, "background", classes.start));
247
  }
248
  }
249
 
@@ -284,7 +308,9 @@
284
  if (dv.copyButtons) clear(dv.copyButtons);
285
 
286
  var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
287
- var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
 
 
288
  for (var i = 0; i < dv.chunks.length; i++) {
289
  var ch = dv.chunks[i];
290
  if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
@@ -312,19 +338,14 @@
312
  linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
313
  }
314
  if (other) {
315
- for (var i = 0; i < other.chunks.length; i++) {
316
  var chunk = other.chunks[i];
317
  for (var j = 0; j < linesToAlign.length; j++) {
318
- var align = linesToAlign[j];
319
- if (align[1] == chunk.editTo) {
320
- j = -1;
321
- break;
322
- } else if (align[1] > chunk.editTo) {
323
- break;
324
- }
325
  }
326
- if (j > -1)
327
- linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
328
  }
329
  }
330
  return linesToAlign;
@@ -390,13 +411,13 @@
390
 
391
  function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
392
  var flip = dv.type == "left";
393
- var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
394
  if (dv.svg) {
395
  var topLpx = top;
396
- var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
397
  if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
398
- var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
399
- var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
400
  if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
401
  var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
402
  var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
@@ -410,10 +431,10 @@
410
  var editOriginals = dv.mv.options.allowEditingOriginals;
411
  copy.title = editOriginals ? "Push to left" : "Revert chunk";
412
  copy.chunk = chunk;
413
- copy.style.top = top + "px";
414
 
415
  if (editOriginals) {
416
- var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
417
  var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
418
  "CodeMirror-merge-copy-reverse"));
419
  copyReverse.title = "Push to right";
@@ -427,8 +448,9 @@
427
 
428
  function copyChunk(dv, to, from, chunk) {
429
  if (dv.diffOutOfDate) return;
430
- to.replaceRange(from.getRange(Pos(chunk.origFrom, 0), Pos(chunk.origTo, 0)),
431
- Pos(chunk.editFrom, 0), Pos(chunk.editTo, 0));
 
432
  }
433
 
434
  // Merge view, containing 0, 1, or 2 diff views.
@@ -446,18 +468,18 @@
446
 
447
  if (hasLeft) {
448
  left = this.left = new DiffView(this, "left");
449
- var leftPane = elt("div", null, "CodeMirror-merge-pane");
450
  wrap.push(leftPane);
451
  wrap.push(buildGap(left));
452
  }
453
 
454
- var editPane = elt("div", null, "CodeMirror-merge-pane");
455
  wrap.push(editPane);
456
 
457
  if (hasRight) {
458
  right = this.right = new DiffView(this, "right");
459
  wrap.push(buildGap(right));
460
- var rightPane = elt("div", null, "CodeMirror-merge-pane");
461
  wrap.push(rightPane);
462
  }
463
 
@@ -470,7 +492,6 @@
470
 
471
  if (left) left.init(leftPane, origLeft, options);
472
  if (right) right.init(rightPane, origRight, options);
473
-
474
  if (options.collapseIdentical)
475
  this.editor().operation(function() {
476
  collapseIdenticalStretches(self, options.collapseIdentical);
@@ -479,6 +500,9 @@
479
  this.aligners = [];
480
  alignChunks(this.left || this.right, true);
481
  }
 
 
 
482
 
483
  var onResize = function() {
484
  if (left) makeConnections(left);
@@ -521,7 +545,7 @@
521
  }
522
 
523
  MergeView.prototype = {
524
- constuctor: MergeView,
525
  editor: function() { return this.edit; },
526
  rightOriginal: function() { return this.right && this.right.orig; },
527
  leftOriginal: function() { return this.left && this.left.orig; },
@@ -547,7 +571,6 @@
547
  var dmp = new diff_match_patch();
548
  function getDiff(a, b) {
549
  var diff = dmp.diff_main(a, b);
550
- dmp.diff_cleanupSemantic(diff);
551
  // The library sometimes leaves in empty parts, which confuse the algorithm
552
  for (var i = 0; i < diff.length; ++i) {
553
  var part = diff[i];
40
  (this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);
41
  this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
42
  this.orig.state.diffViews = [this];
43
+ var classLocation = options.chunkClassLocation || "background";
44
+ if (Object.prototype.toString.call(classLocation) != "[object Array]") classLocation = [classLocation]
45
+ this.classes.classLocation = classLocation
46
 
47
  this.diff = getDiff(asString(orig), asString(options.value));
48
  this.chunks = getChunks(this.diff);
49
  this.diffOutOfDate = this.dealigned = false;
50
 
51
  this.showDifferences = options.showDifferences !== false;
52
+ },
53
+ registerEvents: function() {
54
  this.forceUpdate = registerUpdate(this);
55
  setScrollLock(this, true, false);
56
  registerScroll(this);
93
  updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
94
  updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
95
  }
 
96
 
97
  if (dv.mv.options.connect == "align")
98
  alignChunks(dv);
99
+ makeConnections(dv);
100
+
101
  updating = false;
102
  }
103
  function setDealign(fast) {
119
  // Update faster when a line was added/removed
120
  setDealign(change.text.length - 1 != change.to.line - change.from.line);
121
  }
122
+ function swapDoc() {
123
+ dv.diffOutOfDate = true;
124
+ update("full");
125
+ }
126
  dv.edit.on("change", change);
127
  dv.orig.on("change", change);
128
+ dv.edit.on("swapDoc", swapDoc);
129
+ dv.orig.on("swapDoc", swapDoc);
130
  dv.edit.on("markerAdded", setDealign);
131
  dv.edit.on("markerCleared", setDealign);
132
  dv.orig.on("markerAdded", setDealign);
203
 
204
  // Updating the marks for editor content
205
 
206
+ function removeClass(editor, line, classes) {
207
+ var locs = classes.classLocation
208
+ for (var i = 0; i < locs.length; i++) {
209
+ editor.removeLineClass(line, locs[i], classes.chunk);
210
+ editor.removeLineClass(line, locs[i], classes.start);
211
+ editor.removeLineClass(line, locs[i], classes.end);
212
+ }
213
+ }
214
+
215
  function clearMarks(editor, arr, classes) {
216
  for (var i = 0; i < arr.length; ++i) {
217
  var mark = arr[i];
218
+ if (mark instanceof CodeMirror.TextMarker)
219
  mark.clear();
220
+ else if (mark.parent)
221
+ removeClass(editor, mark, classes);
 
 
 
222
  }
223
  arr.length = 0;
224
  }
244
  });
245
  }
246
 
247
+ function addClass(editor, lineNr, classes, main, start, end) {
248
+ var locs = classes.classLocation, line = editor.getLineHandle(lineNr);
249
+ for (var i = 0; i < locs.length; i++) {
250
+ if (main) editor.addLineClass(line, locs[i], classes.chunk);
251
+ if (start) editor.addLineClass(line, locs[i], classes.start);
252
+ if (end) editor.addLineClass(line, locs[i], classes.end);
253
+ }
254
+ return line;
255
+ }
256
+
257
  function markChanges(editor, diff, type, marks, from, to, classes) {
258
  var pos = Pos(0, 0);
259
  var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
260
  var cls = type == DIFF_DELETE ? classes.del : classes.insert;
261
  function markChunk(start, end) {
262
  var bfrom = Math.max(from, start), bto = Math.min(to, end);
263
+ for (var i = bfrom; i < bto; ++i)
264
+ marks.push(addClass(editor, i, classes, true, i == start, i == end - 1));
 
 
 
 
265
  // When the chunk is empty, make sure a horizontal line shows up
266
  if (start == end && bfrom == end && bto == end) {
267
  if (bfrom)
268
+ marks.push(addClass(editor, bfrom - 1, classes, false, false, true));
269
  else
270
+ marks.push(addClass(editor, bfrom, classes, false, true, false));
271
  }
272
  }
273
 
308
  if (dv.copyButtons) clear(dv.copyButtons);
309
 
310
  var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
311
+ var outerTop = dv.mv.wrap.getBoundingClientRect().top
312
+ var sTopEdit = outerTop - dv.edit.getScrollerElement().getBoundingClientRect().top + dv.edit.getScrollInfo().top
313
+ var sTopOrig = outerTop - dv.orig.getScrollerElement().getBoundingClientRect().top + dv.orig.getScrollInfo().top;
314
  for (var i = 0; i < dv.chunks.length; i++) {
315
  var ch = dv.chunks[i];
316
  if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
338
  linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
339
  }
340
  if (other) {
341
+ chunkLoop: for (var i = 0; i < other.chunks.length; i++) {
342
  var chunk = other.chunks[i];
343
  for (var j = 0; j < linesToAlign.length; j++) {
344
+ var diff = linesToAlign[j][1] - chunk.editTo;
345
+ if (diff == 0) continue chunkLoop
346
+ if (diff > 0) break;
 
 
 
 
347
  }
348
+ linesToAlign.splice(j, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
 
349
  }
350
  }
351
  return linesToAlign;
411
 
412
  function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
413
  var flip = dv.type == "left";
414
+ var top = dv.orig.heightAtLine(chunk.origFrom, "local", true) - sTopOrig;
415
  if (dv.svg) {
416
  var topLpx = top;
417
+ var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local", true) - sTopEdit;
418
  if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
419
+ var botLpx = dv.orig.heightAtLine(chunk.origTo, "local", true) - sTopOrig;
420
+ var botRpx = dv.edit.heightAtLine(chunk.editTo, "local", true) - sTopEdit;
421
  if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
422
  var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
423
  var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
431
  var editOriginals = dv.mv.options.allowEditingOriginals;
432
  copy.title = editOriginals ? "Push to left" : "Revert chunk";
433
  copy.chunk = chunk;
434
+ copy.style.top = (chunk.origTo > chunk.origFrom ? top : dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit) + "px";
435
 
436
  if (editOriginals) {
437
+ var topReverse = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
438
  var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
439
  "CodeMirror-merge-copy-reverse"));
440
  copyReverse.title = "Push to right";
448
 
449
  function copyChunk(dv, to, from, chunk) {
450
  if (dv.diffOutOfDate) return;
451
+ var editStart = chunk.editTo > to.lastLine() ? Pos(chunk.editFrom - 1) : Pos(chunk.editFrom, 0)
452
+ var origStart = chunk.origTo > from.lastLine() ? Pos(chunk.origFrom - 1) : Pos(chunk.origFrom, 0)
453
+ to.replaceRange(from.getRange(origStart, Pos(chunk.origTo, 0)), editStart, Pos(chunk.editTo, 0))
454
  }
455
 
456
  // Merge view, containing 0, 1, or 2 diff views.
468
 
469
  if (hasLeft) {
470
  left = this.left = new DiffView(this, "left");
471
+ var leftPane = elt("div", null, "CodeMirror-merge-pane CodeMirror-merge-left");
472
  wrap.push(leftPane);
473
  wrap.push(buildGap(left));
474
  }
475
 
476
+ var editPane = elt("div", null, "CodeMirror-merge-pane CodeMirror-merge-editor");
477
  wrap.push(editPane);
478
 
479
  if (hasRight) {
480
  right = this.right = new DiffView(this, "right");
481
  wrap.push(buildGap(right));
482
+ var rightPane = elt("div", null, "CodeMirror-merge-pane CodeMirror-merge-right");
483
  wrap.push(rightPane);
484
  }
485
 
492
 
493
  if (left) left.init(leftPane, origLeft, options);
494
  if (right) right.init(rightPane, origRight, options);
 
495
  if (options.collapseIdentical)
496
  this.editor().operation(function() {
497
  collapseIdenticalStretches(self, options.collapseIdentical);
500
  this.aligners = [];
501
  alignChunks(this.left || this.right, true);
502
  }
503
+ if (left) left.registerEvents()
504
+ if (right) right.registerEvents()
505
+
506
 
507
  var onResize = function() {
508
  if (left) makeConnections(left);
545
  }
546
 
547
  MergeView.prototype = {
548
+ constructor: MergeView,
549
  editor: function() { return this.edit; },
550
  rightOriginal: function() { return this.right && this.right.orig; },
551
  leftOriginal: function() { return this.left && this.left.orig; },
571
  var dmp = new diff_match_patch();
572
  function getDiff(a, b) {
573
  var diff = dmp.diff_main(a, b);
 
574
  // The library sometimes leaves in empty parts, which confuse the algorithm
575
  for (var i = 0; i < diff.length; ++i) {
576
  var part = diff[i];
lib/codemirror/addon/merge/merge.min.js CHANGED
@@ -1 +1 @@
1
- !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","diff_match_patch"],e):e(CodeMirror)}(function(e){"use strict";function t(e,t){this.mv=e,this.type=t,this.classes="left"==t?{chunk:"CodeMirror-merge-l-chunk",start:"CodeMirror-merge-l-chunk-start",end:"CodeMirror-merge-l-chunk-end",insert:"CodeMirror-merge-l-inserted",del:"CodeMirror-merge-l-deleted",connect:"CodeMirror-merge-l-connect"}:{chunk:"CodeMirror-merge-r-chunk",start:"CodeMirror-merge-r-chunk-start",end:"CodeMirror-merge-r-chunk-end",insert:"CodeMirror-merge-r-inserted",del:"CodeMirror-merge-r-deleted",connect:"CodeMirror-merge-r-connect"}}function r(t){t.diffOutOfDate&&(t.diff=F(t.orig.getValue(),t.edit.getValue()),t.chunks=w(t.diff),t.diffOutOfDate=!1,e.signal(t.edit,"updateDiff",t.diff))}function i(e){function t(t){z=!0,d=!1,"full"==t&&(e.svg&&O(e.svg),e.copyButtons&&O(e.copyButtons),s(e.edit,a.marked,e.classes),s(e.orig,c.marked,e.classes),a.from=a.to=c.from=c.to=0),r(e),e.showDifferences&&(f(e.edit,e.diff,a,DIFF_INSERT,e.classes),f(e.orig,e.diff,c,DIFF_DELETE,e.classes)),h(e),"align"==e.mv.options.connect&&g(e),z=!1}function i(t){z||(e.dealigned=!0,o(t))}function o(e){z||d||(clearTimeout(l),e===!0&&(d=!0),l=setTimeout(t,e===!0?20:250))}function n(t,r){e.diffOutOfDate||(e.diffOutOfDate=!0,a.from=a.to=c.from=c.to=0),i(r.text.length-1!=r.to.line-r.from.line)}var l,a={from:0,to:0,marked:[]},c={from:0,to:0,marked:[]},d=!1;return e.edit.on("change",n),e.orig.on("change",n),e.edit.on("markerAdded",i),e.edit.on("markerCleared",i),e.orig.on("markerAdded",i),e.orig.on("markerCleared",i),e.edit.on("viewportChange",function(){o(!1)}),e.orig.on("viewportChange",function(){o(!1)}),t(),t}function o(e){e.edit.on("scroll",function(){n(e,DIFF_INSERT)&&h(e)}),e.orig.on("scroll",function(){n(e,DIFF_DELETE)&&h(e)})}function n(e,t){if(e.diffOutOfDate)return!1;if(!e.lockScroll)return!0;var r,i,o=+new Date;if(t==DIFF_INSERT?(r=e.edit,i=e.orig):(r=e.orig,i=e.edit),r.state.scrollSetBy==e&&(r.state.scrollSetAt||0)+50>o)return!1;var n=r.getScrollInfo();if("align"==e.mv.options.connect)m=n.top;else{var a,s,f=.5*n.clientHeight,c=n.top+f,h=r.lineAtHeight(c,"local"),d=M(e.chunks,h,t==DIFF_INSERT),u=l(r,t==DIFF_INSERT?d.edit:d.orig),g=l(i,t==DIFF_INSERT?d.orig:d.edit),v=(c-u.top)/(u.bot-u.top),m=g.top-f+v*(g.bot-g.top);if(m>n.top&&(s=n.top/f)<1)m=m*s+n.top*(1-s);else if((a=n.height-n.clientHeight-n.top)<f){var p=i.getScrollInfo(),k=p.height-p.clientHeight-m;k>a&&(s=a/f)<1&&(m=m*s+(p.height-p.clientHeight-a)*(1-s))}}return i.scrollTo(n.left,m),i.state.scrollSetAt=o,i.state.scrollSetBy=e,!0}function l(e,t){var r=t.after;return null==r&&(r=e.lastLine()+1),{top:e.heightAtLine(t.before||0,"local"),bot:e.heightAtLine(r,"local")}}function a(e,t,r){e.lockScroll=t,t&&0!=r&&n(e,DIFF_INSERT)&&h(e),e.lockButton.innerHTML=t?"⇛⇚":"⇛&nbsp;&nbsp;⇚"}function s(t,r,i){for(var o=0;o<r.length;++o){var n=r[o];n instanceof e.TextMarker?n.clear():n.parent&&(t.removeLineClass(n,"background",i.chunk),t.removeLineClass(n,"background",i.start),t.removeLineClass(n,"background",i.end))}r.length=0}function f(e,t,r,i,o){var n=e.getViewport();e.operation(function(){r.from==r.to||n.from-r.to>20||r.from-n.to>20?(s(e,r.marked,o),c(e,t,i,r.marked,n.from,n.to,o),r.from=n.from,r.to=n.to):(n.from<r.from&&(c(e,t,i,r.marked,n.from,r.from,o),r.from=n.from),n.to>r.to&&(c(e,t,i,r.marked,r.to,n.to,o),r.to=n.to))})}function c(e,t,r,i,o,n,l){function a(t,r){for(var a=Math.max(o,t),s=Math.min(n,r),f=a;f<s;++f){var c=e.addLineClass(f,"background",l.chunk);f==t&&e.addLineClass(c,"background",l.start),f==r-1&&e.addLineClass(c,"background",l.end),i.push(c)}t==r&&a==r&&s==r&&(a?i.push(e.addLineClass(a-1,"background",l.end)):i.push(e.addLineClass(a,"background",l.start)))}for(var s=U(0,0),f=U(o,0),c=e.clipPos(U(n-1)),h=r==DIFF_DELETE?l.del:l.insert,d=0,u=0;u<t.length;++u){var g=t[u],v=g[0],m=g[1];if(v==DIFF_EQUAL){var p=s.line+(D(t,u)?0:1);x(s,m);var k=s.line+(y(t,u)?1:0);k>p&&(u&&a(d,p),d=k)}else if(v==r){var C=x(s,m,!0),T=B(f,s),F=_(c,C);R(T,F)||i.push(e.markText(T,F,{className:h})),s=C}}d<=s.line&&a(d,s.line+1)}function h(e){if(e.showDifferences){if(e.svg){O(e.svg);var t=e.gap.offsetWidth;N(e.svg,"width",t,"height",e.gap.offsetHeight)}e.copyButtons&&O(e.copyButtons);for(var r=e.edit.getViewport(),i=e.orig.getViewport(),o=e.edit.getScrollInfo().top,n=e.orig.getScrollInfo().top,l=0;l<e.chunks.length;l++){var a=e.chunks[l];a.editFrom<=r.to&&a.editTo>=r.from&&a.origFrom<=i.to&&a.origTo>=i.from&&p(e,a,n,o,t)}}}function d(e,t){for(var r=0,i=0,o=0;o<t.length;o++){var n=t[o];if(n.editTo>e&&n.editFrom<=e)return null;if(n.editFrom>e)break;r=n.editTo,i=n.origTo}return i+(e-r)}function u(e,t){for(var r=[],i=0;i<e.chunks.length;i++){var o=e.chunks[i];r.push([o.origTo,o.editTo,t?d(o.editTo,t.chunks):null])}if(t)for(var i=0;i<t.chunks.length;i++){for(var o=t.chunks[i],n=0;n<r.length;n++){var l=r[n];if(l[1]==o.editTo){n=-1;break}if(l[1]>o.editTo)break}n>-1&&r.splice(n-1,0,[d(o.editTo,e.chunks),o.editTo,o.origTo])}return r}function g(e,t){if(e.dealigned||t){if(!e.orig.curOp)return e.orig.operation(function(){g(e,t)});e.dealigned=!1;var i=e.mv.left==e?e.mv.right:e.mv.left;i&&(r(i),i.dealigned=!1);for(var o=u(e,i),n=e.mv.aligners,l=0;l<n.length;l++)n[l].clear();n.length=0;var a=[e.orig,e.edit],s=[];i&&a.push(i.orig);for(var l=0;l<a.length;l++)s.push(a[l].getScrollInfo().top);for(var f=0;f<o.length;f++)v(a,o[f],n);for(var l=0;l<a.length;l++)a[l].scrollTo(null,s[l])}}function v(e,t,r){for(var i=0,o=[],n=0;n<e.length;n++)if(null!=t[n]){var l=e[n].heightAtLine(t[n],"local");o[n]=l,i=Math.max(i,l)}for(var n=0;n<e.length;n++)if(null!=t[n]){var a=i-o[n];a>1&&r.push(m(e[n],t[n],a))}}function m(e,t,r){var i=!0;t>e.lastLine()&&(t--,i=!1);var o=document.createElement("div");return o.className="CodeMirror-merge-spacer",o.style.height=r+"px",o.style.minWidth="1px",e.addLineWidget(t,o,{height:r,above:i})}function p(e,t,r,i,o){var n="left"==e.type,l=e.orig.heightAtLine(t.origFrom,"local")-r;if(e.svg){var a=l,s=e.edit.heightAtLine(t.editFrom,"local")-i;if(n){var f=a;a=s,s=f}var c=e.orig.heightAtLine(t.origTo,"local")-r,h=e.edit.heightAtLine(t.editTo,"local")-i;if(n){var f=c;c=h,h=f}var d=" C "+o/2+" "+s+" "+o/2+" "+a+" "+(o+2)+" "+a,u=" C "+o/2+" "+c+" "+o/2+" "+h+" -1 "+h;N(e.svg.appendChild(document.createElementNS(W,"path")),"d","M -1 "+s+d+" L "+(o+2)+" "+c+u+" z","class",e.classes.connect)}if(e.copyButtons){var g=e.copyButtons.appendChild(S("div","left"==e.type?"⇝":"⇜","CodeMirror-merge-copy")),v=e.mv.options.allowEditingOriginals;if(g.title=v?"Push to left":"Revert chunk",g.chunk=t,g.style.top=l+"px",v){var m=e.orig.heightAtLine(t.editFrom,"local")-i,p=e.copyButtons.appendChild(S("div","right"==e.type?"⇝":"⇜","CodeMirror-merge-copy-reverse"));p.title="Push to right",p.chunk={editFrom:t.origFrom,editTo:t.origTo,origFrom:t.editFrom,origTo:t.editTo},p.style.top=m+"px","right"==e.type?p.style.left="2px":p.style.right="2px"}}}function k(e,t,r,i){e.diffOutOfDate||t.replaceRange(r.getRange(U(i.origFrom,0),U(i.origTo,0)),U(i.editFrom,0),U(i.editTo,0))}function C(t){var r=t.lockButton=S("div",null,"CodeMirror-merge-scrolllock");r.title="Toggle locked scrolling";var i=S("div",[r],"CodeMirror-merge-scrolllock-wrap");e.on(r,"click",function(){a(t,!t.lockScroll)});var o=[i];if(t.mv.options.revertButtons!==!1&&(t.copyButtons=S("div",null,"CodeMirror-merge-copybuttons-"+t.type),e.on(t.copyButtons,"click",function(e){var r=e.target||e.srcElement;if(r.chunk)return"CodeMirror-merge-copy-reverse"==r.className?void k(t,t.orig,t.edit,r.chunk):void k(t,t.edit,t.orig,r.chunk)}),o.unshift(t.copyButtons)),"align"!=t.mv.options.connect){var n=document.createElementNS&&document.createElementNS(W,"svg");n&&!n.createSVGRect&&(n=null),t.svg=n,n&&o.push(n)}return t.gap=S("div",o,"CodeMirror-merge-gap")}function T(e){return"string"==typeof e?e:e.getValue()}function F(e,t){var r=Q.diff_main(e,t);Q.diff_cleanupSemantic(r);for(var i=0;i<r.length;++i){var o=r[i];o[1]?i&&r[i-1][0]==o[0]&&(r.splice(i--,1),r[i][1]+=o[1]):r.splice(i--,1)}return r}function w(e){for(var t=[],r=0,i=0,o=U(0,0),n=U(0,0),l=0;l<e.length;++l){var a=e[l],s=a[0];if(s==DIFF_EQUAL){var f=D(e,l)?0:1,c=o.line+f,h=n.line+f;x(o,a[1],null,n);var d=y(e,l)?1:0,u=o.line+d,g=n.line+d;u>c&&(l&&t.push({origFrom:i,origTo:h,editFrom:r,editTo:c}),r=u,i=g)}else x(s==DIFF_INSERT?o:n,a[1])}return(r<=o.line||i<=n.line)&&t.push({origFrom:i,origTo:n.line+1,editFrom:r,editTo:o.line+1}),t}function y(e,t){if(t==e.length-1)return!0;var r=e[t+1][1];return 1!=r.length&&10==r.charCodeAt(0)&&(t==e.length-2||(r=e[t+2][1],r.length>1&&10==r.charCodeAt(0)))}function D(e,t){if(0==t)return!0;var r=e[t-1][1];return 10==r.charCodeAt(r.length-1)&&(1==t||(r=e[t-2][1],10==r.charCodeAt(r.length-1)))}function M(e,t,r){for(var i,o,n,l,a=0;a<e.length;a++){var s=e[a],f=r?s.editFrom:s.origFrom,c=r?s.editTo:s.origTo;null==o&&(f>t?(o=s.editFrom,l=s.origFrom):c>t&&(o=s.editTo,l=s.origTo)),c<=t?(i=s.editTo,n=s.origTo):f<=t&&(i=s.editFrom,n=s.origFrom)}return{edit:{before:i,after:o},orig:{before:n,after:l}}}function L(t,r,i){function o(){l.clear(),t.removeLineClass(r,"wrap","CodeMirror-merge-collapsed-line")}t.addLineClass(r,"wrap","CodeMirror-merge-collapsed-line");var n=document.createElement("span");n.className="CodeMirror-merge-collapsed-widget",n.title="Identical text collapsed. Click to expand.";var l=t.markText(U(r,0),U(i-1),{inclusiveLeft:!0,inclusiveRight:!0,replacedWith:n,clearOnEnter:!0});return e.on(n,"click",o),{mark:l,clear:o}}function I(e,t){function r(){for(var e=0;e<i.length;e++)i[e].clear()}for(var i=[],o=0;o<t.length;o++){var n=t[o],l=L(n.cm,n.line,n.line+e);i.push(l),l.mark.on("clear",r)}return i[0].mark}function b(e,t,r,i){for(var o=0;o<e.chunks.length;o++)for(var n=e.chunks[o],l=n.editFrom-t;l<n.editTo+t;l++){var a=l+r;a>=0&&a<i.length&&(i[a]=!1)}}function E(e,t){"number"!=typeof t&&(t=2);for(var r=[],i=e.editor(),o=i.firstLine(),n=o,l=i.lastLine();n<=l;n++)r.push(!0);e.left&&b(e.left,t,o,r),e.right&&b(e.right,t,o,r);for(var a=0;a<r.length;a++)if(r[a]){for(var s=a+o,f=1;a<r.length-1&&r[a+1];a++,f++);if(f>t){var c=[{line:s,cm:i}];e.left&&c.push({line:d(s,e.left.chunks),cm:e.left.orig}),e.right&&c.push({line:d(s,e.right.chunks),cm:e.right.orig});var h=I(f,c);e.options.onCollapse&&e.options.onCollapse(e,s,f,h)}}}function S(e,t,r,i){var o=document.createElement(e);if(r&&(o.className=r),i&&(o.style.cssText=i),"string"==typeof t)o.appendChild(document.createTextNode(t));else if(t)for(var n=0;n<t.length;++n)o.appendChild(t[n]);return o}function O(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild)}function N(e){for(var t=1;t<arguments.length;t+=2)e.setAttribute(arguments[t],arguments[t+1])}function A(e,t){t||(t={});for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);return t}function x(e,t,r,i){for(var o=r?U(e.line,e.ch):e,n=0;;){var l=t.indexOf("\n",n);if(l==-1)break;++o.line,i&&++i.line,n=l+1}return o.ch=(n?0:o.ch)+(t.length-n),i&&(i.ch=(n?0:i.ch)+(t.length-n)),o}function _(e,t){return(e.line-t.line||e.ch-t.ch)<0?e:t}function B(e,t){return(e.line-t.line||e.ch-t.ch)>0?e:t}function R(e,t){return e.line==t.line&&e.ch==t.ch}function V(e,t,r){for(var i=e.length-1;i>=0;i--){var o=e[i],n=(r?o.origTo:o.editTo)-1;if(n<t)return n}}function H(e,t,r){for(var i=0;i<e.length;i++){var o=e[i],n=r?o.origFrom:o.editFrom;if(n>t)return n}}function P(t,i){var o=null,n=t.state.diffViews,l=t.getCursor().line;if(n)for(var a=0;a<n.length;a++){var s=n[a],f=t==s.orig;r(s);var c=i<0?V(s.chunks,l,f):H(s.chunks,l,f);null==c||null!=o&&!(i<0?c>o:c<o)||(o=c)}return null==o?e.Pass:void t.setCursor(o,0)}var U=e.Pos,W="http://www.w3.org/2000/svg";t.prototype={constructor:t,init:function(t,r,n){this.edit=this.mv.edit,(this.edit.state.diffViews||(this.edit.state.diffViews=[])).push(this),this.orig=e(t,A({value:r,readOnly:!this.mv.options.allowEditingOriginals},A(n))),this.orig.state.diffViews=[this],this.diff=F(T(r),T(n.value)),this.chunks=w(this.diff),this.diffOutOfDate=this.dealigned=!1,this.showDifferences=n.showDifferences!==!1,this.forceUpdate=i(this),a(this,!0,!1),o(this)},setShowDifferences:function(e){e=e!==!1,e!=this.showDifferences&&(this.showDifferences=e,this.forceUpdate("full"))}};var z=!1,j=e.MergeView=function(r,i){if(!(this instanceof j))return new j(r,i);this.options=i;var o=i.origLeft,n=null==i.origRight?i.orig:i.origRight,l=null!=o,a=null!=n,s=1+(l?1:0)+(a?1:0),f=[],c=this.left=null,d=this.right=null,u=this;if(l){c=this.left=new t(this,"left");var v=S("div",null,"CodeMirror-merge-pane");f.push(v),f.push(C(c))}var m=S("div",null,"CodeMirror-merge-pane");if(f.push(m),a){d=this.right=new t(this,"right"),f.push(C(d));var p=S("div",null,"CodeMirror-merge-pane");f.push(p)}(a?p:m).className+=" CodeMirror-merge-pane-rightmost",f.push(S("div",null,null,"height: 0; clear: both;"));var k=this.wrap=r.appendChild(S("div",f,"CodeMirror-merge CodeMirror-merge-"+s+"pane"));this.edit=e(m,A(i)),c&&c.init(v,o,i),d&&d.init(p,n,i),i.collapseIdentical&&this.editor().operation(function(){E(u,i.collapseIdentical)}),"align"==i.connect&&(this.aligners=[],g(this.left||this.right,!0));var T=function(){c&&h(c),d&&h(d)};e.on(window,"resize",T);var F=setInterval(function(){for(var t=k.parentNode;t&&t!=document.body;t=t.parentNode);t||(clearInterval(F),e.off(window,"resize",T))},5e3)};j.prototype={constuctor:j,editor:function(){return this.edit},rightOriginal:function(){return this.right&&this.right.orig},leftOriginal:function(){return this.left&&this.left.orig},setShowDifferences:function(e){this.right&&this.right.setShowDifferences(e),this.left&&this.left.setShowDifferences(e)},rightChunks:function(){if(this.right)return r(this.right),this.right.chunks},leftChunks:function(){if(this.left)return r(this.left),this.left.chunks}};var Q=new diff_match_patch;e.commands.goNextDiff=function(e){return P(e,1)},e.commands.goPrevDiff=function(e){return P(e,-1)}});
1
+ !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","diff_match_patch"],e):e(CodeMirror)}(function(e){"use strict";function t(e,t){this.mv=e,this.type=t,this.classes="left"==t?{chunk:"CodeMirror-merge-l-chunk",start:"CodeMirror-merge-l-chunk-start",end:"CodeMirror-merge-l-chunk-end",insert:"CodeMirror-merge-l-inserted",del:"CodeMirror-merge-l-deleted",connect:"CodeMirror-merge-l-connect"}:{chunk:"CodeMirror-merge-r-chunk",start:"CodeMirror-merge-r-chunk-start",end:"CodeMirror-merge-r-chunk-end",insert:"CodeMirror-merge-r-inserted",del:"CodeMirror-merge-r-deleted",connect:"CodeMirror-merge-r-connect"}}function r(t){t.diffOutOfDate&&(t.diff=y(t.orig.getValue(),t.edit.getValue()),t.chunks=D(t.diff),t.diffOutOfDate=!1,e.signal(t.edit,"updateDiff",t.diff))}function i(e){function t(t){Q=!0,g=!1,"full"==t&&(e.svg&&N(e.svg),e.copyButtons&&N(e.copyButtons),c(e.edit,s.marked,e.classes),c(e.orig,h.marked,e.classes),s.from=s.to=h.from=h.to=0),r(e),e.showDifferences&&(f(e.edit,e.diff,s,DIFF_INSERT,e.classes),f(e.orig,e.diff,h,DIFF_DELETE,e.classes)),"align"==e.mv.options.connect&&v(e),d(e),Q=!1}function i(t){Q||(e.dealigned=!0,o(t))}function o(e){Q||g||(clearTimeout(a),e===!0&&(g=!0),a=setTimeout(t,e===!0?20:250))}function n(t,r){e.diffOutOfDate||(e.diffOutOfDate=!0,s.from=s.to=h.from=h.to=0),i(r.text.length-1!=r.to.line-r.from.line)}function l(){e.diffOutOfDate=!0,t("full")}var a,s={from:0,to:0,marked:[]},h={from:0,to:0,marked:[]},g=!1;return e.edit.on("change",n),e.orig.on("change",n),e.edit.on("swapDoc",l),e.orig.on("swapDoc",l),e.edit.on("markerAdded",i),e.edit.on("markerCleared",i),e.orig.on("markerAdded",i),e.orig.on("markerCleared",i),e.edit.on("viewportChange",function(){o(!1)}),e.orig.on("viewportChange",function(){o(!1)}),t(),t}function o(e){e.edit.on("scroll",function(){n(e,DIFF_INSERT)&&d(e)}),e.orig.on("scroll",function(){n(e,DIFF_DELETE)&&d(e)})}function n(e,t){if(e.diffOutOfDate)return!1;if(!e.lockScroll)return!0;var r,i,o=+new Date;if(t==DIFF_INSERT?(r=e.edit,i=e.orig):(r=e.orig,i=e.edit),r.state.scrollSetBy==e&&(r.state.scrollSetAt||0)+50>o)return!1;var n=r.getScrollInfo();if("align"==e.mv.options.connect)v=n.top;else{var a,s,c=.5*n.clientHeight,f=n.top+c,h=r.lineAtHeight(f,"local"),g=E(e.chunks,h,t==DIFF_INSERT),d=l(r,t==DIFF_INSERT?g.edit:g.orig),u=l(i,t==DIFF_INSERT?g.orig:g.edit),m=(f-d.top)/(d.bot-d.top),v=u.top-c+m*(u.bot-u.top);if(v>n.top&&(s=n.top/c)<1)v=v*s+n.top*(1-s);else if((a=n.height-n.clientHeight-n.top)<c){var p=i.getScrollInfo(),k=p.height-p.clientHeight-v;k>a&&(s=a/c)<1&&(v=v*s+(p.height-p.clientHeight-a)*(1-s))}}return i.scrollTo(n.left,v),i.state.scrollSetAt=o,i.state.scrollSetBy=e,!0}function l(e,t){var r=t.after;return null==r&&(r=e.lastLine()+1),{top:e.heightAtLine(t.before||0,"local"),bot:e.heightAtLine(r,"local")}}function a(e,t,r){e.lockScroll=t,t&&0!=r&&n(e,DIFF_INSERT)&&d(e),e.lockButton.innerHTML=t?"⇛⇚":"⇛&nbsp;&nbsp;⇚"}function s(e,t,r){for(var i=r.classLocation,o=0;o<i.length;o++)e.removeLineClass(t,i[o],r.chunk),e.removeLineClass(t,i[o],r.start),e.removeLineClass(t,i[o],r.end)}function c(t,r,i){for(var o=0;o<r.length;++o){var n=r[o];n instanceof e.TextMarker?n.clear():n.parent&&s(t,n,i)}r.length=0}function f(e,t,r,i,o){var n=e.getViewport();e.operation(function(){r.from==r.to||n.from-r.to>20||r.from-n.to>20?(c(e,r.marked,o),g(e,t,i,r.marked,n.from,n.to,o),r.from=n.from,r.to=n.to):(n.from<r.from&&(g(e,t,i,r.marked,n.from,r.from,o),r.from=n.from),n.to>r.to&&(g(e,t,i,r.marked,r.to,n.to,o),r.to=n.to))})}function h(e,t,r,i,o,n){for(var l=r.classLocation,a=e.getLineHandle(t),s=0;s<l.length;s++)i&&e.addLineClass(a,l[s],r.chunk),o&&e.addLineClass(a,l[s],r.start),n&&e.addLineClass(a,l[s],r.end);return a}function g(e,t,r,i,o,n,l){function a(t,r){for(var a=Math.max(o,t),s=Math.min(n,r),c=a;c<s;++c)i.push(h(e,c,l,!0,c==t,c==r-1));t==r&&a==r&&s==r&&(a?i.push(h(e,a-1,l,!1,!1,!0)):i.push(h(e,a,l,!1,!0,!1)))}for(var s=W(0,0),c=W(o,0),f=e.clipPos(W(n-1)),g=r==DIFF_DELETE?l.del:l.insert,d=0,u=0;u<t.length;++u){var m=t[u],v=m[0],p=m[1];if(v==DIFF_EQUAL){var k=s.line+(L(t,u)?0:1);R(s,p);var C=s.line+(M(t,u)?1:0);C>k&&(u&&a(d,k),d=C)}else if(v==r){var T=R(s,p,!0),F=V(c,s),w=_(f,T);H(F,w)||i.push(e.markText(F,w,{className:g})),s=T}}d<=s.line&&a(d,s.line+1)}function d(e){if(e.showDifferences){if(e.svg){N(e.svg);var t=e.gap.offsetWidth;x(e.svg,"width",t,"height",e.gap.offsetHeight)}e.copyButtons&&N(e.copyButtons);for(var r=e.edit.getViewport(),i=e.orig.getViewport(),o=e.mv.wrap.getBoundingClientRect().top,n=o-e.edit.getScrollerElement().getBoundingClientRect().top+e.edit.getScrollInfo().top,l=o-e.orig.getScrollerElement().getBoundingClientRect().top+e.orig.getScrollInfo().top,a=0;a<e.chunks.length;a++){var s=e.chunks[a];s.editFrom<=r.to&&s.editTo>=r.from&&s.origFrom<=i.to&&s.origTo>=i.from&&C(e,s,l,n,t)}}}function u(e,t){for(var r=0,i=0,o=0;o<t.length;o++){var n=t[o];if(n.editTo>e&&n.editFrom<=e)return null;if(n.editFrom>e)break;r=n.editTo,i=n.origTo}return i+(e-r)}function m(e,t){for(var r=[],i=0;i<e.chunks.length;i++){var o=e.chunks[i];r.push([o.origTo,o.editTo,t?u(o.editTo,t.chunks):null])}if(t)e:for(var i=0;i<t.chunks.length;i++){for(var o=t.chunks[i],n=0;n<r.length;n++){var l=r[n][1]-o.editTo;if(0==l)continue e;if(l>0)break}r.splice(n,0,[u(o.editTo,e.chunks),o.editTo,o.origTo])}return r}function v(e,t){if(e.dealigned||t){if(!e.orig.curOp)return e.orig.operation(function(){v(e,t)});e.dealigned=!1;var i=e.mv.left==e?e.mv.right:e.mv.left;i&&(r(i),i.dealigned=!1);for(var o=m(e,i),n=e.mv.aligners,l=0;l<n.length;l++)n[l].clear();n.length=0;var a=[e.orig,e.edit],s=[];i&&a.push(i.orig);for(var l=0;l<a.length;l++)s.push(a[l].getScrollInfo().top);for(var c=0;c<o.length;c++)p(a,o[c],n);for(var l=0;l<a.length;l++)a[l].scrollTo(null,s[l])}}function p(e,t,r){for(var i=0,o=[],n=0;n<e.length;n++)if(null!=t[n]){var l=e[n].heightAtLine(t[n],"local");o[n]=l,i=Math.max(i,l)}for(var n=0;n<e.length;n++)if(null!=t[n]){var a=i-o[n];a>1&&r.push(k(e[n],t[n],a))}}function k(e,t,r){var i=!0;t>e.lastLine()&&(t--,i=!1);var o=document.createElement("div");return o.className="CodeMirror-merge-spacer",o.style.height=r+"px",o.style.minWidth="1px",e.addLineWidget(t,o,{height:r,above:i})}function C(e,t,r,i,o){var n="left"==e.type,l=e.orig.heightAtLine(t.origFrom,"local",!0)-r;if(e.svg){var a=l,s=e.edit.heightAtLine(t.editFrom,"local",!0)-i;if(n){var c=a;a=s,s=c}var f=e.orig.heightAtLine(t.origTo,"local",!0)-r,h=e.edit.heightAtLine(t.editTo,"local",!0)-i;if(n){var c=f;f=h,h=c}var g=" C "+o/2+" "+s+" "+o/2+" "+a+" "+(o+2)+" "+a,d=" C "+o/2+" "+f+" "+o/2+" "+h+" -1 "+h;x(e.svg.appendChild(document.createElementNS(z,"path")),"d","M -1 "+s+g+" L "+(o+2)+" "+f+d+" z","class",e.classes.connect)}if(e.copyButtons){var u=e.copyButtons.appendChild(A("div","left"==e.type?"⇝":"⇜","CodeMirror-merge-copy")),m=e.mv.options.allowEditingOriginals;if(u.title=m?"Push to left":"Revert chunk",u.chunk=t,u.style.top=(t.origTo>t.origFrom?l:e.edit.heightAtLine(t.editFrom,"local")-i)+"px",m){var v=e.edit.heightAtLine(t.editFrom,"local")-i,p=e.copyButtons.appendChild(A("div","right"==e.type?"⇝":"⇜","CodeMirror-merge-copy-reverse"));p.title="Push to right",p.chunk={editFrom:t.origFrom,editTo:t.origTo,origFrom:t.editFrom,origTo:t.editTo},p.style.top=v+"px","right"==e.type?p.style.left="2px":p.style.right="2px"}}}function T(e,t,r,i){if(!e.diffOutOfDate){var o=i.editTo>t.lastLine()?W(i.editFrom-1):W(i.editFrom,0),n=i.origTo>r.lastLine()?W(i.origFrom-1):W(i.origFrom,0);t.replaceRange(r.getRange(n,W(i.origTo,0)),o,W(i.editTo,0))}}function F(t){var r=t.lockButton=A("div",null,"CodeMirror-merge-scrolllock");r.title="Toggle locked scrolling";var i=A("div",[r],"CodeMirror-merge-scrolllock-wrap");e.on(r,"click",function(){a(t,!t.lockScroll)});var o=[i];if(t.mv.options.revertButtons!==!1&&(t.copyButtons=A("div",null,"CodeMirror-merge-copybuttons-"+t.type),e.on(t.copyButtons,"click",function(e){var r=e.target||e.srcElement;if(r.chunk)return"CodeMirror-merge-copy-reverse"==r.className?void T(t,t.orig,t.edit,r.chunk):void T(t,t.edit,t.orig,r.chunk)}),o.unshift(t.copyButtons)),"align"!=t.mv.options.connect){var n=document.createElementNS&&document.createElementNS(z,"svg");n&&!n.createSVGRect&&(n=null),t.svg=n,n&&o.push(n)}return t.gap=A("div",o,"CodeMirror-merge-gap")}function w(e){return"string"==typeof e?e:e.getValue()}function y(e,t){for(var r=G.diff_main(e,t),i=0;i<r.length;++i){var o=r[i];o[1]?i&&r[i-1][0]==o[0]&&(r.splice(i--,1),r[i][1]+=o[1]):r.splice(i--,1)}return r}function D(e){for(var t=[],r=0,i=0,o=W(0,0),n=W(0,0),l=0;l<e.length;++l){var a=e[l],s=a[0];if(s==DIFF_EQUAL){var c=L(e,l)?0:1,f=o.line+c,h=n.line+c;R(o,a[1],null,n);var g=M(e,l)?1:0,d=o.line+g,u=n.line+g;d>f&&(l&&t.push({origFrom:i,origTo:h,editFrom:r,editTo:f}),r=d,i=u)}else R(s==DIFF_INSERT?o:n,a[1])}return(r<=o.line||i<=n.line)&&t.push({origFrom:i,origTo:n.line+1,editFrom:r,editTo:o.line+1}),t}function M(e,t){if(t==e.length-1)return!0;var r=e[t+1][1];return 1!=r.length&&10==r.charCodeAt(0)&&(t==e.length-2||(r=e[t+2][1],r.length>1&&10==r.charCodeAt(0)))}function L(e,t){if(0==t)return!0;var r=e[t-1][1];return 10==r.charCodeAt(r.length-1)&&(1==t||(r=e[t-2][1],10==r.charCodeAt(r.length-1)))}function E(e,t,r){for(var i,o,n,l,a=0;a<e.length;a++){var s=e[a],c=r?s.editFrom:s.origFrom,f=r?s.editTo:s.origTo;null==o&&(c>t?(o=s.editFrom,l=s.origFrom):f>t&&(o=s.editTo,l=s.origTo)),f<=t?(i=s.editTo,n=s.origTo):c<=t&&(i=s.editFrom,n=s.origFrom)}return{edit:{before:i,after:o},orig:{before:n,after:l}}}function I(t,r,i){function o(){l.clear(),t.removeLineClass(r,"wrap","CodeMirror-merge-collapsed-line")}t.addLineClass(r,"wrap","CodeMirror-merge-collapsed-line");var n=document.createElement("span");n.className="CodeMirror-merge-collapsed-widget",n.title="Identical text collapsed. Click to expand.";var l=t.markText(W(r,0),W(i-1),{inclusiveLeft:!0,inclusiveRight:!0,replacedWith:n,clearOnEnter:!0});return e.on(n,"click",o),{mark:l,clear:o}}function S(e,t){function r(){for(var e=0;e<i.length;e++)i[e].clear()}for(var i=[],o=0;o<t.length;o++){var n=t[o],l=I(n.cm,n.line,n.line+e);i.push(l),l.mark.on("clear",r)}return i[0].mark}function O(e,t,r,i){for(var o=0;o<e.chunks.length;o++)for(var n=e.chunks[o],l=n.editFrom-t;l<n.editTo+t;l++){var a=l+r;a>=0&&a<i.length&&(i[a]=!1)}}function b(e,t){"number"!=typeof t&&(t=2);for(var r=[],i=e.editor(),o=i.firstLine(),n=o,l=i.lastLine();n<=l;n++)r.push(!0);e.left&&O(e.left,t,o,r),e.right&&O(e.right,t,o,r);for(var a=0;a<r.length;a++)if(r[a]){for(var s=a+o,c=1;a<r.length-1&&r[a+1];a++,c++);if(c>t){var f=[{line:s,cm:i}];e.left&&f.push({line:u(s,e.left.chunks),cm:e.left.orig}),e.right&&f.push({line:u(s,e.right.chunks),cm:e.right.orig});var h=S(c,f);e.options.onCollapse&&e.options.onCollapse(e,s,c,h)}}}function A(e,t,r,i){var o=document.createElement(e);if(r&&(o.className=r),i&&(o.style.cssText=i),"string"==typeof t)o.appendChild(document.createTextNode(t));else if(t)for(var n=0;n<t.length;++n)o.appendChild(t[n]);return o}function N(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild)}function x(e){for(var t=1;t<arguments.length;t+=2)e.setAttribute(arguments[t],arguments[t+1])}function B(e,t){t||(t={});for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);return t}function R(e,t,r,i){for(var o=r?W(e.line,e.ch):e,n=0;;){var l=t.indexOf("\n",n);if(l==-1)break;++o.line,i&&++i.line,n=l+1}return o.ch=(n?0:o.ch)+(t.length-n),i&&(i.ch=(n?0:i.ch)+(t.length-n)),o}function _(e,t){return(e.line-t.line||e.ch-t.ch)<0?e:t}function V(e,t){return(e.line-t.line||e.ch-t.ch)>0?e:t}function H(e,t){return e.line==t.line&&e.ch==t.ch}function P(e,t,r){for(var i=e.length-1;i>=0;i--){var o=e[i],n=(r?o.origTo:o.editTo)-1;if(n<t)return n}}function j(e,t,r){for(var i=0;i<e.length;i++){var o=e[i],n=r?o.origFrom:o.editFrom;if(n>t)return n}}function U(t,i){var o=null,n=t.state.diffViews,l=t.getCursor().line;if(n)for(var a=0;a<n.length;a++){var s=n[a],c=t==s.orig;r(s);var f=i<0?P(s.chunks,l,c):j(s.chunks,l,c);null==f||null!=o&&!(i<0?f>o:f<o)||(o=f)}return null==o?e.Pass:void t.setCursor(o,0)}var W=e.Pos,z="http://www.w3.org/2000/svg";t.prototype={constructor:t,init:function(t,r,i){this.edit=this.mv.edit,(this.edit.state.diffViews||(this.edit.state.diffViews=[])).push(this),this.orig=e(t,B({value:r,readOnly:!this.mv.options.allowEditingOriginals},B(i))),this.orig.state.diffViews=[this];var o=i.chunkClassLocation||"background";"[object Array]"!=Object.prototype.toString.call(o)&&(o=[o]),this.classes.classLocation=o,this.diff=y(w(r),w(i.value)),this.chunks=D(this.diff),this.diffOutOfDate=this.dealigned=!1,this.showDifferences=i.showDifferences!==!1},registerEvents:function(){this.forceUpdate=i(this),a(this,!0,!1),o(this)},setShowDifferences:function(e){e=e!==!1,e!=this.showDifferences&&(this.showDifferences=e,this.forceUpdate("full"))}};var Q=!1,q=e.MergeView=function(r,i){if(!(this instanceof q))return new q(r,i);this.options=i;var o=i.origLeft,n=null==i.origRight?i.orig:i.origRight,l=null!=o,a=null!=n,s=1+(l?1:0)+(a?1:0),c=[],f=this.left=null,h=this.right=null,g=this;if(l){f=this.left=new t(this,"left");var u=A("div",null,"CodeMirror-merge-pane CodeMirror-merge-left");c.push(u),c.push(F(f))}var m=A("div",null,"CodeMirror-merge-pane CodeMirror-merge-editor");if(c.push(m),a){h=this.right=new t(this,"right"),c.push(F(h));var p=A("div",null,"CodeMirror-merge-pane CodeMirror-merge-right");c.push(p)}(a?p:m).className+=" CodeMirror-merge-pane-rightmost",c.push(A("div",null,null,"height: 0; clear: both;"));var k=this.wrap=r.appendChild(A("div",c,"CodeMirror-merge CodeMirror-merge-"+s+"pane"));this.edit=e(m,B(i)),f&&f.init(u,o,i),h&&h.init(p,n,i),i.collapseIdentical&&this.editor().operation(function(){b(g,i.collapseIdentical)}),"align"==i.connect&&(this.aligners=[],v(this.left||this.right,!0)),f&&f.registerEvents(),h&&h.registerEvents();var C=function(){f&&d(f),h&&d(h)};e.on(window,"resize",C);var T=setInterval(function(){for(var t=k.parentNode;t&&t!=document.body;t=t.parentNode);t||(clearInterval(T),e.off(window,"resize",C))},5e3)};q.prototype={constructor:q,editor:function(){return this.edit},rightOriginal:function(){return this.right&&this.right.orig},leftOriginal:function(){return this.left&&this.left.orig},setShowDifferences:function(e){this.right&&this.right.setShowDifferences(e),this.left&&this.left.setShowDifferences(e)},rightChunks:function(){if(this.right)return r(this.right),this.right.chunks},leftChunks:function(){if(this.left)return r(this.left),this.left.chunks}};var G=new diff_match_patch;e.commands.goNextDiff=function(e){return U(e,1)},e.commands.goPrevDiff=function(e){return U(e,-1)}});
lib/codemirror/lib/codemirror.css CHANGED
@@ -52,7 +52,7 @@
52
  }
53
  .cm-fat-cursor .CodeMirror-cursor {
54
  width: auto;
55
- border: 0;
56
  background: #7e7;
57
  }
58
  .cm-fat-cursor div.CodeMirror-cursors {
@@ -88,8 +88,14 @@
88
 
89
  .cm-tab { display: inline-block; text-decoration: inherit; }
90
 
 
 
 
 
 
91
  .CodeMirror-ruler {
92
  border-left: 1px solid #ccc;
 
93
  position: absolute;
94
  }
95
 
@@ -191,16 +197,15 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
191
 
192
  .CodeMirror-gutters {
193
  position: absolute; left: 0; top: 0;
 
194
  z-index: 3;
195
  }
196
  .CodeMirror-gutter {
197
  white-space: normal;
198
  height: 100%;
199
  display: inline-block;
 
200
  margin-bottom: -30px;
201
- /* Hack to make IE7 behave */
202
- *zoom:1;
203
- *display:inline;
204
  }
205
  .CodeMirror-gutter-wrapper {
206
  position: absolute;
@@ -244,6 +249,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
244
  position: relative;
245
  overflow: visible;
246
  -webkit-tap-highlight-color: transparent;
 
 
247
  }
248
  .CodeMirror-wrap pre {
249
  word-wrap: break-word;
@@ -287,7 +294,10 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
287
  visibility: hidden;
288
  }
289
 
290
- .CodeMirror-cursor { position: absolute; }
 
 
 
291
  .CodeMirror-measure pre { position: static; }
292
 
293
  div.CodeMirror-cursors {
@@ -314,9 +324,6 @@ div.CodeMirror-dragcursors {
314
  background: rgba(255, 255, 0, .4);
315
  }
316
 
317
- /* IE7 hack to prevent it from returning funny offsetTops on the spans */
318
- .CodeMirror span { *vertical-align: text-bottom; }
319
-
320
  /* Used to force a border model for a node */
321
  .cm-force-border { padding-right: .1px; }
322
 
52
  }
53
  .cm-fat-cursor .CodeMirror-cursor {
54
  width: auto;
55
+ border: 0 !important;
56
  background: #7e7;
57
  }
58
  .cm-fat-cursor div.CodeMirror-cursors {
88
 
89
  .cm-tab { display: inline-block; text-decoration: inherit; }
90
 
91
+ .CodeMirror-rulers {
92
+ position: absolute;
93
+ left: 0; right: 0; top: -50px; bottom: -20px;
94
+ overflow: hidden;
95
+ }
96
  .CodeMirror-ruler {
97
  border-left: 1px solid #ccc;
98
+ top: 0; bottom: 0;
99
  position: absolute;
100
  }
101
 
197
 
198
  .CodeMirror-gutters {
199
  position: absolute; left: 0; top: 0;
200
+ min-height: 100%;
201
  z-index: 3;
202
  }
203
  .CodeMirror-gutter {
204
  white-space: normal;
205
  height: 100%;
206
  display: inline-block;
207
+ vertical-align: top;
208
  margin-bottom: -30px;
 
 
 
209
  }
210
  .CodeMirror-gutter-wrapper {
211
  position: absolute;
249
  position: relative;
250
  overflow: visible;
251
  -webkit-tap-highlight-color: transparent;
252
+ -webkit-font-variant-ligatures: contextual;
253
+ font-variant-ligatures: contextual;
254
  }
255
  .CodeMirror-wrap pre {
256
  word-wrap: break-word;
294
  visibility: hidden;
295
  }
296
 
297
+ .CodeMirror-cursor {
298
+ position: absolute;
299
+ pointer-events: none;
300
+ }
301
  .CodeMirror-measure pre { position: static; }
302
 
303
  div.CodeMirror-cursors {
324
  background: rgba(255, 255, 0, .4);
325
  }
326
 
 
 
 
327
  /* Used to force a border model for a node */
328
  .cm-force-border { padding-right: .1px; }
329
 
lib/codemirror/lib/codemirror.js CHANGED
@@ -7,8881 +7,9107 @@
7
  // You can find some technical background for some of the code below
8
  // at http://marijnhaverbeke.nl/blog/#cm-internals .
9
 
10
- (function(mod) {
11
- if (typeof exports == "object" && typeof module == "object") // CommonJS
12
- module.exports = mod();
13
- else if (typeof define == "function" && define.amd) // AMD
14
- return define([], mod);
15
- else // Plain browser env
16
- (this || window).CodeMirror = mod();
17
- })(function() {
18
- "use strict";
19
-
20
- // BROWSER SNIFFING
21
-
22
- // Kludges for bugs and behavior differences that can't be feature
23
- // detected are enabled based on userAgent etc sniffing.
24
- var userAgent = navigator.userAgent;
25
- var platform = navigator.platform;
26
-
27
- var gecko = /gecko\/\d/i.test(userAgent);
28
- var ie_upto10 = /MSIE \d/.test(userAgent);
29
- var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
30
- var ie = ie_upto10 || ie_11up;
31
- var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
32
- var webkit = /WebKit\//.test(userAgent);
33
- var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
34
- var chrome = /Chrome\//.test(userAgent);
35
- var presto = /Opera\//.test(userAgent);
36
- var safari = /Apple Computer/.test(navigator.vendor);
37
- var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
38
- var phantom = /PhantomJS/.test(userAgent);
39
-
40
- var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
41
- // This is woefully incomplete. Suggestions for alternative methods welcome.
42
- var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
43
- var mac = ios || /Mac/.test(platform);
44
- var windows = /win/i.test(platform);
45
-
46
- var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
47
- if (presto_version) presto_version = Number(presto_version[1]);
48
- if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
49
- // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
50
- var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
51
- var captureRightClick = gecko || (ie && ie_version >= 9);
52
-
53
- // Optimize some code when these features are not used.
54
- var sawReadOnlySpans = false, sawCollapsedSpans = false;
55
-
56
- // EDITOR CONSTRUCTOR
57
-
58
- // A CodeMirror instance represents an editor. This is the object
59
- // that user code is usually dealing with.
60
-
61
- function CodeMirror(place, options) {
62
- if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
63
-
64
- this.options = options = options ? copyObj(options) : {};
65
- // Determine effective options based on given values and defaults.
66
- copyObj(defaults, options, false);
67
- setGuttersForLineNumbers(options);
68
-
69
- var doc = options.value;
70
- if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator);
71
- this.doc = doc;
72
-
73
- var input = new CodeMirror.inputStyles[options.inputStyle](this);
74
- var display = this.display = new Display(place, doc, input);
75
- display.wrapper.CodeMirror = this;
76
- updateGutters(this);
77
- themeChanged(this);
78
- if (options.lineWrapping)
79
- this.display.wrapper.className += " CodeMirror-wrap";
80
- if (options.autofocus && !mobile) display.input.focus();
81
- initScrollbars(this);
82
-
83
- this.state = {
84
- keyMaps: [], // stores maps added by addKeyMap
85
- overlays: [], // highlighting overlays, as added by addOverlay
86
- modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
87
- overwrite: false,
88
- delayingBlurEvent: false,
89
- focused: false,
90
- suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
91
- pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
92
- selectingText: false,
93
- draggingText: false,
94
- highlight: new Delayed(), // stores highlight worker timeout
95
- keySeq: null, // Unfinished key sequence
96
- specialChars: null
97
- };
98
-
99
- var cm = this;
100
-
101
- // Override magic textarea content restore that IE sometimes does
102
- // on our hidden textarea on reload
103
- if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);
104
-
105
- registerEventHandlers(this);
106
- ensureGlobalHandlers();
107
-
108
- startOperation(this);
109
- this.curOp.forceUpdate = true;
110
- attachDoc(this, doc);
111
-
112
- if ((options.autofocus && !mobile) || cm.hasFocus())
113
- setTimeout(bind(onFocus, this), 20);
114
- else
115
- onBlur(this);
116
-
117
- for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
118
- optionHandlers[opt](this, options[opt], Init);
119
- maybeUpdateLineNumberWidth(this);
120
- if (options.finishInit) options.finishInit(this);
121
- for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
122
- endOperation(this);
123
- // Suppress optimizelegibility in Webkit, since it breaks text
124
- // measuring on line wrapping boundaries.
125
- if (webkit && options.lineWrapping &&
126
- getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
127
- display.lineDiv.style.textRendering = "auto";
128
- }
129
-
130
- // DISPLAY CONSTRUCTOR
131
-
132
- // The display handles the DOM integration, both for input reading
133
- // and content drawing. It holds references to DOM nodes and
134
- // display-related state.
135
-
136
- function Display(place, doc, input) {
137
- var d = this;
138
- this.input = input;
139
-
140
- // Covers bottom-right square when both scrollbars are present.
141
- d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
142
- d.scrollbarFiller.setAttribute("cm-not-content", "true");
143
- // Covers bottom of gutter when coverGutterNextToScrollbar is on
144
- // and h scrollbar is present.
145
- d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
146
- d.gutterFiller.setAttribute("cm-not-content", "true");
147
- // Will contain the actual code, positioned to cover the viewport.
148
- d.lineDiv = elt("div", null, "CodeMirror-code");
149
- // Elements are added to these to represent selection and cursors.
150
- d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
151
- d.cursorDiv = elt("div", null, "CodeMirror-cursors");
152
- // A visibility: hidden element used to find the size of things.
153
- d.measure = elt("div", null, "CodeMirror-measure");
154
- // When lines outside of the viewport are measured, they are drawn in this.
155
- d.lineMeasure = elt("div", null, "CodeMirror-measure");
156
- // Wraps everything that needs to exist inside the vertically-padded coordinate system
157
- d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
158
- null, "position: relative; outline: none");
159
- // Moved around its parent to cover visible view.
160
- d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
161
- // Set to the height of the document, allowing scrolling.
162
- d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
163
- d.sizerWidth = null;
164
- // Behavior of elts with overflow: auto and padding is
165
- // inconsistent across browsers. This is used to ensure the
166
- // scrollable area is big enough.
167
- d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
168
- // Will contain the gutters, if any.
169
- d.gutters = elt("div", null, "CodeMirror-gutters");
170
- d.lineGutter = null;
171
- // Actual scrollable element.
172
- d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
173
- d.scroller.setAttribute("tabIndex", "-1");
174
- // The element in which the editor lives.
175
- d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
176
-
177
- // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
178
- if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
179
- if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;
180
-
181
- if (place) {
182
- if (place.appendChild) place.appendChild(d.wrapper);
183
- else place(d.wrapper);
184
- }
185
-
186
- // Current rendered range (may be bigger than the view window).
187
- d.viewFrom = d.viewTo = doc.first;
188
- d.reportedViewFrom = d.reportedViewTo = doc.first;
189
- // Information about the rendered lines.
190
- d.view = [];
191
- d.renderedView = null;
192
- // Holds info about a single rendered line when it was rendered
193
- // for measurement, while not in view.
194
- d.externalMeasured = null;
195
- // Empty space (in pixels) above the view
196
- d.viewOffset = 0;
197
- d.lastWrapHeight = d.lastWrapWidth = 0;
198
- d.updateLineNumbers = null;
199
-
200
- d.nativeBarWidth = d.barHeight = d.barWidth = 0;
201
- d.scrollbarsClipped = false;
202
-
203
- // Used to only resize the line number gutter when necessary (when
204
- // the amount of lines crosses a boundary that makes its width change)
205
- d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
206
- // Set to true when a non-horizontal-scrolling line widget is
207
- // added. As an optimization, line widget aligning is skipped when
208
- // this is false.
209
- d.alignWidgets = false;
210
-
211
- d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
212
-
213
- // Tracks the maximum line length so that the horizontal scrollbar
214
- // can be kept static when scrolling.
215
- d.maxLine = null;
216
- d.maxLineLength = 0;
217
- d.maxLineChanged = false;
218
-
219
- // Used for measuring wheel scrolling granularity
220
- d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
221
-
222
- // True when shift is held down.
223
- d.shift = false;
224
-
225
- // Used to track whether anything happened since the context menu
226
- // was opened.
227
- d.selForContextMenu = null;
228
-
229
- d.activeTouch = null;
230
-
231
- input.init(d);
232
- }
233
-
234
- // STATE UPDATES
235
-
236
- // Used to get the editor into a consistent state again when options change.
237
-
238
- function loadMode(cm) {
239
- cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
240
- resetModeState(cm);
241
- }
242
-
243
- function resetModeState(cm) {
244
- cm.doc.iter(function(line) {
245
- if (line.stateAfter) line.stateAfter = null;
246
- if (line.styles) line.styles = null;
247
- });
248
- cm.doc.frontier = cm.doc.first;
249
- startWorker(cm, 100);
250
- cm.state.modeGen++;
251
- if (cm.curOp) regChange(cm);
252
- }
253
-
254
- function wrappingChanged(cm) {
255
- if (cm.options.lineWrapping) {
256
- addClass(cm.display.wrapper, "CodeMirror-wrap");
257
- cm.display.sizer.style.minWidth = "";
258
- cm.display.sizerWidth = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  } else {
260
- rmClass(cm.display.wrapper, "CodeMirror-wrap");
261
- findMaxLine(cm);
262
- }
263
- estimateLineHeights(cm);
264
- regChange(cm);
265
- clearCaches(cm);
266
- setTimeout(function(){updateScrollbars(cm);}, 100);
267
- }
268
-
269
- // Returns a function that estimates the height of a line, to use as
270
- // first approximation until the line becomes visible (and is thus
271
- // properly measurable).
272
- function estimateHeight(cm) {
273
- var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
274
- var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
275
- return function(line) {
276
- if (lineIsHidden(cm.doc, line)) return 0;
277
-
278
- var widgetsHeight = 0;
279
- if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {
280
- if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;
281
- }
282
-
283
- if (wrapping)
284
- return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
285
  else
286
- return widgetsHeight + th;
287
- };
288
- }
289
-
290
- function estimateLineHeights(cm) {
291
- var doc = cm.doc, est = estimateHeight(cm);
292
- doc.iter(function(line) {
293
- var estHeight = est(line);
294
- if (estHeight != line.height) updateLineHeight(line, estHeight);
295
- });
296
- }
297
-
298
- function themeChanged(cm) {
299
- cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
300
- cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
301
- clearCaches(cm);
302
- }
303
-
304
- function guttersChanged(cm) {
305
- updateGutters(cm);
306
- regChange(cm);
307
- setTimeout(function(){alignHorizontally(cm);}, 20);
308
- }
309
-
310
- // Rebuild the gutter elements, ensure the margin to the left of the
311
- // code matches their width.
312
- function updateGutters(cm) {
313
- var gutters = cm.display.gutters, specs = cm.options.gutters;
314
- removeChildren(gutters);
315
- for (var i = 0; i < specs.length; ++i) {
316
- var gutterClass = specs[i];
317
- var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
318
- if (gutterClass == "CodeMirror-linenumbers") {
319
- cm.display.lineGutter = gElt;
320
- gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
321
- }
322
- }
323
- gutters.style.display = i ? "" : "none";
324
- updateGutterSpace(cm);
325
- }
326
-
327
- function updateGutterSpace(cm) {
328
- var width = cm.display.gutters.offsetWidth;
329
- cm.display.sizer.style.marginLeft = width + "px";
330
- }
331
-
332
- // Compute the character length of a line, taking into account
333
- // collapsed ranges (see markText) that might hide parts, and join
334
- // other lines onto it.
335
- function lineLength(line) {
336
- if (line.height == 0) return 0;
337
- var len = line.text.length, merged, cur = line;
338
- while (merged = collapsedSpanAtStart(cur)) {
339
- var found = merged.find(0, true);
340
- cur = found.from.line;
341
- len += found.from.ch - found.to.ch;
342
- }
343
- cur = line;
344
- while (merged = collapsedSpanAtEnd(cur)) {
345
- var found = merged.find(0, true);
346
- len -= cur.text.length - found.from.ch;
347
- cur = found.to.line;
348
- len += cur.text.length - found.to.ch;
349
- }
350
- return len;
351
- }
352
-
353
- // Find the longest line in the document.
354
- function findMaxLine(cm) {
355
- var d = cm.display, doc = cm.doc;
356
- d.maxLine = getLine(doc, doc.first);
357
- d.maxLineLength = lineLength(d.maxLine);
358
- d.maxLineChanged = true;
359
- doc.iter(function(line) {
360
- var len = lineLength(line);
361
- if (len > d.maxLineLength) {
362
- d.maxLineLength = len;
363
- d.maxLine = line;
364
- }
365
- });
366
- }
367
-
368
- // Make sure the gutters options contains the element
369
- // "CodeMirror-linenumbers" when the lineNumbers option is true.
370
- function setGuttersForLineNumbers(options) {
371
- var found = indexOf(options.gutters, "CodeMirror-linenumbers");
372
- if (found == -1 && options.lineNumbers) {
373
- options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
374
- } else if (found > -1 && !options.lineNumbers) {
375
- options.gutters = options.gutters.slice(0);
376
- options.gutters.splice(found, 1);
377
- }
378
- }
379
-
380
- // SCROLLBARS
381
-
382
- // Prepare DOM reads needed to update the scrollbars. Done in one
383
- // shot to minimize update/measure roundtrips.
384
- function measureForScrollbars(cm) {
385
- var d = cm.display, gutterW = d.gutters.offsetWidth;
386
- var docH = Math.round(cm.doc.height + paddingVert(cm.display));
387
- return {
388
- clientHeight: d.scroller.clientHeight,
389
- viewHeight: d.wrapper.clientHeight,
390
- scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
391
- viewWidth: d.wrapper.clientWidth,
392
- barLeft: cm.options.fixedGutter ? gutterW : 0,
393
- docHeight: docH,
394
- scrollHeight: docH + scrollGap(cm) + d.barHeight,
395
- nativeBarWidth: d.nativeBarWidth,
396
- gutterWidth: gutterW
397
- };
398
- }
399
-
400
- function NativeScrollbars(place, scroll, cm) {
401
- this.cm = cm;
402
- var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
403
- var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
404
- place(vert); place(horiz);
405
-
406
- on(vert, "scroll", function() {
407
- if (vert.clientHeight) scroll(vert.scrollTop, "vertical");
408
- });
409
- on(horiz, "scroll", function() {
410
- if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
411
- });
412
-
413
- this.checkedZeroWidth = false;
414
- // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
415
- if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
416
- }
417
-
418
- NativeScrollbars.prototype = copyObj({
419
- update: function(measure) {
420
- var needsH = measure.scrollWidth > measure.clientWidth + 1;
421
- var needsV = measure.scrollHeight > measure.clientHeight + 1;
422
- var sWidth = measure.nativeBarWidth;
423
-
424
- if (needsV) {
425
- this.vert.style.display = "block";
426
- this.vert.style.bottom = needsH ? sWidth + "px" : "0";
427
- var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
428
- // A bug in IE8 can cause this value to be negative, so guard it.
429
- this.vert.firstChild.style.height =
430
- Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
 
 
 
 
 
 
431
  } else {
432
- this.vert.style.display = "";
433
- this.vert.firstChild.style.height = "0";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
  }
435
-
436
- if (needsH) {
437
- this.horiz.style.display = "block";
438
- this.horiz.style.right = needsV ? sWidth + "px" : "0";
439
- this.horiz.style.left = measure.barLeft + "px";
440
- var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
441
- this.horiz.firstChild.style.width =
442
- (measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  } else {
444
- this.horiz.style.display = "";
445
- this.horiz.firstChild.style.width = "0";
 
 
446
  }
 
 
447
 
448
- if (!this.checkedZeroWidth && measure.clientHeight > 0) {
449
- if (sWidth == 0) this.zeroWidthHack();
450
- this.checkedZeroWidth = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
  }
 
 
452
 
453
- return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
454
- },
455
- setScrollLeft: function(pos) {
456
- if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
457
- if (this.disableHoriz) this.enableZeroWidthBar(this.horiz, this.disableHoriz);
458
- },
459
- setScrollTop: function(pos) {
460
- if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
461
- if (this.disableVert) this.enableZeroWidthBar(this.vert, this.disableVert);
462
- },
463
- zeroWidthHack: function() {
464
- var w = mac && !mac_geMountainLion ? "12px" : "18px";
465
- this.horiz.style.height = this.vert.style.width = w;
466
- this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none";
467
- this.disableHoriz = new Delayed;
468
- this.disableVert = new Delayed;
469
- },
470
- enableZeroWidthBar: function(bar, delay) {
471
- bar.style.pointerEvents = "auto";
472
- function maybeDisable() {
473
- // To find out whether the scrollbar is still visible, we
474
- // check whether the element under the pixel in the bottom
475
- // left corner of the scrollbar box is the scrollbar box
476
- // itself (when the bar is still visible) or its filler child
477
- // (when the bar is hidden). If it is still visible, we keep
478
- // it enabled, if it's hidden, we disable pointer events.
479
- var box = bar.getBoundingClientRect();
480
- var elt = document.elementFromPoint(box.left + 1, box.bottom - 1);
481
- if (elt != bar) bar.style.pointerEvents = "none";
482
- else delay.set(1000, maybeDisable);
483
- }
484
- delay.set(1000, maybeDisable);
485
- },
486
- clear: function() {
487
- var parent = this.horiz.parentNode;
488
- parent.removeChild(this.horiz);
489
- parent.removeChild(this.vert);
490
- }
491
- }, NativeScrollbars.prototype);
492
-
493
- function NullScrollbars() {}
494
-
495
- NullScrollbars.prototype = copyObj({
496
- update: function() { return {bottom: 0, right: 0}; },
497
- setScrollLeft: function() {},
498
- setScrollTop: function() {},
499
- clear: function() {}
500
- }, NullScrollbars.prototype);
501
-
502
- CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
503
-
504
- function initScrollbars(cm) {
505
- if (cm.display.scrollbars) {
506
- cm.display.scrollbars.clear();
507
- if (cm.display.scrollbars.addClass)
508
- rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);
509
- }
510
-
511
- cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
512
- cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
513
- // Prevent clicks in the scrollbars from killing focus
514
- on(node, "mousedown", function() {
515
- if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);
516
- });
517
- node.setAttribute("cm-not-content", "true");
518
- }, function(pos, axis) {
519
- if (axis == "horizontal") setScrollLeft(cm, pos);
520
- else setScrollTop(cm, pos);
521
- }, cm);
522
- if (cm.display.scrollbars.addClass)
523
- addClass(cm.display.wrapper, cm.display.scrollbars.addClass);
524
- }
525
-
526
- function updateScrollbars(cm, measure) {
527
- if (!measure) measure = measureForScrollbars(cm);
528
- var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
529
- updateScrollbarsInner(cm, measure);
530
- for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
531
- if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
532
- updateHeightsInViewport(cm);
533
- updateScrollbarsInner(cm, measureForScrollbars(cm));
534
- startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
535
- }
536
- }
537
-
538
- // Re-synchronize the fake scrollbars with the actual size of the
539
- // content.
540
- function updateScrollbarsInner(cm, measure) {
541
- var d = cm.display;
542
- var sizes = d.scrollbars.update(measure);
543
-
544
- d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
545
- d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
546
-
547
- if (sizes.right && sizes.bottom) {
548
- d.scrollbarFiller.style.display = "block";
549
- d.scrollbarFiller.style.height = sizes.bottom + "px";
550
- d.scrollbarFiller.style.width = sizes.right + "px";
551
- } else d.scrollbarFiller.style.display = "";
552
- if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
553
- d.gutterFiller.style.display = "block";
554
- d.gutterFiller.style.height = sizes.bottom + "px";
555
- d.gutterFiller.style.width = measure.gutterWidth + "px";
556
- } else d.gutterFiller.style.display = "";
557
- }
558
-
559
- // Compute the lines that are visible in a given viewport (defaults
560
- // the the current scroll position). viewport may contain top,
561
- // height, and ensure (see op.scrollToPos) properties.
562
- function visibleLines(display, doc, viewport) {
563
- var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
564
- top = Math.floor(top - paddingTop(display));
565
- var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
566
-
567
- var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
568
- // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
569
- // forces those lines into the viewport (if possible).
570
- if (viewport && viewport.ensure) {
571
- var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
572
- if (ensureFrom < from) {
573
- from = ensureFrom;
574
- to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
575
- } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
576
- from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
577
- to = ensureTo;
578
  }
579
  }
580
- return {from: from, to: Math.max(to, from + 1)};
581
- }
582
-
583
- // LINE NUMBERS
584
-
585
- // Re-align line numbers and gutter marks to compensate for
586
- // horizontal scrolling.
587
- function alignHorizontally(cm) {
588
- var display = cm.display, view = display.view;
589
- if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
590
- var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
591
- var gutterW = display.gutters.offsetWidth, left = comp + "px";
592
- for (var i = 0; i < view.length; i++) if (!view[i].hidden) {
593
- if (cm.options.fixedGutter && view[i].gutter)
594
- view[i].gutter.style.left = left;
595
- var align = view[i].alignable;
596
- if (align) for (var j = 0; j < align.length; j++)
597
- align[j].style.left = left;
598
- }
599
- if (cm.options.fixedGutter)
600
- display.gutters.style.left = (comp + gutterW) + "px";
601
- }
602
-
603
- // Used to ensure that the line number gutter is still the right
604
- // size for the current document size. Returns true when an update
605
- // is needed.
606
- function maybeUpdateLineNumberWidth(cm) {
607
- if (!cm.options.lineNumbers) return false;
608
- var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
609
- if (last.length != display.lineNumChars) {
610
- var test = display.measure.appendChild(elt("div", [elt("div", last)],
611
- "CodeMirror-linenumber CodeMirror-gutter-elt"));
612
- var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
613
- display.lineGutter.style.width = "";
614
- display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
615
- display.lineNumWidth = display.lineNumInnerWidth + padding;
616
- display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
617
- display.lineGutter.style.width = display.lineNumWidth + "px";
618
- updateGutterSpace(cm);
619
- return true;
620
- }
621
- return false;
622
- }
623
-
624
- function lineNumberFor(options, i) {
625
- return String(options.lineNumberFormatter(i + options.firstLineNumber));
626
- }
627
-
628
- // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
629
- // but using getBoundingClientRect to get a sub-pixel-accurate
630
- // result.
631
- function compensateForHScroll(display) {
632
- return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
633
- }
634
-
635
- // DISPLAY DRAWING
636
-
637
- function DisplayUpdate(cm, viewport, force) {
638
- var display = cm.display;
639
-
640
- this.viewport = viewport;
641
- // Store some values that we'll need later (but don't want to force a relayout for)
642
- this.visible = visibleLines(display, cm.doc, viewport);
643
- this.editorIsHidden = !display.wrapper.offsetWidth;
644
- this.wrapperHeight = display.wrapper.clientHeight;
645
- this.wrapperWidth = display.wrapper.clientWidth;
646
- this.oldDisplayWidth = displayWidth(cm);
647
- this.force = force;
648
- this.dims = getDimensions(cm);
649
- this.events = [];
650
- }
651
-
652
- DisplayUpdate.prototype.signal = function(emitter, type) {
653
- if (hasHandler(emitter, type))
654
- this.events.push(arguments);
655
- };
656
- DisplayUpdate.prototype.finish = function() {
657
- for (var i = 0; i < this.events.length; i++)
658
- signal.apply(null, this.events[i]);
659
- };
660
-
661
- function maybeClipScrollbars(cm) {
662
- var display = cm.display;
663
- if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
664
- display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
665
- display.heightForcer.style.height = scrollGap(cm) + "px";
666
- display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
667
- display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
668
- display.scrollbarsClipped = true;
669
- }
670
- }
671
-
672
- // Does the actual updating of the line display. Bails out
673
- // (returning false) when there is nothing to be done and forced is
674
- // false.
675
- function updateDisplayIfNeeded(cm, update) {
676
- var display = cm.display, doc = cm.doc;
677
-
678
- if (update.editorIsHidden) {
679
- resetView(cm);
680
- return false;
681
- }
682
-
683
- // Bail out if the visible area is already rendered and nothing changed.
684
- if (!update.force &&
685
- update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
686
- (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
687
- display.renderedView == display.view && countDirtyView(cm) == 0)
688
- return false;
689
-
690
- if (maybeUpdateLineNumberWidth(cm)) {
691
- resetView(cm);
692
- update.dims = getDimensions(cm);
693
- }
694
-
695
- // Compute a suitable new viewport (from & to)
696
- var end = doc.first + doc.size;
697
- var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
698
- var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
699
- if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
700
- if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
701
- if (sawCollapsedSpans) {
702
- from = visualLineNo(cm.doc, from);
703
- to = visualLineEndNo(cm.doc, to);
704
- }
705
-
706
- var different = from != display.viewFrom || to != display.viewTo ||
707
- display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
708
- adjustView(cm, from, to);
709
-
710
- display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
711
- // Position the mover div to align with the current scroll position
712
- cm.display.mover.style.top = display.viewOffset + "px";
713
-
714
- var toUpdate = countDirtyView(cm);
715
- if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
716
- (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
717
- return false;
718
-
719
- // For big changes, we hide the enclosing element during the
720
- // update, since that speeds up the operations on most browsers.
721
- var focused = activeElt();
722
- if (toUpdate > 4) display.lineDiv.style.display = "none";
723
- patchDisplay(cm, display.updateLineNumbers, update.dims);
724
- if (toUpdate > 4) display.lineDiv.style.display = "";
725
- display.renderedView = display.view;
726
- // There might have been a widget with a focused element that got
727
- // hidden or updated, if so re-focus it.
728
- if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();
729
-
730
- // Prevent selection and cursors from interfering with the scroll
731
- // width and height.
732
- removeChildren(display.cursorDiv);
733
- removeChildren(display.selectionDiv);
734
- display.gutters.style.height = display.sizer.style.minHeight = 0;
735
-
736
- if (different) {
737
- display.lastWrapHeight = update.wrapperHeight;
738
- display.lastWrapWidth = update.wrapperWidth;
739
- startWorker(cm, 400);
740
- }
741
 
742
- display.updateLineNumbers = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
743
 
744
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
  }
746
-
747
- function postUpdateDisplay(cm, update) {
748
- var viewport = update.viewport;
749
- for (var first = true;; first = false) {
750
- if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
751
- // Clip forced viewport to actual scrollable area.
752
- if (viewport && viewport.top != null)
753
- viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
754
- // Updated line heights might result in the drawn area not
755
- // actually covering the viewport. Keep looping until it does.
756
- update.visible = visibleLines(cm.display, cm.doc, viewport);
757
- if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
758
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
759
  }
760
- if (!updateDisplayIfNeeded(cm, update)) break;
761
- updateHeightsInViewport(cm);
762
- var barMeasure = measureForScrollbars(cm);
763
- updateSelection(cm);
764
- setDocumentHeight(cm, barMeasure);
765
- updateScrollbars(cm, barMeasure);
766
- }
767
-
768
- update.signal(cm, "update", cm);
769
- if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
770
- update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
771
- cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
772
- }
773
- }
774
-
775
- function updateDisplaySimple(cm, viewport) {
776
- var update = new DisplayUpdate(cm, viewport);
777
- if (updateDisplayIfNeeded(cm, update)) {
778
- updateHeightsInViewport(cm);
779
- postUpdateDisplay(cm, update);
780
- var barMeasure = measureForScrollbars(cm);
781
- updateSelection(cm);
782
- setDocumentHeight(cm, barMeasure);
783
- updateScrollbars(cm, barMeasure);
784
- update.finish();
785
- }
786
- }
787
-
788
- function setDocumentHeight(cm, measure) {
789
- cm.display.sizer.style.minHeight = measure.docHeight + "px";
790
- var total = measure.docHeight + cm.display.barHeight;
791
- cm.display.heightForcer.style.top = total + "px";
792
- cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";
793
- }
794
-
795
- // Read the actual heights of the rendered lines, and update their
796
- // stored heights to match.
797
- function updateHeightsInViewport(cm) {
798
- var display = cm.display;
799
- var prevBottom = display.lineDiv.offsetTop;
800
- for (var i = 0; i < display.view.length; i++) {
801
- var cur = display.view[i], height;
802
- if (cur.hidden) continue;
803
- if (ie && ie_version < 8) {
804
- var bot = cur.node.offsetTop + cur.node.offsetHeight;
805
- height = bot - prevBottom;
806
- prevBottom = bot;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
807
  } else {
808
- var box = cur.node.getBoundingClientRect();
809
- height = box.bottom - box.top;
810
- }
811
- var diff = cur.line.height - height;
812
- if (height < 2) height = textHeight(display);
813
- if (diff > .001 || diff < -.001) {
814
- updateLineHeight(cur.line, height);
815
- updateWidgetHeight(cur.line);
816
- if (cur.rest) for (var j = 0; j < cur.rest.length; j++)
817
- updateWidgetHeight(cur.rest[j]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
  }
819
  }
820
  }
821
 
822
- // Read and store the height of line widgets associated with the
823
- // given line.
824
- function updateWidgetHeight(line) {
825
- if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
826
- line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight;
827
- }
828
-
829
- // Do a bulk-read of the DOM positions and sizes needed to draw the
830
- // view, so that we don't interleave reading and writing to the DOM.
831
- function getDimensions(cm) {
832
- var d = cm.display, left = {}, width = {};
833
- var gutterLeft = d.gutters.clientLeft;
834
- for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
835
- left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
836
- width[cm.options.gutters[i]] = n.clientWidth;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
837
  }
838
- return {fixedPos: compensateForHScroll(d),
839
- gutterTotalWidth: d.gutters.offsetWidth,
840
- gutterLeft: left,
841
- gutterWidth: width,
842
- wrapperWidth: d.wrapper.clientWidth};
843
- }
844
-
845
- // Sync the actual display DOM structure with display.view, removing
846
- // nodes for lines that are no longer in view, and creating the ones
847
- // that are not there yet, and updating the ones that are out of
848
- // date.
849
- function patchDisplay(cm, updateNumbersFrom, dims) {
850
- var display = cm.display, lineNumbers = cm.options.lineNumbers;
851
- var container = display.lineDiv, cur = container.firstChild;
852
-
853
- function rm(node) {
854
- var next = node.nextSibling;
855
- // Works around a throw-scroll bug in OS X Webkit
856
- if (webkit && mac && cm.display.currentWheelTarget == node)
857
- node.style.display = "none";
858
- else
859
- node.parentNode.removeChild(node);
860
- return next;
861
- }
862
-
863
- var view = display.view, lineN = display.viewFrom;
864
- // Loop over the elements in the view, syncing cur (the DOM nodes
865
- // in display.lineDiv) with the view as we go.
866
- for (var i = 0; i < view.length; i++) {
867
- var lineView = view[i];
868
- if (lineView.hidden) {
869
- } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
870
- var node = buildLineElement(cm, lineView, lineN, dims);
871
- container.insertBefore(node, cur);
872
- } else { // Already drawn
873
- while (cur != lineView.node) cur = rm(cur);
874
- var updateNumber = lineNumbers && updateNumbersFrom != null &&
875
- updateNumbersFrom <= lineN && lineView.lineNumber;
876
- if (lineView.changes) {
877
- if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;
878
- updateLineForChanges(cm, lineView, lineN, dims);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
879
  }
880
- if (updateNumber) {
881
- removeChildren(lineView.lineNumber);
882
- lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
883
  }
884
- cur = lineView.node.nextSibling;
885
  }
886
- lineN += lineView.size;
887
- }
888
- while (cur) cur = rm(cur);
889
- }
890
-
891
- // When an aspect of a line changes, a string is added to
892
- // lineView.changes. This updates the relevant part of the line's
893
- // DOM structure.
894
- function updateLineForChanges(cm, lineView, lineN, dims) {
895
- for (var j = 0; j < lineView.changes.length; j++) {
896
- var type = lineView.changes[j];
897
- if (type == "text") updateLineText(cm, lineView);
898
- else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
899
- else if (type == "class") updateLineClasses(lineView);
900
- else if (type == "widget") updateLineWidgets(cm, lineView, dims);
901
- }
902
- lineView.changes = null;
903
- }
904
-
905
- // Lines with gutter elements, widgets or a background class need to
906
- // be wrapped, and have the extra elements added to the wrapper div
907
- function ensureLineWrapped(lineView) {
908
- if (lineView.node == lineView.text) {
909
- lineView.node = elt("div", null, null, "position: relative");
910
- if (lineView.text.parentNode)
911
- lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
912
- lineView.node.appendChild(lineView.text);
913
- if (ie && ie_version < 8) lineView.node.style.zIndex = 2;
914
- }
915
- return lineView.node;
916
- }
917
-
918
- function updateLineBackground(lineView) {
919
- var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
920
- if (cls) cls += " CodeMirror-linebackground";
921
- if (lineView.background) {
922
- if (cls) lineView.background.className = cls;
923
- else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
924
- } else if (cls) {
925
- var wrap = ensureLineWrapped(lineView);
926
- lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
927
- }
928
- }
929
-
930
- // Wrapper around buildLineContent which will reuse the structure
931
- // in display.externalMeasured when possible.
932
- function getLineContent(cm, lineView) {
933
- var ext = cm.display.externalMeasured;
934
- if (ext && ext.line == lineView.line) {
935
- cm.display.externalMeasured = null;
936
- lineView.measure = ext.measure;
937
- return ext.built;
938
- }
939
- return buildLineContent(cm, lineView);
940
- }
941
-
942
- // Redraw the line's text. Interacts with the background and text
943
- // classes because the mode may output tokens that influence these
944
- // classes.
945
- function updateLineText(cm, lineView) {
946
- var cls = lineView.text.className;
947
- var built = getLineContent(cm, lineView);
948
- if (lineView.text == lineView.node) lineView.node = built.pre;
949
- lineView.text.parentNode.replaceChild(built.pre, lineView.text);
950
- lineView.text = built.pre;
951
- if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
952
- lineView.bgClass = built.bgClass;
953
- lineView.textClass = built.textClass;
954
- updateLineClasses(lineView);
955
- } else if (cls) {
956
- lineView.text.className = cls;
957
- }
958
- }
959
-
960
- function updateLineClasses(lineView) {
961
- updateLineBackground(lineView);
962
- if (lineView.line.wrapClass)
963
- ensureLineWrapped(lineView).className = lineView.line.wrapClass;
964
- else if (lineView.node != lineView.text)
965
- lineView.node.className = "";
966
- var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
967
- lineView.text.className = textClass || "";
968
- }
969
-
970
- function updateLineGutter(cm, lineView, lineN, dims) {
971
- if (lineView.gutter) {
972
- lineView.node.removeChild(lineView.gutter);
973
- lineView.gutter = null;
974
- }
975
- if (lineView.gutterBackground) {
976
- lineView.node.removeChild(lineView.gutterBackground);
977
- lineView.gutterBackground = null;
978
- }
979
- if (lineView.line.gutterClass) {
980
- var wrap = ensureLineWrapped(lineView);
981
- lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
982
- "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
983
- "px; width: " + dims.gutterTotalWidth + "px");
984
- wrap.insertBefore(lineView.gutterBackground, lineView.text);
985
- }
986
- var markers = lineView.line.gutterMarkers;
987
- if (cm.options.lineNumbers || markers) {
988
- var wrap = ensureLineWrapped(lineView);
989
- var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
990
- (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px");
991
- cm.display.input.setUneditable(gutterWrap);
992
- wrap.insertBefore(gutterWrap, lineView.text);
993
- if (lineView.line.gutterClass)
994
- gutterWrap.className += " " + lineView.line.gutterClass;
995
- if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
996
- lineView.lineNumber = gutterWrap.appendChild(
997
- elt("div", lineNumberFor(cm.options, lineN),
998
- "CodeMirror-linenumber CodeMirror-gutter-elt",
999
- "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
1000
- + cm.display.lineNumInnerWidth + "px"));
1001
- if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {
1002
- var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
1003
- if (found)
1004
- gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
1005
- dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
1006
- }
1007
- }
1008
- }
1009
-
1010
- function updateLineWidgets(cm, lineView, dims) {
1011
- if (lineView.alignable) lineView.alignable = null;
1012
- for (var node = lineView.node.firstChild, next; node; node = next) {
1013
- var next = node.nextSibling;
1014
- if (node.className == "CodeMirror-linewidget")
1015
- lineView.node.removeChild(node);
1016
- }
1017
- insertLineWidgets(cm, lineView, dims);
1018
- }
1019
-
1020
- // Build a line's DOM representation from scratch
1021
- function buildLineElement(cm, lineView, lineN, dims) {
1022
- var built = getLineContent(cm, lineView);
1023
- lineView.text = lineView.node = built.pre;
1024
- if (built.bgClass) lineView.bgClass = built.bgClass;
1025
- if (built.textClass) lineView.textClass = built.textClass;
1026
-
1027
- updateLineClasses(lineView);
1028
- updateLineGutter(cm, lineView, lineN, dims);
1029
- insertLineWidgets(cm, lineView, dims);
1030
- return lineView.node;
1031
- }
1032
-
1033
- // A lineView may contain multiple logical lines (when merged by
1034
- // collapsed spans). The widgets for all of them need to be drawn.
1035
- function insertLineWidgets(cm, lineView, dims) {
1036
- insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
1037
- if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
1038
- insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);
1039
- }
1040
-
1041
- function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
1042
- if (!line.widgets) return;
1043
- var wrap = ensureLineWrapped(lineView);
1044
- for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
1045
- var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
1046
- if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");
1047
- positionLineWidget(widget, node, lineView, dims);
1048
- cm.display.input.setUneditable(node);
1049
- if (allowAbove && widget.above)
1050
- wrap.insertBefore(node, lineView.gutter || lineView.text);
1051
- else
1052
- wrap.appendChild(node);
1053
- signalLater(widget, "redraw");
1054
- }
1055
- }
1056
 
1057
- function positionLineWidget(widget, node, lineView, dims) {
1058
- if (widget.noHScroll) {
1059
- (lineView.alignable || (lineView.alignable = [])).push(node);
1060
- var width = dims.wrapperWidth;
1061
- node.style.left = dims.fixedPos + "px";
1062
- if (!widget.coverGutter) {
1063
- width -= dims.gutterTotalWidth;
1064
- node.style.paddingLeft = dims.gutterTotalWidth + "px";
1065
  }
1066
- node.style.width = width + "px";
1067
- }
1068
- if (widget.coverGutter) {
1069
- node.style.zIndex = 5;
1070
- node.style.position = "relative";
1071
- if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
1072
- }
1073
- }
1074
-
1075
- // POSITION OBJECT
1076
-
1077
- // A Pos instance represents a position within the text.
1078
- var Pos = CodeMirror.Pos = function(line, ch) {
1079
- if (!(this instanceof Pos)) return new Pos(line, ch);
1080
- this.line = line; this.ch = ch;
1081
  };
1082
 
1083
- // Compare two positions, return 0 if they are the same, a negative
1084
- // number when a is less, and a positive number otherwise.
1085
- var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };
1086
-
1087
- function copyPos(x) {return Pos(x.line, x.ch);}
1088
- function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
1089
- function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
1090
-
1091
- // INPUT HANDLING
1092
-
1093
- function ensureFocus(cm) {
1094
- if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
1095
- }
1096
-
1097
- // This will be set to an array of strings when copying, so that,
1098
- // when pasting, we know what kind of selections the copied text
1099
- // was made out of.
1100
- var lastCopied = null;
1101
-
1102
- function applyTextInput(cm, inserted, deleted, sel, origin) {
1103
- var doc = cm.doc;
1104
- cm.display.shift = false;
1105
- if (!sel) sel = doc.sel;
1106
-
1107
- var paste = cm.state.pasteIncoming || origin == "paste";
1108
- var textLines = doc.splitLines(inserted), multiPaste = null;
1109
- // When pasing N lines into N selections, insert one line per selection
1110
- if (paste && sel.ranges.length > 1) {
1111
- if (lastCopied && lastCopied.join("\n") == inserted) {
1112
- if (sel.ranges.length % lastCopied.length == 0) {
1113
- multiPaste = [];
1114
- for (var i = 0; i < lastCopied.length; i++)
1115
- multiPaste.push(doc.splitLines(lastCopied[i]));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1116
  }
1117
- } else if (textLines.length == sel.ranges.length) {
1118
- multiPaste = map(textLines, function(l) { return [l]; });
1119
  }
 
1120
  }
1121
-
1122
- // Normal behavior is to insert the new text into every selection
1123
- for (var i = sel.ranges.length - 1; i >= 0; i--) {
1124
- var range = sel.ranges[i];
1125
- var from = range.from(), to = range.to();
1126
- if (range.empty()) {
1127
- if (deleted && deleted > 0) // Handle deletion
1128
- from = Pos(from.line, from.ch - deleted);
1129
- else if (cm.state.overwrite && !paste) // Handle overwrite
1130
- to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
1131
- }
1132
- var updateInput = cm.curOp.updateInput;
1133
- var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
1134
- origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
1135
- makeChange(cm.doc, changeEvent);
1136
- signalLater(cm, "inputRead", cm, changeEvent);
1137
- }
1138
- if (inserted && !paste)
1139
- triggerElectric(cm, inserted);
1140
-
1141
- ensureCursorVisible(cm);
1142
- cm.curOp.updateInput = updateInput;
1143
- cm.curOp.typing = true;
1144
- cm.state.pasteIncoming = cm.state.cutIncoming = false;
1145
- }
1146
-
1147
- function handlePaste(e, cm) {
1148
- var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
1149
- if (pasted) {
1150
- e.preventDefault();
1151
- if (!cm.isReadOnly() && !cm.options.disableInput)
1152
- runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
1153
- return true;
1154
- }
1155
- }
1156
-
1157
- function triggerElectric(cm, inserted) {
1158
- // When an 'electric' character is inserted, immediately trigger a reindent
1159
- if (!cm.options.electricChars || !cm.options.smartIndent) return;
1160
- var sel = cm.doc.sel;
1161
-
1162
- for (var i = sel.ranges.length - 1; i >= 0; i--) {
1163
- var range = sel.ranges[i];
1164
- if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
1165
- var mode = cm.getModeAt(range.head);
1166
- var indented = false;
1167
- if (mode.electricChars) {
1168
- for (var j = 0; j < mode.electricChars.length; j++)
1169
- if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
1170
- indented = indentLine(cm, range.head.line, "smart");
1171
- break;
1172
- }
1173
- } else if (mode.electricInput) {
1174
- if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
1175
- indented = indentLine(cm, range.head.line, "smart");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1176
  }
1177
- if (indented) signalLater(cm, "electricInput", cm, range.head.line);
1178
  }
1179
- }
1180
 
1181
- function copyableRanges(cm) {
1182
- var text = [], ranges = [];
1183
- for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
1184
- var line = cm.doc.sel.ranges[i].head.line;
1185
- var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
1186
- ranges.push(lineRange);
1187
- text.push(cm.getRange(lineRange.anchor, lineRange.head));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1188
  }
1189
- return {text: text, ranges: ranges};
1190
- }
1191
-
1192
- function disableBrowserMagic(field) {
1193
- field.setAttribute("autocorrect", "off");
1194
- field.setAttribute("autocapitalize", "off");
1195
- field.setAttribute("spellcheck", "false");
1196
- }
1197
-
1198
- // TEXTAREA INPUT STYLE
1199
 
1200
- function TextareaInput(cm) {
1201
- this.cm = cm;
1202
- // See input.poll and input.reset
1203
- this.prevInput = "";
1204
-
1205
- // Flag that indicates whether we expect input to appear real soon
1206
- // now (after some event like 'keypress' or 'input') and are
1207
- // polling intensively.
1208
- this.pollingFast = false;
1209
- // Self-resetting timeout for the poller
1210
- this.polling = new Delayed();
1211
- // Tracks when input.reset has punted to just putting a short
1212
- // string into the textarea instead of the full selection.
1213
- this.inaccurateSelection = false;
1214
- // Used to work around IE issue with selection being forgotten when focus moves away from textarea
1215
- this.hasSelection = false;
1216
- this.composing = null;
1217
- };
1218
-
1219
- function hiddenTextarea() {
1220
- var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
1221
- var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
1222
- // The textarea is kept positioned near the cursor to prevent the
1223
- // fact that it'll be scrolled into view on input from scrolling
1224
- // our fake cursor out of view. On webkit, when wrap=off, paste is
1225
- // very slow. So make the area wide instead.
1226
- if (webkit) te.style.width = "1000px";
1227
- else te.setAttribute("wrap", "off");
1228
- // If border: 0; -- iOS fails to open keyboard (issue #1287)
1229
- if (ios) te.style.border = "1px solid black";
1230
- disableBrowserMagic(te);
1231
- return div;
1232
- }
1233
-
1234
- TextareaInput.prototype = copyObj({
1235
- init: function(display) {
1236
- var input = this, cm = this.cm;
1237
-
1238
- // Wraps and hides input textarea
1239
- var div = this.wrapper = hiddenTextarea();
1240
- // The semihidden textarea that is focused when the editor is
1241
- // focused, and receives input.
1242
- var te = this.textarea = div.firstChild;
1243
- display.wrapper.insertBefore(div, display.wrapper.firstChild);
1244
-
1245
- // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
1246
- if (ios) te.style.width = "0px";
1247
-
1248
- on(te, "input", function() {
1249
- if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;
1250
- input.poll();
1251
- });
1252
-
1253
- on(te, "paste", function(e) {
1254
- if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return
1255
-
1256
- cm.state.pasteIncoming = true;
1257
- input.fastPoll();
1258
- });
1259
-
1260
- function prepareCopyCut(e) {
1261
- if (cm.somethingSelected()) {
1262
- lastCopied = cm.getSelections();
1263
- if (input.inaccurateSelection) {
1264
- input.prevInput = "";
1265
- input.inaccurateSelection = false;
1266
- te.value = lastCopied.join("\n");
1267
- selectInput(te);
1268
- }
1269
- } else if (!cm.options.lineWiseCopyCut) {
1270
- return;
1271
- } else {
1272
- var ranges = copyableRanges(cm);
1273
- lastCopied = ranges.text;
1274
- if (e.type == "cut") {
1275
- cm.setSelections(ranges.ranges, null, sel_dontScroll);
1276
- } else {
1277
- input.prevInput = "";
1278
- te.value = ranges.text.join("\n");
1279
- selectInput(te);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1280
  }
1281
  }
1282
- if (e.type == "cut") cm.state.cutIncoming = true;
1283
  }
1284
- on(te, "cut", prepareCopyCut);
1285
- on(te, "copy", prepareCopyCut);
1286
-
1287
- on(display.scroller, "paste", function(e) {
1288
- if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return;
1289
- cm.state.pasteIncoming = true;
1290
- input.focus();
1291
- });
1292
-
1293
- // Prevent normal selection in the editor (we handle our own)
1294
- on(display.lineSpace, "selectstart", function(e) {
1295
- if (!eventInWidget(display, e)) e_preventDefault(e);
1296
- });
1297
-
1298
- on(te, "compositionstart", function() {
1299
- var start = cm.getCursor("from");
1300
- if (input.composing) input.composing.range.clear()
1301
- input.composing = {
1302
- start: start,
1303
- range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
1304
- };
1305
- });
1306
- on(te, "compositionend", function() {
1307
- if (input.composing) {
1308
- input.poll();
1309
- input.composing.range.clear();
1310
- input.composing = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1311
  }
1312
- });
1313
- },
1314
-
1315
- prepareSelection: function() {
1316
- // Redraw the selection and/or cursor
1317
- var cm = this.cm, display = cm.display, doc = cm.doc;
1318
- var result = prepareSelection(cm);
1319
-
1320
- // Move the hidden textarea near the cursor to prevent scrolling artifacts
1321
- if (cm.options.moveInputWithCursor) {
1322
- var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
1323
- var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
1324
- result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
1325
- headPos.top + lineOff.top - wrapOff.top));
1326
- result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
1327
- headPos.left + lineOff.left - wrapOff.left));
1328
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1329
 
1330
- return result;
1331
- },
 
 
 
1332
 
1333
- showSelection: function(drawn) {
1334
- var cm = this.cm, display = cm.display;
1335
- removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
1336
- removeChildrenAndAdd(display.selectionDiv, drawn.selection);
1337
- if (drawn.teTop != null) {
1338
- this.wrapper.style.top = drawn.teTop + "px";
1339
- this.wrapper.style.left = drawn.teLeft + "px";
1340
- }
1341
- },
1342
 
1343
- // Reset the input to correspond to the selection (or to be empty,
1344
- // when not typing and nothing is selected)
1345
- reset: function(typing) {
1346
- if (this.contextMenuPending) return;
1347
- var minimal, selected, cm = this.cm, doc = cm.doc;
1348
- if (cm.somethingSelected()) {
1349
- this.prevInput = "";
1350
- var range = doc.sel.primary();
1351
- minimal = hasCopyEvent &&
1352
- (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
1353
- var content = minimal ? "-" : selected || cm.getSelection();
1354
- this.textarea.value = content;
1355
- if (cm.state.focused) selectInput(this.textarea);
1356
- if (ie && ie_version >= 9) this.hasSelection = content;
1357
- } else if (!typing) {
1358
- this.prevInput = this.textarea.value = "";
1359
- if (ie && ie_version >= 9) this.hasSelection = null;
1360
- }
1361
- this.inaccurateSelection = minimal;
1362
- },
1363
 
1364
- getField: function() { return this.textarea; },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1365
 
1366
- supportsTouch: function() { return false; },
 
 
1367
 
1368
- focus: function() {
1369
- if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
1370
- try { this.textarea.focus(); }
1371
- catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
1372
- }
 
 
1373
  },
1374
 
1375
- blur: function() { this.textarea.blur(); },
 
1376
 
1377
- resetPosition: function() {
1378
- this.wrapper.style.top = this.wrapper.style.left = 0;
1379
  },
1380
-
1381
- receivedFocus: function() { this.slowPoll(); },
1382
-
1383
- // Poll for input changes, using the normal rate of polling. This
1384
- // runs as long as the editor is focused.
1385
- slowPoll: function() {
1386
- var input = this;
1387
- if (input.pollingFast) return;
1388
- input.polling.set(this.cm.options.pollInterval, function() {
1389
- input.poll();
1390
- if (input.cm.state.focused) input.slowPoll();
1391
- });
1392
  },
1393
 
1394
- // When an event has just come in that is likely to add or change
1395
- // something in the input textarea, we poll faster, to ensure that
1396
- // the change appears on the screen quickly.
1397
- fastPoll: function() {
1398
- var missed = false, input = this;
1399
- input.pollingFast = true;
1400
- function p() {
1401
- var changed = input.poll();
1402
- if (!changed && !missed) {missed = true; input.polling.set(60, p);}
1403
- else {input.pollingFast = false; input.slowPoll();}
1404
- }
1405
- input.polling.set(20, p);
1406
- },
1407
 
1408
- // Read input from the textarea, and update the document to match.
1409
- // When something is selected, it is present in the textarea, and
1410
- // selected (unless it is huge, in which case a placeholder is
1411
- // used). When nothing is selected, the cursor sits after previously
1412
- // seen text (can be empty), which is stored in prevInput (we must
1413
- // not reset the textarea when typing, because that breaks IME).
1414
- poll: function() {
1415
- var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
1416
- // Since this is called a *lot*, try to bail out as cheaply as
1417
- // possible when it is clear that nothing happened. hasSelection
1418
- // will be the case when there is a lot of text in the textarea,
1419
- // in which case reading its value would be expensive.
1420
- if (this.contextMenuPending || !cm.state.focused ||
1421
- (hasSelection(input) && !prevInput && !this.composing) ||
1422
- cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
1423
- return false;
1424
-
1425
- var text = input.value;
1426
- // If nothing changed, bail.
1427
- if (text == prevInput && !cm.somethingSelected()) return false;
1428
- // Work around nonsensical selection resetting in IE9/10, and
1429
- // inexplicable appearance of private area unicode characters on
1430
- // some key combos in Mac (#2689).
1431
- if (ie && ie_version >= 9 && this.hasSelection === text ||
1432
- mac && /[\uf700-\uf7ff]/.test(text)) {
1433
- cm.display.input.reset();
1434
- return false;
1435
  }
 
1436
 
1437
- if (cm.doc.sel == cm.display.selForContextMenu) {
1438
- var first = text.charCodeAt(0);
1439
- if (first == 0x200b && !prevInput) prevInput = "\u200b";
1440
- if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
1441
  }
1442
- // Find the part of the input that is actually new
1443
- var same = 0, l = Math.min(prevInput.length, text.length);
1444
- while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1445
-
1446
- var self = this;
1447
- runInOp(cm, function() {
1448
- applyTextInput(cm, text.slice(same), prevInput.length - same,
1449
- null, self.composing ? "*compose" : null);
1450
-
1451
- // Don't leave long text in the textarea, since it makes further polling slow
1452
- if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
1453
- else self.prevInput = text;
1454
-
1455
- if (self.composing) {
1456
- self.composing.range.clear();
1457
- self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
1458
- {className: "CodeMirror-composing"});
1459
- }
1460
- });
1461
- return true;
1462
- },
1463
-
1464
- ensurePolled: function() {
1465
- if (this.pollingFast && this.poll()) this.pollingFast = false;
1466
- },
1467
-
1468
- onKeyPress: function() {
1469
- if (ie && ie_version >= 9) this.hasSelection = null;
1470
- this.fastPoll();
1471
- },
1472
 
1473
- onContextMenu: function(e) {
1474
- var input = this, cm = input.cm, display = cm.display, te = input.textarea;
1475
- var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
1476
- if (!pos || presto) return; // Opera is difficult.
1477
-
1478
- // Reset the current text selection only if the click is done outside of the selection
1479
- // and 'resetSelectionOnContextMenu' option is true.
1480
- var reset = cm.options.resetSelectionOnContextMenu;
1481
- if (reset && cm.doc.sel.contains(pos) == -1)
1482
- operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
1483
-
1484
- var oldCSS = te.style.cssText;
1485
- input.wrapper.style.position = "absolute";
1486
- te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
1487
- "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
1488
- (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
1489
- "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
1490
- if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
1491
- display.input.focus();
1492
- if (webkit) window.scrollTo(null, oldScrollY);
1493
- display.input.reset();
1494
- // Adds "Select all" to context menu in FF
1495
- if (!cm.somethingSelected()) te.value = input.prevInput = " ";
1496
- input.contextMenuPending = true;
1497
- display.selForContextMenu = cm.doc.sel;
1498
- clearTimeout(display.detectingSelectAll);
1499
-
1500
- // Select-all will be greyed out if there's nothing to select, so
1501
- // this adds a zero-width space so that we can later check whether
1502
- // it got selected.
1503
- function prepareSelectAllHack() {
1504
- if (te.selectionStart != null) {
1505
- var selected = cm.somethingSelected();
1506
- var extval = "\u200b" + (selected ? te.value : "");
1507
- te.value = "\u21da"; // Used to catch context-menu undo
1508
- te.value = extval;
1509
- input.prevInput = selected ? "" : "\u200b";
1510
- te.selectionStart = 1; te.selectionEnd = extval.length;
1511
- // Re-set this, in case some other handler touched the
1512
- // selection in the meantime.
1513
- display.selForContextMenu = cm.doc.sel;
1514
- }
1515
- }
1516
- function rehide() {
1517
- input.contextMenuPending = false;
1518
- input.wrapper.style.position = "relative";
1519
- te.style.cssText = oldCSS;
1520
- if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
1521
-
1522
- // Try to detect the user choosing select-all
1523
- if (te.selectionStart != null) {
1524
- if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
1525
- var i = 0, poll = function() {
1526
- if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
1527
- te.selectionEnd > 0 && input.prevInput == "\u200b")
1528
- operation(cm, commands.selectAll)(cm);
1529
- else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
1530
- else display.input.reset();
1531
- };
1532
- display.detectingSelectAll = setTimeout(poll, 200);
1533
  }
1534
  }
 
1535
 
1536
- if (ie && ie_version >= 9) prepareSelectAllHack();
1537
- if (captureRightClick) {
1538
- e_stop(e);
1539
- var mouseup = function() {
1540
- off(window, "mouseup", mouseup);
1541
- setTimeout(rehide, 20);
1542
- };
1543
- on(window, "mouseup", mouseup);
1544
- } else {
1545
- setTimeout(rehide, 50);
1546
- }
1547
  },
1548
 
1549
- readOnlyChanged: function(val) {
1550
- if (!val) this.reset();
1551
  },
1552
 
1553
- setUneditable: nothing,
1554
-
1555
- needsContentAttribute: false
1556
- }, TextareaInput.prototype);
1557
-
1558
- // CONTENTEDITABLE INPUT STYLE
1559
-
1560
- function ContentEditableInput(cm) {
1561
- this.cm = cm;
1562
- this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
1563
- this.polling = new Delayed();
1564
- this.gracePeriod = false;
1565
- }
1566
-
1567
- ContentEditableInput.prototype = copyObj({
1568
- init: function(display) {
1569
- var input = this, cm = input.cm;
1570
- var div = input.div = display.lineDiv;
1571
- disableBrowserMagic(div);
1572
-
1573
- on(div, "paste", function(e) {
1574
- if (!signalDOMEvent(cm, e)) handlePaste(e, cm);
1575
- })
1576
-
1577
- on(div, "compositionstart", function(e) {
1578
- var data = e.data;
1579
- input.composing = {sel: cm.doc.sel, data: data, startData: data};
1580
- if (!data) return;
1581
- var prim = cm.doc.sel.primary();
1582
- var line = cm.getLine(prim.head.line);
1583
- var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));
1584
- if (found > -1 && found <= prim.head.ch)
1585
- input.composing.sel = simpleSelection(Pos(prim.head.line, found),
1586
- Pos(prim.head.line, found + data.length));
1587
- });
1588
- on(div, "compositionupdate", function(e) {
1589
- input.composing.data = e.data;
1590
- });
1591
- on(div, "compositionend", function(e) {
1592
- var ours = input.composing;
1593
- if (!ours) return;
1594
- if (e.data != ours.startData && !/\u200b/.test(e.data))
1595
- ours.data = e.data;
1596
- // Need a small delay to prevent other code (input event,
1597
- // selection polling) from doing damage when fired right after
1598
- // compositionend.
1599
- setTimeout(function() {
1600
- if (!ours.handled)
1601
- input.applyComposition(ours);
1602
- if (input.composing == ours)
1603
- input.composing = null;
1604
- }, 50);
1605
- });
1606
-
1607
- on(div, "touchstart", function() {
1608
- input.forceCompositionEnd();
1609
- });
1610
-
1611
- on(div, "input", function() {
1612
- if (input.composing) return;
1613
- if (cm.isReadOnly() || !input.pollContent())
1614
- runInOp(input.cm, function() {regChange(cm);});
1615
- });
1616
-
1617
- function onCopyCut(e) {
1618
- if (cm.somethingSelected()) {
1619
- lastCopied = cm.getSelections();
1620
- if (e.type == "cut") cm.replaceSelection("", null, "cut");
1621
- } else if (!cm.options.lineWiseCopyCut) {
1622
- return;
1623
- } else {
1624
- var ranges = copyableRanges(cm);
1625
- lastCopied = ranges.text;
1626
- if (e.type == "cut") {
1627
- cm.operation(function() {
1628
- cm.setSelections(ranges.ranges, 0, sel_dontScroll);
1629
- cm.replaceSelection("", null, "cut");
1630
- });
1631
- }
1632
- }
1633
- // iOS exposes the clipboard API, but seems to discard content inserted into it
1634
- if (e.clipboardData && !ios) {
1635
- e.preventDefault();
1636
- e.clipboardData.clearData();
1637
- e.clipboardData.setData("text/plain", lastCopied.join("\n"));
1638
- } else {
1639
- // Old-fashioned briefly-focus-a-textarea hack
1640
- var kludge = hiddenTextarea(), te = kludge.firstChild;
1641
- cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
1642
- te.value = lastCopied.join("\n");
1643
- var hadFocus = document.activeElement;
1644
- selectInput(te);
1645
- setTimeout(function() {
1646
- cm.display.lineSpace.removeChild(kludge);
1647
- hadFocus.focus();
1648
- }, 50);
1649
- }
1650
- }
1651
- on(div, "copy", onCopyCut);
1652
- on(div, "cut", onCopyCut);
1653
  },
1654
 
1655
- prepareSelection: function() {
1656
- var result = prepareSelection(this.cm, false);
1657
- result.focus = this.cm.state.focused;
1658
- return result;
1659
  },
1660
 
1661
- showSelection: function(info) {
1662
- if (!info || !this.cm.display.view.length) return;
1663
- if (info.focus) this.showPrimarySelection();
1664
- this.showMultipleSelections(info);
1665
  },
1666
 
1667
- showPrimarySelection: function() {
1668
- var sel = window.getSelection(), prim = this.cm.doc.sel.primary();
1669
- var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);
1670
- var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);
1671
- if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
1672
- cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
1673
- cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
1674
- return;
1675
-
1676
- var start = posToDOM(this.cm, prim.from());
1677
- var end = posToDOM(this.cm, prim.to());
1678
- if (!start && !end) return;
1679
-
1680
- var view = this.cm.display.view;
1681
- var old = sel.rangeCount && sel.getRangeAt(0);
1682
- if (!start) {
1683
- start = {node: view[0].measure.map[2], offset: 0};
1684
- } else if (!end) { // FIXME dangerously hacky
1685
- var measure = view[view.length - 1].measure;
1686
- var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
1687
- end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
1688
- }
1689
 
1690
- try { var rng = range(start.node, start.offset, end.offset, end.node); }
1691
- catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
1692
- if (rng) {
1693
- if (!gecko && this.cm.state.focused) {
1694
- sel.collapse(start.node, start.offset);
1695
- if (!rng.collapsed) sel.addRange(rng);
1696
- } else {
1697
- sel.removeAllRanges();
1698
- sel.addRange(rng);
1699
  }
1700
- if (old && sel.anchorNode == null) sel.addRange(old);
1701
- else if (gecko) this.startGracePeriod();
 
 
1702
  }
1703
- this.rememberSelection();
 
 
 
 
 
1704
  },
1705
 
1706
- startGracePeriod: function() {
1707
- var input = this;
1708
- clearTimeout(this.gracePeriod);
1709
- this.gracePeriod = setTimeout(function() {
1710
- input.gracePeriod = false;
1711
- if (input.selectionChanged())
1712
- input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
1713
- }, 20);
1714
  },
1715
 
1716
- showMultipleSelections: function(info) {
1717
- removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
1718
- removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
 
 
 
1719
  },
1720
 
1721
- rememberSelection: function() {
1722
- var sel = window.getSelection();
1723
- this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
1724
- this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
1725
  },
1726
 
1727
- selectionInEditor: function() {
1728
- var sel = window.getSelection();
1729
- if (!sel.rangeCount) return false;
1730
- var node = sel.getRangeAt(0).commonAncestorContainer;
1731
- return contains(this.div, node);
1732
  },
1733
 
1734
- focus: function() {
1735
- if (this.cm.options.readOnly != "nocursor") this.div.focus();
 
1736
  },
1737
- blur: function() { this.div.blur(); },
1738
- getField: function() { return this.div; },
1739
-
1740
- supportsTouch: function() { return true; },
1741
-
1742
- receivedFocus: function() {
1743
- var input = this;
1744
- if (this.selectionInEditor())
1745
- this.pollSelection();
1746
- else
1747
- runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });
1748
-
1749
- function poll() {
1750
- if (input.cm.state.focused) {
1751
- input.pollSelection();
1752
- input.polling.set(input.cm.options.pollInterval, poll);
1753
- }
1754
  }
1755
- this.polling.set(this.cm.options.pollInterval, poll);
1756
- },
1757
-
1758
- selectionChanged: function() {
1759
- var sel = window.getSelection();
1760
- return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
1761
- sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
1762
  },
1763
 
1764
- pollSelection: function() {
1765
- if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
1766
- var sel = window.getSelection(), cm = this.cm;
1767
- this.rememberSelection();
1768
- var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
1769
- var head = domToPos(cm, sel.focusNode, sel.focusOffset);
1770
- if (anchor && head) runInOp(cm, function() {
1771
- setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
1772
- if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;
1773
- });
1774
- }
1775
- },
1776
 
1777
- pollContent: function() {
1778
- var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
1779
- var from = sel.from(), to = sel.to();
1780
- if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;
1781
 
1782
- var fromIndex;
1783
- if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
1784
- var fromLine = lineNo(display.view[0].line);
1785
- var fromNode = display.view[0].node;
1786
- } else {
1787
- var fromLine = lineNo(display.view[fromIndex].line);
1788
- var fromNode = display.view[fromIndex - 1].node.nextSibling;
 
 
 
 
 
 
 
 
 
 
 
 
 
1789
  }
1790
- var toIndex = findViewIndex(cm, to.line);
1791
- if (toIndex == display.view.length - 1) {
1792
- var toLine = display.viewTo - 1;
1793
- var toNode = display.lineDiv.lastChild;
 
1794
  } else {
1795
- var toLine = lineNo(display.view[toIndex + 1].line) - 1;
1796
- var toNode = display.view[toIndex + 1].node.previousSibling;
1797
- }
1798
-
1799
- var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
1800
- var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
1801
- while (newText.length > 1 && oldText.length > 1) {
1802
- if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
1803
- else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
1804
- else break;
1805
- }
1806
-
1807
- var cutFront = 0, cutEnd = 0;
1808
- var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
1809
- while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
1810
- ++cutFront;
1811
- var newBot = lst(newText), oldBot = lst(oldText);
1812
- var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
1813
- oldBot.length - (oldText.length == 1 ? cutFront : 0));
1814
- while (cutEnd < maxCutEnd &&
1815
- newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
1816
- ++cutEnd;
1817
-
1818
- newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);
1819
- newText[0] = newText[0].slice(cutFront);
1820
-
1821
- var chFrom = Pos(fromLine, cutFront);
1822
- var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
1823
- if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
1824
- replaceRange(cm.doc, newText, chFrom, chTo, "+input");
1825
- return true;
1826
  }
 
 
1827
  },
1828
 
1829
- ensurePolled: function() {
1830
- this.forceCompositionEnd();
1831
- },
1832
- reset: function() {
1833
- this.forceCompositionEnd();
1834
- },
1835
- forceCompositionEnd: function() {
1836
- if (!this.composing || this.composing.handled) return;
1837
- this.applyComposition(this.composing);
1838
- this.composing.handled = true;
1839
- this.div.blur();
1840
- this.div.focus();
1841
- },
1842
- applyComposition: function(composing) {
1843
- if (this.cm.isReadOnly())
1844
- operation(this.cm, regChange)(this.cm)
1845
- else if (composing.data && composing.data != composing.startData)
1846
- operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
1847
- },
1848
-
1849
- setUneditable: function(node) {
1850
- node.contentEditable = "false"
1851
- },
1852
-
1853
- onKeyPress: function(e) {
1854
- e.preventDefault();
1855
- if (!this.cm.isReadOnly())
1856
- operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
1857
- },
1858
 
1859
- readOnlyChanged: function(val) {
1860
- this.div.contentEditable = String(val != "nocursor")
 
1861
  },
1862
 
1863
- onContextMenu: nothing,
1864
- resetPosition: nothing,
1865
-
1866
- needsContentAttribute: true
1867
- }, ContentEditableInput.prototype);
1868
-
1869
- function posToDOM(cm, pos) {
1870
- var view = findViewForLine(cm, pos.line);
1871
- if (!view || view.hidden) return null;
1872
- var line = getLine(cm.doc, pos.line);
1873
- var info = mapFromLineView(view, line, pos.line);
1874
-
1875
- var order = getOrder(line), side = "left";
1876
- if (order) {
1877
- var partPos = getBidiPartAt(order, pos.ch);
1878
- side = partPos % 2 ? "right" : "left";
1879
- }
1880
- var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
1881
- result.offset = result.collapse == "right" ? result.end : result.start;
1882
- return result;
1883
- }
1884
 
1885
- function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }
 
1886
 
1887
- function domToPos(cm, node, offset) {
1888
- var lineNode;
1889
- if (node == cm.display.lineDiv) {
1890
- lineNode = cm.display.lineDiv.childNodes[offset];
1891
- if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);
1892
- node = null; offset = 0;
1893
- } else {
1894
- for (lineNode = node;; lineNode = lineNode.parentNode) {
1895
- if (!lineNode || lineNode == cm.display.lineDiv) return null;
1896
- if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;
1897
  }
1898
- }
1899
- for (var i = 0; i < cm.display.view.length; i++) {
1900
- var lineView = cm.display.view[i];
1901
- if (lineView.node == lineNode)
1902
- return locateNodeInLineView(lineView, node, offset);
1903
- }
1904
- }
1905
 
1906
- function locateNodeInLineView(lineView, node, offset) {
1907
- var wrapper = lineView.text.firstChild, bad = false;
1908
- if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);
1909
- if (node == wrapper) {
1910
- bad = true;
1911
- node = wrapper.childNodes[offset];
1912
- offset = 0;
1913
- if (!node) {
1914
- var line = lineView.rest ? lst(lineView.rest) : lineView.line;
1915
- return badPos(Pos(lineNo(line), line.text.length), bad);
1916
- }
1917
- }
1918
 
1919
- var textNode = node.nodeType == 3 ? node : null, topNode = node;
1920
- if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
1921
- textNode = node.firstChild;
1922
- if (offset) offset = textNode.nodeValue.length;
1923
- }
1924
- while (topNode.parentNode != wrapper) topNode = topNode.parentNode;
1925
- var measure = lineView.measure, maps = measure.maps;
1926
-
1927
- function find(textNode, topNode, offset) {
1928
- for (var i = -1; i < (maps ? maps.length : 0); i++) {
1929
- var map = i < 0 ? measure.map : maps[i];
1930
- for (var j = 0; j < map.length; j += 3) {
1931
- var curNode = map[j + 2];
1932
- if (curNode == textNode || curNode == topNode) {
1933
- var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
1934
- var ch = map[j] + offset;
1935
- if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];
1936
- return Pos(line, ch);
1937
- }
1938
- }
1939
- }
1940
- }
1941
- var found = find(textNode, topNode, offset);
1942
- if (found) return badPos(found, bad);
1943
 
1944
- // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
1945
- for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
1946
- found = find(after, after.firstChild, 0);
1947
- if (found)
1948
- return badPos(Pos(found.line, found.ch - dist), bad);
1949
- else
1950
- dist += after.textContent.length;
1951
- }
1952
- for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {
1953
- found = find(before, before.firstChild, -1);
1954
- if (found)
1955
- return badPos(Pos(found.line, found.ch + dist), bad);
1956
  else
1957
- dist += after.textContent.length;
1958
- }
1959
- }
1960
-
1961
- function domTextBetween(cm, from, to, fromLine, toLine) {
1962
- var text = "", closing = false, lineSep = cm.doc.lineSeparator();
1963
- function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
1964
- function walk(node) {
1965
- if (node.nodeType == 1) {
1966
- var cmText = node.getAttribute("cm-text");
1967
- if (cmText != null) {
1968
- if (cmText == "") cmText = node.textContent.replace(/\u200b/g, "");
1969
- text += cmText;
1970
- return;
1971
- }
1972
- var markerID = node.getAttribute("cm-marker"), range;
1973
- if (markerID) {
1974
- var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
1975
- if (found.length && (range = found[0].find()))
1976
- text += getBetween(cm.doc, range.from, range.to).join(lineSep);
1977
- return;
1978
- }
1979
- if (node.getAttribute("contenteditable") == "false") return;
1980
- for (var i = 0; i < node.childNodes.length; i++)
1981
- walk(node.childNodes[i]);
1982
- if (/^(pre|div|p)$/i.test(node.nodeName))
1983
- closing = true;
1984
- } else if (node.nodeType == 3) {
1985
- var val = node.nodeValue;
1986
- if (!val) return;
1987
- if (closing) {
1988
- text += lineSep;
1989
- closing = false;
1990
- }
1991
- text += val;
1992
- }
1993
- }
1994
- for (;;) {
1995
- walk(from);
1996
- if (from == to) break;
1997
- from = from.nextSibling;
1998
- }
1999
- return text;
2000
- }
2001
-
2002
- CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
2003
-
2004
- // SELECTION / CURSOR
2005
-
2006
- // Selection objects are immutable. A new one is created every time
2007
- // the selection changes. A selection is one or more non-overlapping
2008
- // (and non-touching) ranges, sorted, and an integer that indicates
2009
- // which one is the primary selection (the one that's scrolled into
2010
- // view, that getCursor returns, etc).
2011
- function Selection(ranges, primIndex) {
2012
- this.ranges = ranges;
2013
- this.primIndex = primIndex;
2014
- }
2015
 
2016
- Selection.prototype = {
2017
- primary: function() { return this.ranges[this.primIndex]; },
2018
- equals: function(other) {
2019
- if (other == this) return true;
2020
- if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;
2021
- for (var i = 0; i < this.ranges.length; i++) {
2022
- var here = this.ranges[i], there = other.ranges[i];
2023
- if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;
2024
- }
2025
- return true;
2026
- },
2027
- deepCopy: function() {
2028
- for (var out = [], i = 0; i < this.ranges.length; i++)
2029
- out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
2030
- return new Selection(out, this.primIndex);
2031
- },
2032
- somethingSelected: function() {
2033
- for (var i = 0; i < this.ranges.length; i++)
2034
- if (!this.ranges[i].empty()) return true;
2035
- return false;
2036
  },
2037
- contains: function(pos, end) {
2038
- if (!end) end = pos;
2039
- for (var i = 0; i < this.ranges.length; i++) {
2040
- var range = this.ranges[i];
2041
- if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
2042
- return i;
2043
- }
2044
- return -1;
2045
- }
2046
- };
2047
 
2048
- function Range(anchor, head) {
2049
- this.anchor = anchor; this.head = head;
2050
- }
2051
 
2052
- Range.prototype = {
2053
- from: function() { return minPos(this.anchor, this.head); },
2054
- to: function() { return maxPos(this.anchor, this.head); },
2055
- empty: function() {
2056
- return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
2057
- }
2058
- };
 
 
 
 
 
 
 
 
 
2059
 
2060
- // Take an unsorted, potentially overlapping set of ranges, and
2061
- // build a selection out of it. 'Consumes' ranges array (modifying
2062
- // it).
2063
- function normalizeSelection(ranges, primIndex) {
2064
- var prim = ranges[primIndex];
2065
- ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });
2066
- primIndex = indexOf(ranges, prim);
2067
- for (var i = 1; i < ranges.length; i++) {
2068
- var cur = ranges[i], prev = ranges[i - 1];
2069
- if (cmp(prev.to(), cur.from()) >= 0) {
2070
- var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
2071
- var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
2072
- if (i <= primIndex) --primIndex;
2073
- ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
2074
- }
2075
- }
2076
- return new Selection(ranges, primIndex);
2077
- }
2078
-
2079
- function simpleSelection(anchor, head) {
2080
- return new Selection([new Range(anchor, head || anchor)], 0);
2081
- }
2082
-
2083
- // Most of the external API clips given positions to make sure they
2084
- // actually exist within the document.
2085
- function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
2086
- function clipPos(doc, pos) {
2087
- if (pos.line < doc.first) return Pos(doc.first, 0);
2088
- var last = doc.first + doc.size - 1;
2089
- if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2090
- return clipToLen(pos, getLine(doc, pos.line).text.length);
2091
- }
2092
- function clipToLen(pos, linelen) {
2093
- var ch = pos.ch;
2094
- if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2095
- else if (ch < 0) return Pos(pos.line, 0);
2096
- else return pos;
2097
- }
2098
- function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2099
- function clipPosArray(doc, array) {
2100
- for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);
2101
- return out;
2102
- }
2103
-
2104
- // SELECTION UPDATES
2105
-
2106
- // The 'scroll' parameter given to many of these indicated whether
2107
- // the new cursor position should be scrolled into view after
2108
- // modifying the selection.
2109
-
2110
- // If shift is held or the extend flag is set, extends a range to
2111
- // include a given position (and optionally a second position).
2112
- // Otherwise, simply returns the range between the given positions.
2113
- // Used for cursor motion and such.
2114
- function extendRange(doc, range, head, other) {
2115
- if (doc.cm && doc.cm.display.shift || doc.extend) {
2116
- var anchor = range.anchor;
2117
- if (other) {
2118
- var posBefore = cmp(head, anchor) < 0;
2119
- if (posBefore != (cmp(other, anchor) < 0)) {
2120
- anchor = head;
2121
- head = other;
2122
- } else if (posBefore != (cmp(head, other) < 0)) {
2123
- head = other;
2124
- }
2125
  }
2126
- return new Range(anchor, head);
2127
- } else {
2128
- return new Range(other || head, head);
2129
- }
2130
- }
2131
-
2132
- // Extend the primary selection range, discard the rest.
2133
- function extendSelection(doc, head, other, options) {
2134
- setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
2135
- }
2136
-
2137
- // Extend all selections (pos is an array of selections with length
2138
- // equal the number of selections)
2139
- function extendSelections(doc, heads, options) {
2140
- for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
2141
- out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
2142
- var newSel = normalizeSelection(out, doc.sel.primIndex);
2143
- setSelection(doc, newSel, options);
2144
- }
2145
-
2146
- // Updates a single range in the selection.
2147
- function replaceOneSelection(doc, i, range, options) {
2148
- var ranges = doc.sel.ranges.slice(0);
2149
- ranges[i] = range;
2150
- setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
2151
- }
2152
-
2153
- // Reset the selection to a single range.
2154
- function setSimpleSelection(doc, anchor, head, options) {
2155
- setSelection(doc, simpleSelection(anchor, head), options);
2156
- }
2157
-
2158
- // Give beforeSelectionChange handlers a change to influence a
2159
- // selection update.
2160
- function filterSelectionChange(doc, sel, options) {
2161
- var obj = {
2162
- ranges: sel.ranges,
2163
- update: function(ranges) {
2164
- this.ranges = [];
2165
- for (var i = 0; i < ranges.length; i++)
2166
- this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
2167
- clipPos(doc, ranges[i].head));
2168
- },
2169
- origin: options && options.origin
2170
- };
2171
- signal(doc, "beforeSelectionChange", doc, obj);
2172
- if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2173
- if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);
2174
- else return sel;
2175
- }
2176
-
2177
- function setSelectionReplaceHistory(doc, sel, options) {
2178
- var done = doc.history.done, last = lst(done);
2179
- if (last && last.ranges) {
2180
- done[done.length - 1] = sel;
2181
- setSelectionNoUndo(doc, sel, options);
2182
- } else {
2183
- setSelection(doc, sel, options);
2184
- }
2185
- }
2186
-
2187
- // Set a new selection.
2188
- function setSelection(doc, sel, options) {
2189
- setSelectionNoUndo(doc, sel, options);
2190
- addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
2191
- }
2192
-
2193
- function setSelectionNoUndo(doc, sel, options) {
2194
- if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
2195
- sel = filterSelectionChange(doc, sel, options);
2196
-
2197
- var bias = options && options.bias ||
2198
- (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
2199
- setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
2200
-
2201
- if (!(options && options.scroll === false) && doc.cm)
2202
- ensureCursorVisible(doc.cm);
2203
- }
2204
-
2205
- function setSelectionInner(doc, sel) {
2206
- if (sel.equals(doc.sel)) return;
2207
 
2208
- doc.sel = sel;
 
 
 
 
 
2209
 
2210
- if (doc.cm) {
2211
- doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
2212
- signalCursorActivity(doc.cm);
2213
- }
2214
- signalLater(doc, "cursorActivity", doc);
2215
- }
2216
 
2217
- // Verify that the selection does not partially select any atomic
2218
- // marked ranges.
2219
- function reCheckSelection(doc) {
2220
- setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
2221
- }
 
 
 
 
 
 
 
2222
 
2223
- // Return a selection that does not partially select any atomic
2224
- // ranges.
2225
- function skipAtomicInSelection(doc, sel, bias, mayClear) {
2226
- var out;
2227
- for (var i = 0; i < sel.ranges.length; i++) {
2228
- var range = sel.ranges[i];
2229
- var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
2230
- var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
2231
- var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);
2232
- if (out || newAnchor != range.anchor || newHead != range.head) {
2233
- if (!out) out = sel.ranges.slice(0, i);
2234
- out[i] = new Range(newAnchor, newHead);
2235
  }
2236
- }
2237
- return out ? normalizeSelection(out, sel.primIndex) : sel;
2238
- }
2239
-
2240
- function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
2241
- var line = getLine(doc, pos.line);
2242
- if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
2243
- var sp = line.markedSpans[i], m = sp.marker;
2244
- if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
2245
- (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
2246
- if (mayClear) {
2247
- signal(m, "beforeCursorEnter");
2248
- if (m.explicitlyCleared) {
2249
- if (!line.markedSpans) break;
2250
- else {--i; continue;}
2251
- }
2252
- }
2253
- if (!m.atomic) continue;
2254
-
2255
- if (oldPos) {
2256
- var near = m.find(dir < 0 ? 1 : -1), diff;
2257
- if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) near = movePos(doc, near, -dir, line);
2258
- if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
2259
- return skipAtomicInner(doc, near, pos, dir, mayClear);
2260
- }
2261
 
2262
- var far = m.find(dir < 0 ? -1 : 1);
2263
- if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) far = movePos(doc, far, dir, line);
2264
- return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null;
 
 
 
 
 
 
2265
  }
2266
- }
2267
- return pos;
2268
- }
2269
-
2270
- // Ensure a given position is not inside an atomic range.
2271
- function skipAtomic(doc, pos, oldPos, bias, mayClear) {
2272
- var dir = bias || 1;
2273
- var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
2274
- (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
2275
- skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
2276
- (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));
2277
- if (!found) {
2278
- doc.cantEdit = true;
2279
- return Pos(doc.first, 0);
2280
- }
2281
- return found;
2282
- }
2283
 
2284
- function movePos(doc, pos, dir, line) {
2285
- if (dir < 0 && pos.ch == 0) {
2286
- if (pos.line > doc.first) return clipPos(doc, Pos(pos.line - 1));
2287
- else return null;
2288
- } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
2289
- if (pos.line < doc.first + doc.size - 1) return Pos(pos.line + 1, 0);
2290
- else return null;
2291
- } else {
2292
- return new Pos(pos.line, pos.ch + dir);
2293
- }
2294
- }
 
 
 
 
 
2295
 
2296
- // SELECTION DRAWING
2297
 
2298
- function updateSelection(cm) {
2299
- cm.display.input.showSelection(cm.display.input.prepareSelection());
2300
- }
 
 
 
 
 
 
 
 
2301
 
2302
- function prepareSelection(cm, primary) {
2303
- var doc = cm.doc, result = {};
2304
- var curFragment = result.cursors = document.createDocumentFragment();
2305
- var selFragment = result.selection = document.createDocumentFragment();
 
 
 
 
 
 
 
2306
 
2307
- for (var i = 0; i < doc.sel.ranges.length; i++) {
2308
- if (primary === false && i == doc.sel.primIndex) continue;
2309
- var range = doc.sel.ranges[i];
2310
- var collapsed = range.empty();
2311
- if (collapsed || cm.options.showCursorWhenSelecting)
2312
- drawSelectionCursor(cm, range.head, curFragment);
2313
- if (!collapsed)
2314
- drawSelectionRange(cm, range, selFragment);
2315
- }
2316
- return result;
2317
  }
 
2318
 
2319
- // Draws a cursor for the given range
2320
- function drawSelectionCursor(cm, head, output) {
2321
- var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);
2322
-
2323
- var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
2324
- cursor.style.left = pos.left + "px";
2325
- cursor.style.top = pos.top + "px";
2326
- cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
2327
-
2328
- if (pos.other) {
2329
- // Secondary cursor, shown when on a 'jump' in bi-directional text
2330
- var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
2331
- otherCursor.style.display = "";
2332
- otherCursor.style.left = pos.other.left + "px";
2333
- otherCursor.style.top = pos.other.top + "px";
2334
- otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
2335
- }
2336
  }
2337
-
2338
- // Draws the given range as a highlighted selection
2339
- function drawSelectionRange(cm, range, output) {
2340
- var display = cm.display, doc = cm.doc;
2341
- var fragment = document.createDocumentFragment();
2342
- var padding = paddingH(cm.display), leftSide = padding.left;
2343
- var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
2344
-
2345
- function add(left, top, width, bottom) {
2346
- if (top < 0) top = 0;
2347
- top = Math.round(top);
2348
- bottom = Math.round(bottom);
2349
- fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
2350
- "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
2351
- "px; height: " + (bottom - top) + "px"));
2352
- }
2353
-
2354
- function drawForLine(line, fromArg, toArg) {
2355
- var lineObj = getLine(doc, line);
2356
- var lineLen = lineObj.text.length;
2357
- var start, end;
2358
- function coords(ch, bias) {
2359
- return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
2360
- }
2361
-
2362
- iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
2363
- var leftPos = coords(from, "left"), rightPos, left, right;
2364
- if (from == to) {
2365
- rightPos = leftPos;
2366
- left = right = leftPos.left;
2367
- } else {
2368
- rightPos = coords(to - 1, "right");
2369
- if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
2370
- left = leftPos.left;
2371
- right = rightPos.right;
2372
- }
2373
- if (fromArg == null && from == 0) left = leftSide;
2374
- if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
2375
- add(left, leftPos.top, null, leftPos.bottom);
2376
- left = leftSide;
2377
- if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
2378
- }
2379
- if (toArg == null && to == lineLen) right = rightSide;
2380
- if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
2381
- start = leftPos;
2382
- if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
2383
- end = rightPos;
2384
- if (left < leftSide + 1) left = leftSide;
2385
- add(left, rightPos.top, right - left, rightPos.bottom);
2386
- });
2387
- return {start: start, end: end};
2388
- }
2389
-
2390
- var sFrom = range.from(), sTo = range.to();
2391
- if (sFrom.line == sTo.line) {
2392
- drawForLine(sFrom.line, sFrom.ch, sTo.ch);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2393
  } else {
2394
- var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
2395
- var singleVLine = visualLine(fromLine) == visualLine(toLine);
2396
- var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
2397
- var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
2398
- if (singleVLine) {
2399
- if (leftEnd.top < rightStart.top - 2) {
2400
- add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
2401
- add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
2402
- } else {
2403
- add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
2404
- }
2405
- }
2406
- if (leftEnd.bottom < rightStart.top)
2407
- add(leftSide, leftEnd.bottom, null, rightStart.top);
2408
- }
2409
-
2410
- output.appendChild(fragment);
2411
- }
2412
-
2413
- // Cursor-blinking
2414
- function restartBlink(cm) {
2415
- if (!cm.state.focused) return;
2416
- var display = cm.display;
2417
- clearInterval(display.blinker);
2418
- var on = true;
2419
- display.cursorDiv.style.visibility = "";
2420
- if (cm.options.cursorBlinkRate > 0)
2421
- display.blinker = setInterval(function() {
2422
- display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
2423
- }, cm.options.cursorBlinkRate);
2424
- else if (cm.options.cursorBlinkRate < 0)
2425
- display.cursorDiv.style.visibility = "hidden";
2426
- }
2427
-
2428
- // HIGHLIGHT WORKER
2429
-
2430
- function startWorker(cm, time) {
2431
- if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
2432
- cm.state.highlight.set(time, bind(highlightWorker, cm));
2433
- }
2434
-
2435
- function highlightWorker(cm) {
2436
- var doc = cm.doc;
2437
- if (doc.frontier < doc.first) doc.frontier = doc.first;
2438
- if (doc.frontier >= cm.display.viewTo) return;
2439
- var end = +new Date + cm.options.workTime;
2440
- var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
2441
- var changedLines = [];
2442
-
2443
- doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
2444
- if (doc.frontier >= cm.display.viewFrom) { // Visible
2445
- var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength;
2446
- var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true);
2447
- line.styles = highlighted.styles;
2448
- var oldCls = line.styleClasses, newCls = highlighted.classes;
2449
- if (newCls) line.styleClasses = newCls;
2450
- else if (oldCls) line.styleClasses = null;
2451
- var ischange = !oldStyles || oldStyles.length != line.styles.length ||
2452
- oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
2453
- for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
2454
- if (ischange) changedLines.push(doc.frontier);
2455
- line.stateAfter = tooLong ? state : copyState(doc.mode, state);
2456
- } else {
2457
- if (line.text.length <= cm.options.maxHighlightLength)
2458
- processLine(cm, line.text, state);
2459
- line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
2460
- }
2461
- ++doc.frontier;
2462
- if (+new Date > end) {
2463
- startWorker(cm, cm.options.workDelay);
2464
- return true;
2465
- }
2466
- });
2467
- if (changedLines.length) runInOp(cm, function() {
2468
- for (var i = 0; i < changedLines.length; i++)
2469
- regLineChange(cm, changedLines[i], "text");
2470
- });
2471
- }
2472
-
2473
- // Finds the line to start with when starting a parse. Tries to
2474
- // find a line with a stateAfter, so that it can start with a
2475
- // valid state. If that fails, it returns the line with the
2476
- // smallest indentation, which tends to need the least context to
2477
- // parse correctly.
2478
- function findStartLine(cm, n, precise) {
2479
- var minindent, minline, doc = cm.doc;
2480
- var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
2481
- for (var search = n; search > lim; --search) {
2482
- if (search <= doc.first) return doc.first;
2483
- var line = getLine(doc, search - 1);
2484
- if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
2485
- var indented = countColumn(line.text, null, cm.options.tabSize);
2486
- if (minline == null || minindent > indented) {
2487
- minline = search - 1;
2488
- minindent = indented;
2489
  }
2490
- }
2491
- return minline;
2492
- }
2493
-
2494
- function getStateBefore(cm, n, precise) {
2495
- var doc = cm.doc, display = cm.display;
2496
- if (!doc.mode.startState) return true;
2497
- var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
2498
- if (!state) state = startState(doc.mode);
2499
- else state = copyState(doc.mode, state);
2500
- doc.iter(pos, n, function(line) {
2501
- processLine(cm, line.text, state);
2502
- var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
2503
- line.stateAfter = save ? copyState(doc.mode, state) : null;
2504
- ++pos;
2505
- });
2506
- if (precise) doc.frontier = pos;
2507
- return state;
2508
- }
2509
-
2510
- // POSITION MEASUREMENT
2511
-
2512
- function paddingTop(display) {return display.lineSpace.offsetTop;}
2513
- function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
2514
- function paddingH(display) {
2515
- if (display.cachedPaddingH) return display.cachedPaddingH;
2516
- var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
2517
- var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
2518
- var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
2519
- if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
2520
- return data;
2521
- }
2522
-
2523
- function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }
2524
- function displayWidth(cm) {
2525
- return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;
2526
- }
2527
- function displayHeight(cm) {
2528
- return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;
2529
- }
2530
-
2531
- // Ensure the lineView.wrapping.heights array is populated. This is
2532
- // an array of bottom offsets for the lines that make up a drawn
2533
- // line. When lineWrapping is on, there might be more than one
2534
- // height.
2535
- function ensureLineHeights(cm, lineView, rect) {
2536
- var wrapping = cm.options.lineWrapping;
2537
- var curWidth = wrapping && displayWidth(cm);
2538
- if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
2539
- var heights = lineView.measure.heights = [];
2540
- if (wrapping) {
2541
- lineView.measure.width = curWidth;
2542
- var rects = lineView.text.firstChild.getClientRects();
2543
- for (var i = 0; i < rects.length - 1; i++) {
2544
- var cur = rects[i], next = rects[i + 1];
2545
- if (Math.abs(cur.bottom - next.bottom) > 2)
2546
- heights.push((cur.bottom + next.top) / 2 - rect.top);
2547
- }
2548
- }
2549
- heights.push(rect.bottom - rect.top);
2550
- }
2551
- }
2552
-
2553
- // Find a line map (mapping character offsets to text nodes) and a
2554
- // measurement cache for the given line number. (A line view might
2555
- // contain multiple lines when collapsed ranges are present.)
2556
- function mapFromLineView(lineView, line, lineN) {
2557
- if (lineView.line == line)
2558
- return {map: lineView.measure.map, cache: lineView.measure.cache};
2559
- for (var i = 0; i < lineView.rest.length; i++)
2560
- if (lineView.rest[i] == line)
2561
- return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
2562
- for (var i = 0; i < lineView.rest.length; i++)
2563
- if (lineNo(lineView.rest[i]) > lineN)
2564
- return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
2565
- }
2566
-
2567
- // Render a line into the hidden node display.externalMeasured. Used
2568
- // when measurement is needed for a line that's not in the viewport.
2569
- function updateExternalMeasurement(cm, line) {
2570
- line = visualLine(line);
2571
- var lineN = lineNo(line);
2572
- var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
2573
- view.lineN = lineN;
2574
- var built = view.built = buildLineContent(cm, view);
2575
- view.text = built.pre;
2576
- removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
2577
- return view;
2578
- }
2579
-
2580
- // Get a {top, bottom, left, right} box (in line-local coordinates)
2581
- // for a given character.
2582
- function measureChar(cm, line, ch, bias) {
2583
- return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
2584
- }
2585
-
2586
- // Find a line view that corresponds to the given line number.
2587
- function findViewForLine(cm, lineN) {
2588
- if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
2589
- return cm.display.view[findViewIndex(cm, lineN)];
2590
- var ext = cm.display.externalMeasured;
2591
- if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
2592
- return ext;
2593
- }
2594
-
2595
- // Measurement can be split in two steps, the set-up work that
2596
- // applies to the whole line, and the measurement of the actual
2597
- // character. Functions like coordsChar, that need to do a lot of
2598
- // measurements in a row, can thus ensure that the set-up work is
2599
- // only done once.
2600
- function prepareMeasureForLine(cm, line) {
2601
- var lineN = lineNo(line);
2602
- var view = findViewForLine(cm, lineN);
2603
- if (view && !view.text) {
2604
- view = null;
2605
- } else if (view && view.changes) {
2606
- updateLineForChanges(cm, view, lineN, getDimensions(cm));
2607
- cm.curOp.forceUpdate = true;
2608
- }
2609
- if (!view)
2610
- view = updateExternalMeasurement(cm, line);
2611
-
2612
- var info = mapFromLineView(view, line, lineN);
2613
- return {
2614
- line: line, view: view, rect: null,
2615
- map: info.map, cache: info.cache, before: info.before,
2616
- hasHeights: false
2617
- };
2618
- }
2619
-
2620
- // Given a prepared measurement object, measures the position of an
2621
- // actual character (or fetches it from the cache).
2622
- function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
2623
- if (prepared.before) ch = -1;
2624
- var key = ch + (bias || ""), found;
2625
- if (prepared.cache.hasOwnProperty(key)) {
2626
- found = prepared.cache[key];
2627
  } else {
2628
- if (!prepared.rect)
2629
- prepared.rect = prepared.view.text.getBoundingClientRect();
2630
- if (!prepared.hasHeights) {
2631
- ensureLineHeights(cm, prepared.view, prepared.rect);
2632
- prepared.hasHeights = true;
2633
- }
2634
- found = measureCharInner(cm, prepared, ch, bias);
2635
- if (!found.bogus) prepared.cache[key] = found;
2636
- }
2637
- return {left: found.left, right: found.right,
2638
- top: varHeight ? found.rtop : found.top,
2639
- bottom: varHeight ? found.rbottom : found.bottom};
2640
- }
2641
-
2642
- var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
2643
-
2644
- function nodeAndOffsetInLineMap(map, ch, bias) {
2645
- var node, start, end, collapse;
2646
- // First, search the line map for the text node corresponding to,
2647
- // or closest to, the target character.
2648
- for (var i = 0; i < map.length; i += 3) {
2649
- var mStart = map[i], mEnd = map[i + 1];
2650
- if (ch < mStart) {
2651
- start = 0; end = 1;
2652
- collapse = "left";
2653
- } else if (ch < mEnd) {
2654
- start = ch - mStart;
2655
- end = start + 1;
2656
- } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
2657
- end = mEnd - mStart;
2658
- start = end - 1;
2659
- if (ch >= mEnd) collapse = "right";
2660
- }
2661
- if (start != null) {
2662
- node = map[i + 2];
2663
- if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
2664
- collapse = bias;
2665
- if (bias == "left" && start == 0)
2666
- while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
2667
- node = map[(i -= 3) + 2];
2668
- collapse = "left";
2669
- }
2670
- if (bias == "right" && start == mEnd - mStart)
2671
- while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
2672
- node = map[(i += 3) + 2];
2673
- collapse = "right";
2674
- }
2675
- break;
2676
- }
2677
- }
2678
- return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};
2679
- }
2680
-
2681
- function measureCharInner(cm, prepared, ch, bias) {
2682
- var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
2683
- var node = place.node, start = place.start, end = place.end, collapse = place.collapse;
2684
-
2685
- var rect;
2686
- if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
2687
- for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
2688
- while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;
2689
- while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;
2690
- if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) {
2691
- rect = node.parentNode.getBoundingClientRect();
2692
- } else if (ie && cm.options.lineWrapping) {
2693
- var rects = range(node, start, end).getClientRects();
2694
- if (rects.length)
2695
- rect = rects[bias == "right" ? rects.length - 1 : 0];
2696
- else
2697
- rect = nullRect;
2698
- } else {
2699
- rect = range(node, start, end).getBoundingClientRect() || nullRect;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2700
  }
2701
- if (rect.left || rect.right || start == 0) break;
2702
- end = start;
2703
- start = start - 1;
2704
- collapse = "right";
2705
- }
2706
- if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);
2707
- } else { // If it is a widget, simply get the box for the whole widget.
2708
- if (start > 0) collapse = bias = "right";
2709
- var rects;
2710
- if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
2711
- rect = rects[bias == "right" ? rects.length - 1 : 0];
2712
- else
2713
- rect = node.getBoundingClientRect();
2714
- }
2715
- if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
2716
- var rSpan = node.parentNode.getClientRects()[0];
2717
- if (rSpan)
2718
- rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
2719
- else
2720
- rect = nullRect;
2721
- }
2722
-
2723
- var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
2724
- var mid = (rtop + rbot) / 2;
2725
- var heights = prepared.view.measure.heights;
2726
- for (var i = 0; i < heights.length - 1; i++)
2727
- if (mid < heights[i]) break;
2728
- var top = i ? heights[i - 1] : 0, bot = heights[i];
2729
- var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
2730
- right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
2731
- top: top, bottom: bot};
2732
- if (!rect.left && !rect.right) result.bogus = true;
2733
- if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
2734
-
2735
- return result;
2736
- }
2737
-
2738
- // Work around problem with bounding client rects on ranges being
2739
- // returned incorrectly when zoomed on IE10 and below.
2740
- function maybeUpdateRectForZooming(measure, rect) {
2741
- if (!window.screen || screen.logicalXDPI == null ||
2742
- screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
2743
- return rect;
2744
- var scaleX = screen.logicalXDPI / screen.deviceXDPI;
2745
- var scaleY = screen.logicalYDPI / screen.deviceYDPI;
2746
- return {left: rect.left * scaleX, right: rect.right * scaleX,
2747
- top: rect.top * scaleY, bottom: rect.bottom * scaleY};
2748
- }
2749
-
2750
- function clearLineMeasurementCacheFor(lineView) {
2751
- if (lineView.measure) {
2752
- lineView.measure.cache = {};
2753
- lineView.measure.heights = null;
2754
- if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
2755
- lineView.measure.caches[i] = {};
2756
- }
2757
- }
2758
-
2759
- function clearLineMeasurementCache(cm) {
2760
- cm.display.externalMeasure = null;
2761
- removeChildren(cm.display.lineMeasure);
2762
- for (var i = 0; i < cm.display.view.length; i++)
2763
- clearLineMeasurementCacheFor(cm.display.view[i]);
2764
- }
2765
-
2766
- function clearCaches(cm) {
2767
- clearLineMeasurementCache(cm);
2768
- cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
2769
- if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
2770
- cm.display.lineNumChars = null;
2771
- }
2772
-
2773
- function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
2774
- function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
2775
-
2776
- // Converts a {top, bottom, left, right} box from line-local
2777
- // coordinates into another coordinate system. Context may be one of
2778
- // "line", "div" (display.lineDiv), "local"/null (editor), "window",
2779
- // or "page".
2780
- function intoCoordSystem(cm, lineObj, rect, context) {
2781
- if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
2782
- var size = widgetHeight(lineObj.widgets[i]);
2783
- rect.top += size; rect.bottom += size;
2784
- }
2785
- if (context == "line") return rect;
2786
- if (!context) context = "local";
2787
- var yOff = heightAtLine(lineObj);
2788
- if (context == "local") yOff += paddingTop(cm.display);
2789
- else yOff -= cm.display.viewOffset;
2790
- if (context == "page" || context == "window") {
2791
- var lOff = cm.display.lineSpace.getBoundingClientRect();
2792
- yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
2793
- var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
2794
- rect.left += xOff; rect.right += xOff;
2795
- }
2796
- rect.top += yOff; rect.bottom += yOff;
2797
- return rect;
2798
- }
2799
-
2800
- // Coverts a box from "div" coords to another coordinate system.
2801
- // Context may be "window", "page", "div", or "local"/null.
2802
- function fromCoordSystem(cm, coords, context) {
2803
- if (context == "div") return coords;
2804
- var left = coords.left, top = coords.top;
2805
- // First move into "page" coordinate system
2806
- if (context == "page") {
2807
- left -= pageScrollX();
2808
- top -= pageScrollY();
2809
- } else if (context == "local" || !context) {
2810
- var localBox = cm.display.sizer.getBoundingClientRect();
2811
- left += localBox.left;
2812
- top += localBox.top;
2813
- }
2814
-
2815
- var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
2816
- return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
2817
- }
2818
-
2819
- function charCoords(cm, pos, context, lineObj, bias) {
2820
- if (!lineObj) lineObj = getLine(cm.doc, pos.line);
2821
- return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
2822
- }
2823
-
2824
- // Returns a box for a given cursor position, which may have an
2825
- // 'other' property containing the position of the secondary cursor
2826
- // on a bidi boundary.
2827
- function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
2828
- lineObj = lineObj || getLine(cm.doc, pos.line);
2829
- if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);
2830
- function get(ch, right) {
2831
- var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
2832
- if (right) m.left = m.right; else m.right = m.left;
2833
- return intoCoordSystem(cm, lineObj, m, context);
2834
- }
2835
- function getBidi(ch, partPos) {
2836
- var part = order[partPos], right = part.level % 2;
2837
- if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
2838
- part = order[--partPos];
2839
- ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
2840
- right = true;
2841
- } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
2842
- part = order[++partPos];
2843
- ch = bidiLeft(part) - part.level % 2;
2844
- right = false;
2845
- }
2846
- if (right && ch == part.to && ch > part.from) return get(ch - 1);
2847
- return get(ch, right);
2848
- }
2849
- var order = getOrder(lineObj), ch = pos.ch;
2850
- if (!order) return get(ch);
2851
- var partPos = getBidiPartAt(order, ch);
2852
- var val = getBidi(ch, partPos);
2853
- if (bidiOther != null) val.other = getBidi(ch, bidiOther);
2854
- return val;
2855
- }
2856
-
2857
- // Used to cheaply estimate the coordinates for a position. Used for
2858
- // intermediate scroll updates.
2859
- function estimateCoords(cm, pos) {
2860
- var left = 0, pos = clipPos(cm.doc, pos);
2861
- if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;
2862
- var lineObj = getLine(cm.doc, pos.line);
2863
- var top = heightAtLine(lineObj) + paddingTop(cm.display);
2864
- return {left: left, right: left, top: top, bottom: top + lineObj.height};
2865
- }
2866
-
2867
- // Positions returned by coordsChar contain some extra information.
2868
- // xRel is the relative x position of the input coordinates compared
2869
- // to the found position (so xRel > 0 means the coordinates are to
2870
- // the right of the character position, for example). When outside
2871
- // is true, that means the coordinates lie outside the line's
2872
- // vertical range.
2873
- function PosWithInfo(line, ch, outside, xRel) {
2874
- var pos = Pos(line, ch);
2875
- pos.xRel = xRel;
2876
- if (outside) pos.outside = true;
2877
- return pos;
2878
- }
2879
-
2880
- // Compute the character position closest to the given coordinates.
2881
- // Input must be lineSpace-local ("div" coordinate system).
2882
- function coordsChar(cm, x, y) {
2883
- var doc = cm.doc;
2884
- y += cm.display.viewOffset;
2885
- if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
2886
- var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
2887
- if (lineN > last)
2888
- return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
2889
- if (x < 0) x = 0;
2890
-
2891
- var lineObj = getLine(doc, lineN);
2892
- for (;;) {
2893
- var found = coordsCharInner(cm, lineObj, lineN, x, y);
2894
- var merged = collapsedSpanAtEnd(lineObj);
2895
- var mergedPos = merged && merged.find(0, true);
2896
- if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
2897
- lineN = lineNo(lineObj = mergedPos.to.line);
2898
- else
2899
- return found;
2900
- }
2901
- }
2902
-
2903
- function coordsCharInner(cm, lineObj, lineNo, x, y) {
2904
- var innerOff = y - heightAtLine(lineObj);
2905
- var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
2906
- var preparedMeasure = prepareMeasureForLine(cm, lineObj);
2907
-
2908
- function getX(ch) {
2909
- var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
2910
- wrongLine = true;
2911
- if (innerOff > sp.bottom) return sp.left - adjust;
2912
- else if (innerOff < sp.top) return sp.left + adjust;
2913
- else wrongLine = false;
2914
- return sp.left;
2915
- }
2916
-
2917
- var bidi = getOrder(lineObj), dist = lineObj.text.length;
2918
- var from = lineLeft(lineObj), to = lineRight(lineObj);
2919
- var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
2920
-
2921
- if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
2922
- // Do a binary search between these bounds.
2923
- for (;;) {
2924
- if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
2925
- var ch = x < fromX || x - fromX <= toX - x ? from : to;
2926
- var xDiff = x - (ch == from ? fromX : toX);
2927
- while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
2928
- var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
2929
- xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
2930
- return pos;
2931
- }
2932
- var step = Math.ceil(dist / 2), middle = from + step;
2933
- if (bidi) {
2934
- middle = from;
2935
- for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
2936
- }
2937
- var middleX = getX(middle);
2938
- if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
2939
- else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
2940
- }
2941
- }
2942
-
2943
- var measureText;
2944
- // Compute the default text height.
2945
- function textHeight(display) {
2946
- if (display.cachedTextHeight != null) return display.cachedTextHeight;
2947
- if (measureText == null) {
2948
- measureText = elt("pre");
2949
- // Measure a bunch of lines, for browsers that compute
2950
- // fractional heights.
2951
- for (var i = 0; i < 49; ++i) {
2952
- measureText.appendChild(document.createTextNode("x"));
2953
- measureText.appendChild(elt("br"));
2954
- }
2955
- measureText.appendChild(document.createTextNode("x"));
2956
- }
2957
- removeChildrenAndAdd(display.measure, measureText);
2958
- var height = measureText.offsetHeight / 50;
2959
- if (height > 3) display.cachedTextHeight = height;
2960
- removeChildren(display.measure);
2961
- return height || 1;
2962
- }
2963
-
2964
- // Compute the default character width.
2965
- function charWidth(display) {
2966
- if (display.cachedCharWidth != null) return display.cachedCharWidth;
2967
- var anchor = elt("span", "xxxxxxxxxx");
2968
- var pre = elt("pre", [anchor]);
2969
- removeChildrenAndAdd(display.measure, pre);
2970
- var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
2971
- if (width > 2) display.cachedCharWidth = width;
2972
- return width || 10;
2973
- }
2974
-
2975
- // OPERATIONS
2976
-
2977
- // Operations are used to wrap a series of changes to the editor
2978
- // state in such a way that each change won't have to update the
2979
- // cursor and display (which would be awkward, slow, and
2980
- // error-prone). Instead, display updates are batched and then all
2981
- // combined and executed at once.
2982
-
2983
- var operationGroup = null;
2984
-
2985
- var nextOpId = 0;
2986
- // Start a new operation.
2987
- function startOperation(cm) {
2988
- cm.curOp = {
2989
- cm: cm,
2990
- viewChanged: false, // Flag that indicates that lines might need to be redrawn
2991
- startHeight: cm.doc.height, // Used to detect need to update scrollbar
2992
- forceUpdate: false, // Used to force a redraw
2993
- updateInput: null, // Whether to reset the input textarea
2994
- typing: false, // Whether this reset should be careful to leave existing text (for compositing)
2995
- changeObjs: null, // Accumulated changes, for firing change events
2996
- cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
2997
- cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
2998
- selectionChanged: false, // Whether the selection needs to be redrawn
2999
- updateMaxLine: false, // Set when the widest line needs to be determined anew
3000
- scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
3001
- scrollToPos: null, // Used to scroll to a specific position
3002
- focus: false,
3003
- id: ++nextOpId // Unique ID
3004
- };
3005
- if (operationGroup) {
3006
- operationGroup.ops.push(cm.curOp);
3007
- } else {
3008
- cm.curOp.ownsGroup = operationGroup = {
3009
- ops: [cm.curOp],
3010
- delayedCallbacks: []
3011
- };
3012
- }
3013
- }
3014
-
3015
- function fireCallbacksForOps(group) {
3016
- // Calls delayed callbacks and cursorActivity handlers until no
3017
- // new ones appear
3018
- var callbacks = group.delayedCallbacks, i = 0;
3019
- do {
3020
- for (; i < callbacks.length; i++)
3021
- callbacks[i].call(null);
3022
- for (var j = 0; j < group.ops.length; j++) {
3023
- var op = group.ops[j];
3024
- if (op.cursorActivityHandlers)
3025
- while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
3026
- op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm);
3027
  }
3028
- } while (i < callbacks.length);
3029
- }
3030
-
3031
- // Finish an operation, updating the display and signalling delayed events
3032
- function endOperation(cm) {
3033
- var op = cm.curOp, group = op.ownsGroup;
3034
- if (!group) return;
3035
-
3036
- try { fireCallbacksForOps(group); }
3037
- finally {
3038
- operationGroup = null;
3039
- for (var i = 0; i < group.ops.length; i++)
3040
- group.ops[i].cm.curOp = null;
3041
- endOperations(group);
3042
  }
3043
  }
 
 
3044
 
3045
- // The DOM updates done when an operation finishes are batched so
3046
- // that the minimum number of relayouts are required.
3047
- function endOperations(group) {
3048
- var ops = group.ops;
3049
- for (var i = 0; i < ops.length; i++) // Read DOM
3050
- endOperation_R1(ops[i]);
3051
- for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
3052
- endOperation_W1(ops[i]);
3053
- for (var i = 0; i < ops.length; i++) // Read DOM
3054
- endOperation_R2(ops[i]);
3055
- for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
3056
- endOperation_W2(ops[i]);
3057
- for (var i = 0; i < ops.length; i++) // Read DOM
3058
- endOperation_finish(ops[i]);
3059
- }
3060
-
3061
- function endOperation_R1(op) {
3062
- var cm = op.cm, display = cm.display;
3063
- maybeClipScrollbars(cm);
3064
- if (op.updateMaxLine) findMaxLine(cm);
3065
-
3066
- op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
3067
- op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
3068
- op.scrollToPos.to.line >= display.viewTo) ||
3069
- display.maxLineChanged && cm.options.lineWrapping;
3070
- op.update = op.mustUpdate &&
3071
- new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
3072
- }
3073
-
3074
- function endOperation_W1(op) {
3075
- op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
3076
  }
3077
-
3078
- function endOperation_R2(op) {
3079
- var cm = op.cm, display = cm.display;
3080
- if (op.updatedDisplay) updateHeightsInViewport(cm);
3081
-
3082
- op.barMeasure = measureForScrollbars(cm);
3083
-
3084
- // If the max line changed since it was last measured, measure it,
3085
- // and ensure the document's width matches it.
3086
- // updateDisplay_W2 will use these properties to do the actual resizing
3087
- if (display.maxLineChanged && !cm.options.lineWrapping) {
3088
- op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
3089
- cm.display.sizerWidth = op.adjustWidthTo;
3090
- op.barMeasure.scrollWidth =
3091
- Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
3092
- op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
3093
- }
3094
-
3095
- if (op.updatedDisplay || op.selectionChanged)
3096
- op.preparedSelection = display.input.prepareSelection();
3097
- }
3098
-
3099
- function endOperation_W2(op) {
3100
- var cm = op.cm;
3101
-
3102
- if (op.adjustWidthTo != null) {
3103
- cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
3104
- if (op.maxScrollLeft < cm.doc.scrollLeft)
3105
- setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);
3106
- cm.display.maxLineChanged = false;
3107
- }
3108
-
3109
- if (op.preparedSelection)
3110
- cm.display.input.showSelection(op.preparedSelection);
3111
- if (op.updatedDisplay)
3112
- setDocumentHeight(cm, op.barMeasure);
3113
- if (op.updatedDisplay || op.startHeight != cm.doc.height)
3114
- updateScrollbars(cm, op.barMeasure);
3115
-
3116
- if (op.selectionChanged) restartBlink(cm);
3117
-
3118
- if (cm.state.focused && op.updateInput)
3119
- cm.display.input.reset(op.typing);
3120
- if (op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()))
3121
- ensureFocus(op.cm);
3122
- }
3123
-
3124
- function endOperation_finish(op) {
3125
- var cm = op.cm, display = cm.display, doc = cm.doc;
3126
-
3127
- if (op.updatedDisplay) postUpdateDisplay(cm, op.update);
3128
-
3129
- // Abort mouse wheel delta measurement, when scrolling explicitly
3130
- if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
3131
- display.wheelStartX = display.wheelStartY = null;
3132
-
3133
- // Propagate the scroll position to the actual DOM scroller
3134
- if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
3135
- doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
3136
- display.scrollbars.setScrollTop(doc.scrollTop);
3137
- display.scroller.scrollTop = doc.scrollTop;
3138
- }
3139
- if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
3140
- doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
3141
- display.scrollbars.setScrollLeft(doc.scrollLeft);
3142
- display.scroller.scrollLeft = doc.scrollLeft;
3143
- alignHorizontally(cm);
3144
- }
3145
- // If we need to scroll a specific position into view, do so.
3146
- if (op.scrollToPos) {
3147
- var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
3148
- clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
3149
- if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
3150
- }
3151
-
3152
- // Fire events for markers that are hidden/unidden by editing or
3153
- // undoing
3154
- var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
3155
- if (hidden) for (var i = 0; i < hidden.length; ++i)
3156
- if (!hidden[i].lines.length) signal(hidden[i], "hide");
3157
- if (unhidden) for (var i = 0; i < unhidden.length; ++i)
3158
- if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
3159
-
3160
- if (display.wrapper.offsetHeight)
3161
- doc.scrollTop = cm.display.scroller.scrollTop;
3162
-
3163
- // Fire change events, and delayed event handlers
3164
- if (op.changeObjs)
3165
- signal(cm, "changes", cm, op.changeObjs);
3166
- if (op.update)
3167
- op.update.finish();
3168
- }
3169
-
3170
- // Run the given function in an operation
3171
- function runInOp(cm, f) {
3172
- if (cm.curOp) return f();
3173
- startOperation(cm);
3174
- try { return f(); }
3175
- finally { endOperation(cm); }
3176
- }
3177
- // Wraps a function in an operation. Returns the wrapped function.
3178
- function operation(cm, f) {
3179
- return function() {
3180
- if (cm.curOp) return f.apply(cm, arguments);
3181
- startOperation(cm);
3182
- try { return f.apply(cm, arguments); }
3183
- finally { endOperation(cm); }
3184
- };
3185
- }
3186
- // Used to add methods to editor and doc instances, wrapping them in
3187
- // operations.
3188
- function methodOp(f) {
3189
- return function() {
3190
- if (this.curOp) return f.apply(this, arguments);
3191
- startOperation(this);
3192
- try { return f.apply(this, arguments); }
3193
- finally { endOperation(this); }
3194
- };
3195
- }
3196
- function docMethodOp(f) {
3197
- return function() {
3198
- var cm = this.cm;
3199
- if (!cm || cm.curOp) return f.apply(this, arguments);
3200
- startOperation(cm);
3201
- try { return f.apply(this, arguments); }
3202
- finally { endOperation(cm); }
3203
- };
3204
- }
3205
-
3206
- // VIEW TRACKING
3207
-
3208
- // These objects are used to represent the visible (currently drawn)
3209
- // part of the document. A LineView may correspond to multiple
3210
- // logical lines, if those are connected by collapsed ranges.
3211
- function LineView(doc, line, lineN) {
3212
- // The starting line
3213
- this.line = line;
3214
- // Continuing lines, if any
3215
- this.rest = visualLineContinued(line);
3216
- // Number of logical lines in this visual line
3217
- this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
3218
- this.node = this.text = null;
3219
- this.hidden = lineIsHidden(doc, line);
3220
- }
3221
-
3222
- // Create a range of LineView objects for the given lines.
3223
- function buildViewArray(cm, from, to) {
3224
- var array = [], nextPos;
3225
- for (var pos = from; pos < to; pos = nextPos) {
3226
- var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
3227
- nextPos = pos + view.size;
3228
- array.push(view);
3229
- }
3230
- return array;
3231
- }
3232
-
3233
- // Updates the display.view data structure for a given change to the
3234
- // document. From and to are in pre-change coordinates. Lendiff is
3235
- // the amount of lines added or subtracted by the change. This is
3236
- // used for changes that span multiple lines, or change the way
3237
- // lines are divided into visual lines. regLineChange (below)
3238
- // registers single-line changes.
3239
- function regChange(cm, from, to, lendiff) {
3240
- if (from == null) from = cm.doc.first;
3241
- if (to == null) to = cm.doc.first + cm.doc.size;
3242
- if (!lendiff) lendiff = 0;
3243
-
3244
- var display = cm.display;
3245
- if (lendiff && to < display.viewTo &&
3246
- (display.updateLineNumbers == null || display.updateLineNumbers > from))
3247
- display.updateLineNumbers = from;
3248
-
3249
- cm.curOp.viewChanged = true;
3250
-
3251
- if (from >= display.viewTo) { // Change after
3252
- if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
3253
- resetView(cm);
3254
- } else if (to <= display.viewFrom) { // Change before
3255
- if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
3256
- resetView(cm);
3257
- } else {
3258
- display.viewFrom += lendiff;
3259
- display.viewTo += lendiff;
3260
- }
3261
- } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
3262
- resetView(cm);
3263
- } else if (from <= display.viewFrom) { // Top overlap
3264
- var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
3265
- if (cut) {
3266
- display.view = display.view.slice(cut.index);
3267
- display.viewFrom = cut.lineN;
3268
- display.viewTo += lendiff;
3269
- } else {
3270
- resetView(cm);
3271
- }
3272
- } else if (to >= display.viewTo) { // Bottom overlap
3273
- var cut = viewCuttingPoint(cm, from, from, -1);
3274
- if (cut) {
3275
- display.view = display.view.slice(0, cut.index);
3276
- display.viewTo = cut.lineN;
3277
- } else {
3278
- resetView(cm);
3279
- }
3280
- } else { // Gap in the middle
3281
- var cutTop = viewCuttingPoint(cm, from, from, -1);
3282
- var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
3283
- if (cutTop && cutBot) {
3284
- display.view = display.view.slice(0, cutTop.index)
3285
- .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
3286
- .concat(display.view.slice(cutBot.index));
3287
- display.viewTo += lendiff;
3288
- } else {
3289
- resetView(cm);
3290
- }
3291
- }
3292
-
3293
- var ext = display.externalMeasured;
3294
- if (ext) {
3295
- if (to < ext.lineN)
3296
- ext.lineN += lendiff;
3297
- else if (from < ext.lineN + ext.size)
3298
- display.externalMeasured = null;
3299
- }
3300
- }
3301
-
3302
- // Register a change to a single line. Type must be one of "text",
3303
- // "gutter", "class", "widget"
3304
- function regLineChange(cm, line, type) {
3305
- cm.curOp.viewChanged = true;
3306
- var display = cm.display, ext = cm.display.externalMeasured;
3307
- if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
3308
- display.externalMeasured = null;
3309
-
3310
- if (line < display.viewFrom || line >= display.viewTo) return;
3311
- var lineView = display.view[findViewIndex(cm, line)];
3312
- if (lineView.node == null) return;
3313
- var arr = lineView.changes || (lineView.changes = []);
3314
- if (indexOf(arr, type) == -1) arr.push(type);
3315
- }
3316
-
3317
- // Clear the view.
3318
- function resetView(cm) {
3319
- cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
3320
- cm.display.view = [];
3321
- cm.display.viewOffset = 0;
3322
- }
3323
-
3324
- // Find the view element corresponding to a given line. Return null
3325
- // when the line isn't visible.
3326
- function findViewIndex(cm, n) {
3327
- if (n >= cm.display.viewTo) return null;
3328
- n -= cm.display.viewFrom;
3329
- if (n < 0) return null;
3330
- var view = cm.display.view;
3331
- for (var i = 0; i < view.length; i++) {
3332
- n -= view[i].size;
3333
- if (n < 0) return i;
3334
- }
3335
- }
3336
-
3337
- function viewCuttingPoint(cm, oldN, newN, dir) {
3338
- var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
3339
- if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
3340
- return {index: index, lineN: newN};
3341
- for (var i = 0, n = cm.display.viewFrom; i < index; i++)
3342
- n += view[i].size;
3343
- if (n != oldN) {
3344
- if (dir > 0) {
3345
- if (index == view.length - 1) return null;
3346
- diff = (n + view[index].size) - oldN;
3347
- index++;
3348
  } else {
3349
- diff = n - oldN;
3350
- }
3351
- oldN += diff; newN += diff;
3352
- }
3353
- while (visualLineNo(cm.doc, newN) != newN) {
3354
- if (index == (dir < 0 ? 0 : view.length - 1)) return null;
3355
- newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
3356
- index += dir;
3357
- }
3358
- return {index: index, lineN: newN};
3359
- }
3360
-
3361
- // Force the view to cover a given range, adding empty view element
3362
- // or clipping off existing ones as needed.
3363
- function adjustView(cm, from, to) {
3364
- var display = cm.display, view = display.view;
3365
- if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
3366
- display.view = buildViewArray(cm, from, to);
3367
- display.viewFrom = from;
3368
- } else {
3369
- if (display.viewFrom > from)
3370
- display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);
3371
- else if (display.viewFrom < from)
3372
- display.view = display.view.slice(findViewIndex(cm, from));
3373
- display.viewFrom = from;
3374
- if (display.viewTo < to)
3375
- display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));
3376
- else if (display.viewTo > to)
3377
- display.view = display.view.slice(0, findViewIndex(cm, to));
3378
- }
3379
- display.viewTo = to;
3380
- }
3381
-
3382
- // Count the number of lines in the view whose DOM representation is
3383
- // out of date (or nonexistent).
3384
- function countDirtyView(cm) {
3385
- var view = cm.display.view, dirty = 0;
3386
- for (var i = 0; i < view.length; i++) {
3387
- var lineView = view[i];
3388
- if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;
3389
- }
3390
- return dirty;
3391
- }
3392
-
3393
- // EVENT HANDLERS
3394
-
3395
- // Attach the necessary event handlers when initializing the editor
3396
- function registerEventHandlers(cm) {
3397
- var d = cm.display;
3398
- on(d.scroller, "mousedown", operation(cm, onMouseDown));
3399
- // Older IE's will not fire a second mousedown for a double click
3400
- if (ie && ie_version < 11)
3401
- on(d.scroller, "dblclick", operation(cm, function(e) {
3402
- if (signalDOMEvent(cm, e)) return;
3403
- var pos = posFromMouse(cm, e);
3404
- if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
3405
- e_preventDefault(e);
3406
- var word = cm.findWordAt(pos);
3407
- extendSelection(cm.doc, word.anchor, word.head);
3408
- }));
3409
- else
3410
- on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
3411
- // Some browsers fire contextmenu *after* opening the menu, at
3412
- // which point we can't mess with it anymore. Context menu is
3413
- // handled in onMouseDown for these browsers.
3414
- if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
3415
-
3416
- // Used to suppress mouse event handling when a touch happens
3417
- var touchFinished, prevTouch = {end: 0};
3418
- function finishTouch() {
3419
- if (d.activeTouch) {
3420
- touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);
3421
- prevTouch = d.activeTouch;
3422
- prevTouch.end = +new Date;
3423
- }
3424
- };
3425
- function isMouseLikeTouchEvent(e) {
3426
- if (e.touches.length != 1) return false;
3427
- var touch = e.touches[0];
3428
- return touch.radiusX <= 1 && touch.radiusY <= 1;
3429
- }
3430
- function farAway(touch, other) {
3431
- if (other.left == null) return true;
3432
- var dx = other.left - touch.left, dy = other.top - touch.top;
3433
- return dx * dx + dy * dy > 20 * 20;
3434
- }
3435
- on(d.scroller, "touchstart", function(e) {
3436
- if (!isMouseLikeTouchEvent(e)) {
3437
- clearTimeout(touchFinished);
3438
- var now = +new Date;
3439
- d.activeTouch = {start: now, moved: false,
3440
- prev: now - prevTouch.end <= 300 ? prevTouch : null};
3441
- if (e.touches.length == 1) {
3442
- d.activeTouch.left = e.touches[0].pageX;
3443
- d.activeTouch.top = e.touches[0].pageY;
3444
- }
3445
- }
3446
- });
3447
- on(d.scroller, "touchmove", function() {
3448
- if (d.activeTouch) d.activeTouch.moved = true;
3449
- });
3450
- on(d.scroller, "touchend", function(e) {
3451
- var touch = d.activeTouch;
3452
- if (touch && !eventInWidget(d, e) && touch.left != null &&
3453
- !touch.moved && new Date - touch.start < 300) {
3454
- var pos = cm.coordsChar(d.activeTouch, "page"), range;
3455
- if (!touch.prev || farAway(touch, touch.prev)) // Single tap
3456
- range = new Range(pos, pos);
3457
- else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
3458
- range = cm.findWordAt(pos);
3459
- else // Triple tap
3460
- range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));
3461
- cm.setSelection(range.anchor, range.head);
3462
- cm.focus();
3463
- e_preventDefault(e);
3464
- }
3465
- finishTouch();
3466
- });
3467
- on(d.scroller, "touchcancel", finishTouch);
3468
-
3469
- // Sync scrolling between fake scrollbars and real scrollable
3470
- // area, ensure viewport is updated when scrolling.
3471
- on(d.scroller, "scroll", function() {
3472
- if (d.scroller.clientHeight) {
3473
- setScrollTop(cm, d.scroller.scrollTop);
3474
- setScrollLeft(cm, d.scroller.scrollLeft, true);
3475
- signal(cm, "scroll", cm);
3476
- }
3477
- });
3478
-
3479
- // Listen to wheel events in order to try and update the viewport on time.
3480
- on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
3481
- on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
3482
-
3483
- // Prevent wrapper from ever scrolling
3484
- on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
3485
-
3486
- d.dragFunctions = {
3487
- enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
3488
- over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
3489
- start: function(e){onDragStart(cm, e);},
3490
- drop: operation(cm, onDrop),
3491
- leave: function() {clearDragCursor(cm);}
3492
- };
3493
-
3494
- var inp = d.input.getField();
3495
- on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
3496
- on(inp, "keydown", operation(cm, onKeyDown));
3497
- on(inp, "keypress", operation(cm, onKeyPress));
3498
- on(inp, "focus", bind(onFocus, cm));
3499
- on(inp, "blur", bind(onBlur, cm));
3500
- }
3501
-
3502
- function dragDropChanged(cm, value, old) {
3503
- var wasOn = old && old != CodeMirror.Init;
3504
- if (!value != !wasOn) {
3505
- var funcs = cm.display.dragFunctions;
3506
- var toggle = value ? on : off;
3507
- toggle(cm.display.scroller, "dragstart", funcs.start);
3508
- toggle(cm.display.scroller, "dragenter", funcs.enter);
3509
- toggle(cm.display.scroller, "dragover", funcs.over);
3510
- toggle(cm.display.scroller, "dragleave", funcs.leave);
3511
- toggle(cm.display.scroller, "drop", funcs.drop);
3512
- }
3513
- }
3514
-
3515
- // Called when the window resizes
3516
- function onResize(cm) {
3517
- var d = cm.display;
3518
- if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
3519
- return;
3520
- // Might be a text scaling operation, clear size caches.
3521
- d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
3522
- d.scrollbarsClipped = false;
3523
- cm.setSize();
3524
- }
3525
-
3526
- // MOUSE EVENTS
3527
-
3528
- // Return true when the given mouse event happened in a widget
3529
- function eventInWidget(display, e) {
3530
- for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
3531
- if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
3532
- (n.parentNode == display.sizer && n != display.mover))
3533
- return true;
3534
- }
3535
- }
3536
-
3537
- // Given a mouse event, find the corresponding position. If liberal
3538
- // is false, it checks whether a gutter or scrollbar was clicked,
3539
- // and returns null if it was. forRect is used by rectangular
3540
- // selections, and tries to estimate a character position even for
3541
- // coordinates beyond the right of the text.
3542
- function posFromMouse(cm, e, liberal, forRect) {
3543
- var display = cm.display;
3544
- if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null;
3545
-
3546
- var x, y, space = display.lineSpace.getBoundingClientRect();
3547
- // Fails unpredictably on IE[67] when mouse is dragged around quickly.
3548
- try { x = e.clientX - space.left; y = e.clientY - space.top; }
3549
- catch (e) { return null; }
3550
- var coords = coordsChar(cm, x, y), line;
3551
- if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
3552
- var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
3553
- coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
3554
- }
3555
- return coords;
3556
- }
3557
-
3558
- // A mouse down can be a single click, double click, triple click,
3559
- // start of selection drag, start of text drag, new cursor
3560
- // (ctrl-click), rectangle drag (alt-drag), or xwin
3561
- // middle-click-paste. Or it might be a click on something we should
3562
- // not interfere with, such as a scrollbar or widget.
3563
- function onMouseDown(e) {
3564
- var cm = this, display = cm.display;
3565
- if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return;
3566
- display.shift = e.shiftKey;
3567
-
3568
- if (eventInWidget(display, e)) {
3569
- if (!webkit) {
3570
- // Briefly turn off draggability, to allow widgets to do
3571
- // normal dragging things.
3572
- display.scroller.draggable = false;
3573
- setTimeout(function(){display.scroller.draggable = true;}, 100);
3574
- }
3575
- return;
3576
- }
3577
- if (clickInGutter(cm, e)) return;
3578
- var start = posFromMouse(cm, e);
3579
- window.focus();
3580
-
3581
- switch (e_button(e)) {
3582
- case 1:
3583
- // #3261: make sure, that we're not starting a second selection
3584
- if (cm.state.selectingText)
3585
- cm.state.selectingText(e);
3586
- else if (start)
3587
- leftButtonDown(cm, e, start);
3588
- else if (e_target(e) == display.scroller)
3589
- e_preventDefault(e);
3590
- break;
3591
- case 2:
3592
- if (webkit) cm.state.lastMiddleDown = +new Date;
3593
- if (start) extendSelection(cm.doc, start);
3594
- setTimeout(function() {display.input.focus();}, 20);
3595
- e_preventDefault(e);
3596
- break;
3597
- case 3:
3598
- if (captureRightClick) onContextMenu(cm, e);
3599
- else delayBlurEvent(cm);
3600
- break;
3601
- }
3602
- }
3603
-
3604
- var lastClick, lastDoubleClick;
3605
- function leftButtonDown(cm, e, start) {
3606
- if (ie) setTimeout(bind(ensureFocus, cm), 0);
3607
- else cm.curOp.focus = activeElt();
3608
-
3609
- var now = +new Date, type;
3610
- if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
3611
- type = "triple";
3612
- } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
3613
- type = "double";
3614
- lastDoubleClick = {time: now, pos: start};
3615
- } else {
3616
- type = "single";
3617
- lastClick = {time: now, pos: start};
3618
- }
3619
-
3620
- var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
3621
- if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
3622
- type == "single" && (contained = sel.contains(start)) > -1 &&
3623
- (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
3624
- (cmp(contained.to(), start) > 0 || start.xRel < 0))
3625
- leftButtonStartDrag(cm, e, start, modifier);
3626
- else
3627
- leftButtonSelect(cm, e, start, type, modifier);
3628
- }
3629
-
3630
- // Start a text drag. When it ends, see if any dragging actually
3631
- // happen, and treat as a click if it didn't.
3632
- function leftButtonStartDrag(cm, e, start, modifier) {
3633
- var display = cm.display, startTime = +new Date;
3634
- var dragEnd = operation(cm, function(e2) {
3635
- if (webkit) display.scroller.draggable = false;
3636
- cm.state.draggingText = false;
3637
- off(document, "mouseup", dragEnd);
3638
- off(display.scroller, "drop", dragEnd);
3639
- if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
3640
- e_preventDefault(e2);
3641
- if (!modifier && +new Date - 200 < startTime)
3642
- extendSelection(cm.doc, start);
3643
- // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
3644
- if (webkit || ie && ie_version == 9)
3645
- setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
3646
- else
3647
- display.input.focus();
3648
- }
3649
- });
3650
- // Let the drag handler handle this.
3651
- if (webkit) display.scroller.draggable = true;
3652
- cm.state.draggingText = dragEnd;
3653
- // IE's approach to draggable
3654
- if (display.scroller.dragDrop) display.scroller.dragDrop();
3655
- on(document, "mouseup", dragEnd);
3656
- on(display.scroller, "drop", dragEnd);
3657
- }
3658
-
3659
- // Normal selection, as opposed to text dragging.
3660
- function leftButtonSelect(cm, e, start, type, addNew) {
3661
- var display = cm.display, doc = cm.doc;
3662
- e_preventDefault(e);
3663
-
3664
- var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
3665
- if (addNew && !e.shiftKey) {
3666
- ourIndex = doc.sel.contains(start);
3667
- if (ourIndex > -1)
3668
- ourRange = ranges[ourIndex];
3669
- else
3670
- ourRange = new Range(start, start);
3671
- } else {
3672
- ourRange = doc.sel.primary();
3673
- ourIndex = doc.sel.primIndex;
3674
- }
3675
-
3676
- if (e.altKey) {
3677
- type = "rect";
3678
- if (!addNew) ourRange = new Range(start, start);
3679
- start = posFromMouse(cm, e, true, true);
3680
- ourIndex = -1;
3681
- } else if (type == "double") {
3682
- var word = cm.findWordAt(start);
3683
- if (cm.display.shift || doc.extend)
3684
- ourRange = extendRange(doc, ourRange, word.anchor, word.head);
3685
- else
3686
- ourRange = word;
3687
- } else if (type == "triple") {
3688
- var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
3689
- if (cm.display.shift || doc.extend)
3690
- ourRange = extendRange(doc, ourRange, line.anchor, line.head);
3691
- else
3692
- ourRange = line;
3693
- } else {
3694
- ourRange = extendRange(doc, ourRange, start);
3695
- }
3696
-
3697
- if (!addNew) {
3698
- ourIndex = 0;
3699
- setSelection(doc, new Selection([ourRange], 0), sel_mouse);
3700
- startSel = doc.sel;
3701
- } else if (ourIndex == -1) {
3702
- ourIndex = ranges.length;
3703
- setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
3704
- {scroll: false, origin: "*mouse"});
3705
- } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
3706
- setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
3707
- {scroll: false, origin: "*mouse"});
3708
- startSel = doc.sel;
3709
- } else {
3710
- replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
3711
- }
3712
-
3713
- var lastPos = start;
3714
- function extendTo(pos) {
3715
- if (cmp(lastPos, pos) == 0) return;
3716
- lastPos = pos;
3717
-
3718
- if (type == "rect") {
3719
- var ranges = [], tabSize = cm.options.tabSize;
3720
- var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
3721
- var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
3722
- var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
3723
- for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
3724
- line <= end; line++) {
3725
- var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
3726
- if (left == right)
3727
- ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
3728
- else if (text.length > leftPos)
3729
- ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
3730
- }
3731
- if (!ranges.length) ranges.push(new Range(start, start));
3732
- setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
3733
- {origin: "*mouse", scroll: false});
3734
- cm.scrollIntoView(pos);
3735
- } else {
3736
- var oldRange = ourRange;
3737
- var anchor = oldRange.anchor, head = pos;
3738
- if (type != "single") {
3739
- if (type == "double")
3740
- var range = cm.findWordAt(pos);
3741
- else
3742
- var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
3743
- if (cmp(range.anchor, anchor) > 0) {
3744
- head = range.head;
3745
- anchor = minPos(oldRange.from(), range.anchor);
3746
- } else {
3747
- head = range.anchor;
3748
- anchor = maxPos(oldRange.to(), range.head);
3749
- }
3750
- }
3751
- var ranges = startSel.ranges.slice(0);
3752
- ranges[ourIndex] = new Range(clipPos(doc, anchor), head);
3753
- setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);
3754
- }
3755
- }
3756
-
3757
- var editorSize = display.wrapper.getBoundingClientRect();
3758
- // Used to ensure timeout re-tries don't fire when another extend
3759
- // happened in the meantime (clearTimeout isn't reliable -- at
3760
- // least on Chrome, the timeouts still happen even when cleared,
3761
- // if the clear happens after their scheduled firing time).
3762
- var counter = 0;
3763
-
3764
- function extend(e) {
3765
- var curCount = ++counter;
3766
- var cur = posFromMouse(cm, e, true, type == "rect");
3767
- if (!cur) return;
3768
- if (cmp(cur, lastPos) != 0) {
3769
- cm.curOp.focus = activeElt();
3770
- extendTo(cur);
3771
- var visible = visibleLines(display, doc);
3772
- if (cur.line >= visible.to || cur.line < visible.from)
3773
- setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
3774
- } else {
3775
- var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
3776
- if (outside) setTimeout(operation(cm, function() {
3777
- if (counter != curCount) return;
3778
- display.scroller.scrollTop += outside;
3779
- extend(e);
3780
- }), 50);
3781
- }
3782
- }
3783
-
3784
- function done(e) {
3785
- cm.state.selectingText = false;
3786
- counter = Infinity;
3787
- e_preventDefault(e);
3788
- display.input.focus();
3789
- off(document, "mousemove", move);
3790
- off(document, "mouseup", up);
3791
- doc.history.lastSelOrigin = null;
3792
- }
3793
-
3794
- var move = operation(cm, function(e) {
3795
- if (!e_button(e)) done(e);
3796
- else extend(e);
3797
- });
3798
- var up = operation(cm, done);
3799
- cm.state.selectingText = up;
3800
- on(document, "mousemove", move);
3801
- on(document, "mouseup", up);
3802
- }
3803
-
3804
- // Determines whether an event happened in the gutter, and fires the
3805
- // handlers for the corresponding event.
3806
- function gutterEvent(cm, e, type, prevent) {
3807
- try { var mX = e.clientX, mY = e.clientY; }
3808
- catch(e) { return false; }
3809
- if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
3810
- if (prevent) e_preventDefault(e);
3811
-
3812
- var display = cm.display;
3813
- var lineBox = display.lineDiv.getBoundingClientRect();
3814
-
3815
- if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
3816
- mY -= lineBox.top - display.viewOffset;
3817
-
3818
- for (var i = 0; i < cm.options.gutters.length; ++i) {
3819
- var g = display.gutters.childNodes[i];
3820
- if (g && g.getBoundingClientRect().right >= mX) {
3821
- var line = lineAtHeight(cm.doc, mY);
3822
- var gutter = cm.options.gutters[i];
3823
- signal(cm, type, cm, line, gutter, e);
3824
- return e_defaultPrevented(e);
3825
- }
3826
- }
3827
- }
3828
-
3829
- function clickInGutter(cm, e) {
3830
- return gutterEvent(cm, e, "gutterClick", true);
3831
- }
3832
-
3833
- // Kludge to work around strange IE behavior where it'll sometimes
3834
- // re-fire a series of drag-related events right after the drop (#1551)
3835
- var lastDrop = 0;
3836
-
3837
- function onDrop(e) {
3838
- var cm = this;
3839
- clearDragCursor(cm);
3840
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
3841
- return;
3842
- e_preventDefault(e);
3843
- if (ie) lastDrop = +new Date;
3844
- var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
3845
- if (!pos || cm.isReadOnly()) return;
3846
- // Might be a file drop, in which case we simply extract the text
3847
- // and insert it.
3848
- if (files && files.length && window.FileReader && window.File) {
3849
- var n = files.length, text = Array(n), read = 0;
3850
- var loadFile = function(file, i) {
3851
- if (cm.options.allowDropFileTypes &&
3852
- indexOf(cm.options.allowDropFileTypes, file.type) == -1)
3853
- return;
3854
-
3855
- var reader = new FileReader;
3856
- reader.onload = operation(cm, function() {
3857
- var content = reader.result;
3858
- if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = "";
3859
- text[i] = content;
3860
- if (++read == n) {
3861
- pos = clipPos(cm.doc, pos);
3862
- var change = {from: pos, to: pos,
3863
- text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
3864
- origin: "paste"};
3865
- makeChange(cm.doc, change);
3866
- setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
3867
- }
3868
- });
3869
- reader.readAsText(file);
3870
- };
3871
- for (var i = 0; i < n; ++i) loadFile(files[i], i);
3872
- } else { // Normal drop
3873
- // Don't do a replace if the drop happened inside of the selected text.
3874
- if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
3875
- cm.state.draggingText(e);
3876
- // Ensure the editor is re-focused
3877
- setTimeout(function() {cm.display.input.focus();}, 20);
3878
- return;
3879
- }
3880
  try {
3881
- var text = e.dataTransfer.getData("Text");
3882
- if (text) {
3883
- if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))
3884
- var selected = cm.listSelections();
3885
- setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
3886
- if (selected) for (var i = 0; i < selected.length; ++i)
3887
- replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
3888
- cm.replaceSelection(text, "around", "paste");
3889
- cm.display.input.focus();
3890
- }
3891
- }
3892
- catch(e){}
3893
- }
3894
- }
3895
-
3896
- function onDragStart(cm, e) {
3897
- if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
3898
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
3899
-
3900
- e.dataTransfer.setData("Text", cm.getSelection());
3901
-
3902
- // Use dummy image instead of default browsers image.
3903
- // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
3904
- if (e.dataTransfer.setDragImage && !safari) {
3905
- var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
3906
- img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
3907
- if (presto) {
3908
- img.width = img.height = 1;
3909
- cm.display.wrapper.appendChild(img);
3910
- // Force a relayout, or Opera won't use our image for some obscure reason
3911
- img._top = img.offsetTop;
3912
- }
3913
- e.dataTransfer.setDragImage(img, 0, 0);
3914
- if (presto) img.parentNode.removeChild(img);
3915
- }
3916
- }
3917
-
3918
- function onDragOver(cm, e) {
3919
- var pos = posFromMouse(cm, e);
3920
- if (!pos) return;
3921
- var frag = document.createDocumentFragment();
3922
- drawSelectionCursor(cm, pos, frag);
3923
- if (!cm.display.dragCursor) {
3924
- cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
3925
- cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
3926
- }
3927
- removeChildrenAndAdd(cm.display.dragCursor, frag);
3928
- }
3929
-
3930
- function clearDragCursor(cm) {
3931
- if (cm.display.dragCursor) {
3932
- cm.display.lineSpace.removeChild(cm.display.dragCursor);
3933
- cm.display.dragCursor = null;
3934
- }
3935
- }
3936
-
3937
- // SCROLL EVENTS
3938
-
3939
- // Sync the scrollable area and scrollbars, ensure the viewport
3940
- // covers the visible area.
3941
- function setScrollTop(cm, val) {
3942
- if (Math.abs(cm.doc.scrollTop - val) < 2) return;
3943
- cm.doc.scrollTop = val;
3944
- if (!gecko) updateDisplaySimple(cm, {top: val});
3945
- if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
3946
- cm.display.scrollbars.setScrollTop(val);
3947
- if (gecko) updateDisplaySimple(cm);
3948
- startWorker(cm, 100);
3949
- }
3950
- // Sync scroller and scrollbar, ensure the gutter elements are
3951
- // aligned.
3952
- function setScrollLeft(cm, val, isScroller) {
3953
- if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
3954
- val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
3955
- cm.doc.scrollLeft = val;
3956
- alignHorizontally(cm);
3957
- if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
3958
- cm.display.scrollbars.setScrollLeft(val);
3959
- }
3960
-
3961
- // Since the delta values reported on mouse wheel events are
3962
- // unstandardized between browsers and even browser versions, and
3963
- // generally horribly unpredictable, this code starts by measuring
3964
- // the scroll effect that the first few mouse wheel events have,
3965
- // and, from that, detects the way it can convert deltas to pixel
3966
- // offsets afterwards.
3967
- //
3968
- // The reason we want to know the amount a wheel event will scroll
3969
- // is that it gives us a chance to update the display before the
3970
- // actual scrolling happens, reducing flickering.
3971
-
3972
- var wheelSamples = 0, wheelPixelsPerUnit = null;
3973
- // Fill in a browser-detected starting value on browsers where we
3974
- // know one. These don't have to be accurate -- the result of them
3975
- // being wrong would just be a slight flicker on the first wheel
3976
- // scroll (if it is large enough).
3977
- if (ie) wheelPixelsPerUnit = -.53;
3978
- else if (gecko) wheelPixelsPerUnit = 15;
3979
- else if (chrome) wheelPixelsPerUnit = -.7;
3980
- else if (safari) wheelPixelsPerUnit = -1/3;
3981
-
3982
- var wheelEventDelta = function(e) {
3983
- var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
3984
- if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
3985
- if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
3986
- else if (dy == null) dy = e.wheelDelta;
3987
- return {x: dx, y: dy};
3988
- };
3989
- CodeMirror.wheelEventPixels = function(e) {
3990
- var delta = wheelEventDelta(e);
3991
- delta.x *= wheelPixelsPerUnit;
3992
- delta.y *= wheelPixelsPerUnit;
3993
- return delta;
3994
- };
3995
-
3996
- function onScrollWheel(cm, e) {
3997
- var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
3998
-
3999
- var display = cm.display, scroll = display.scroller;
4000
- // Quit if there's nothing to scroll here
4001
- var canScrollX = scroll.scrollWidth > scroll.clientWidth;
4002
- var canScrollY = scroll.scrollHeight > scroll.clientHeight;
4003
- if (!(dx && canScrollX || dy && canScrollY)) return;
4004
-
4005
- // Webkit browsers on OS X abort momentum scrolls when the target
4006
- // of the scroll event is removed from the scrollable element.
4007
- // This hack (see related code in patchDisplay) makes sure the
4008
- // element is kept around.
4009
- if (dy && mac && webkit) {
4010
- outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
4011
- for (var i = 0; i < view.length; i++) {
4012
- if (view[i].node == cur) {
4013
- cm.display.currentWheelTarget = cur;
4014
- break outer;
4015
- }
4016
- }
4017
- }
4018
- }
4019
-
4020
- // On some browsers, horizontal scrolling will cause redraws to
4021
- // happen before the gutter has been realigned, causing it to
4022
- // wriggle around in a most unseemly way. When we have an
4023
- // estimated pixels/delta value, we just handle horizontal
4024
- // scrolling entirely here. It'll be slightly off from native, but
4025
- // better than glitching out.
4026
- if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
4027
- if (dy && canScrollY)
4028
- setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
4029
- setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
4030
- // Only prevent default scrolling if vertical scrolling is
4031
- // actually possible. Otherwise, it causes vertical scroll
4032
- // jitter on OSX trackpads when deltaX is small and deltaY
4033
- // is large (issue #3579)
4034
- if (!dy || (dy && canScrollY))
4035
- e_preventDefault(e);
4036
- display.wheelStartX = null; // Abort measurement, if in progress
4037
- return;
4038
- }
4039
-
4040
- // 'Project' the visible viewport to cover the area that is being
4041
- // scrolled into view (if we know enough to estimate it).
4042
- if (dy && wheelPixelsPerUnit != null) {
4043
- var pixels = dy * wheelPixelsPerUnit;
4044
- var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
4045
- if (pixels < 0) top = Math.max(0, top + pixels - 50);
4046
- else bot = Math.min(cm.doc.height, bot + pixels + 50);
4047
- updateDisplaySimple(cm, {top: top, bottom: bot});
4048
- }
4049
-
4050
- if (wheelSamples < 20) {
4051
- if (display.wheelStartX == null) {
4052
- display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
4053
- display.wheelDX = dx; display.wheelDY = dy;
4054
- setTimeout(function() {
4055
- if (display.wheelStartX == null) return;
4056
- var movedX = scroll.scrollLeft - display.wheelStartX;
4057
- var movedY = scroll.scrollTop - display.wheelStartY;
4058
- var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
4059
- (movedX && display.wheelDX && movedX / display.wheelDX);
4060
- display.wheelStartX = display.wheelStartY = null;
4061
- if (!sample) return;
4062
- wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
4063
- ++wheelSamples;
4064
- }, 200);
4065
- } else {
4066
- display.wheelDX += dx; display.wheelDY += dy;
4067
- }
4068
- }
4069
- }
4070
-
4071
- // KEY EVENTS
4072
-
4073
- // Run a handler that was bound to a key.
4074
- function doHandleBinding(cm, bound, dropShift) {
4075
- if (typeof bound == "string") {
4076
- bound = commands[bound];
4077
- if (!bound) return false;
4078
- }
4079
- // Ensure previous input has been read, so that the handler sees a
4080
- // consistent view of the document
4081
- cm.display.input.ensurePolled();
4082
- var prevShift = cm.display.shift, done = false;
4083
- try {
4084
- if (cm.isReadOnly()) cm.state.suppressEdits = true;
4085
- if (dropShift) cm.display.shift = false;
4086
- done = bound(cm) != Pass;
4087
- } finally {
4088
- cm.display.shift = prevShift;
4089
- cm.state.suppressEdits = false;
4090
- }
4091
- return done;
4092
- }
4093
-
4094
- function lookupKeyForEditor(cm, name, handle) {
4095
- for (var i = 0; i < cm.state.keyMaps.length; i++) {
4096
- var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
4097
- if (result) return result;
4098
- }
4099
- return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
4100
- || lookupKey(name, cm.options.keyMap, handle, cm);
4101
- }
4102
-
4103
- var stopSeq = new Delayed;
4104
- function dispatchKey(cm, name, e, handle) {
4105
- var seq = cm.state.keySeq;
4106
- if (seq) {
4107
- if (isModifierKey(name)) return "handled";
4108
- stopSeq.set(50, function() {
4109
- if (cm.state.keySeq == seq) {
4110
- cm.state.keySeq = null;
4111
- cm.display.input.reset();
4112
- }
4113
- });
4114
- name = seq + " " + name;
4115
- }
4116
- var result = lookupKeyForEditor(cm, name, handle);
4117
-
4118
- if (result == "multi")
4119
- cm.state.keySeq = name;
4120
- if (result == "handled")
4121
- signalLater(cm, "keyHandled", cm, name, e);
4122
-
4123
- if (result == "handled" || result == "multi") {
4124
- e_preventDefault(e);
4125
- restartBlink(cm);
4126
- }
4127
-
4128
- if (seq && !result && /\'$/.test(name)) {
4129
- e_preventDefault(e);
4130
- return true;
4131
- }
4132
- return !!result;
4133
- }
4134
-
4135
- // Handle a key from the keydown event.
4136
- function handleKeyBinding(cm, e) {
4137
- var name = keyName(e, true);
4138
- if (!name) return false;
4139
-
4140
- if (e.shiftKey && !cm.state.keySeq) {
4141
- // First try to resolve full name (including 'Shift-'). Failing
4142
- // that, see if there is a cursor-motion command (starting with
4143
- // 'go') bound to the keyname without 'Shift-'.
4144
- return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
4145
- || dispatchKey(cm, name, e, function(b) {
4146
- if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
4147
- return doHandleBinding(cm, b);
4148
- });
4149
- } else {
4150
- return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });
4151
- }
4152
- }
4153
-
4154
- // Handle a key from the keypress event
4155
- function handleCharBinding(cm, e, ch) {
4156
- return dispatchKey(cm, "'" + ch + "'", e,
4157
- function(b) { return doHandleBinding(cm, b, true); });
4158
- }
4159
-
4160
- var lastStoppedKey = null;
4161
- function onKeyDown(e) {
4162
- var cm = this;
4163
- cm.curOp.focus = activeElt();
4164
- if (signalDOMEvent(cm, e)) return;
4165
- // IE does strange things with escape.
4166
- if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
4167
- var code = e.keyCode;
4168
- cm.display.shift = code == 16 || e.shiftKey;
4169
- var handled = handleKeyBinding(cm, e);
4170
- if (presto) {
4171
- lastStoppedKey = handled ? code : null;
4172
- // Opera has no cut event... we try to at least catch the key combo
4173
- if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
4174
- cm.replaceSelection("", null, "cut");
4175
- }
4176
-
4177
- // Turn mouse into crosshair when Alt is held on Mac.
4178
- if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
4179
- showCrossHair(cm);
4180
- }
4181
-
4182
- function showCrossHair(cm) {
4183
- var lineDiv = cm.display.lineDiv;
4184
- addClass(lineDiv, "CodeMirror-crosshair");
4185
-
4186
- function up(e) {
4187
- if (e.keyCode == 18 || !e.altKey) {
4188
- rmClass(lineDiv, "CodeMirror-crosshair");
4189
- off(document, "keyup", up);
4190
- off(document, "mouseover", up);
4191
- }
4192
- }
4193
- on(document, "keyup", up);
4194
- on(document, "mouseover", up);
4195
- }
4196
-
4197
- function onKeyUp(e) {
4198
- if (e.keyCode == 16) this.doc.sel.shift = false;
4199
- signalDOMEvent(this, e);
4200
- }
4201
-
4202
- function onKeyPress(e) {
4203
- var cm = this;
4204
- if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
4205
- var keyCode = e.keyCode, charCode = e.charCode;
4206
- if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
4207
- if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;
4208
- var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
4209
- if (handleCharBinding(cm, e, ch)) return;
4210
- cm.display.input.onKeyPress(e);
4211
- }
4212
-
4213
- // FOCUS/BLUR EVENTS
4214
-
4215
- function delayBlurEvent(cm) {
4216
- cm.state.delayingBlurEvent = true;
4217
- setTimeout(function() {
4218
- if (cm.state.delayingBlurEvent) {
4219
- cm.state.delayingBlurEvent = false;
4220
- onBlur(cm);
4221
- }
4222
- }, 100);
4223
- }
4224
-
4225
- function onFocus(cm) {
4226
- if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;
4227
-
4228
- if (cm.options.readOnly == "nocursor") return;
4229
- if (!cm.state.focused) {
4230
- signal(cm, "focus", cm);
4231
- cm.state.focused = true;
4232
- addClass(cm.display.wrapper, "CodeMirror-focused");
4233
- // This test prevents this from firing when a context
4234
- // menu is closed (since the input reset would kill the
4235
- // select-all detection hack)
4236
- if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
4237
- cm.display.input.reset();
4238
- if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730
4239
- }
4240
- cm.display.input.receivedFocus();
4241
- }
4242
- restartBlink(cm);
4243
- }
4244
- function onBlur(cm) {
4245
- if (cm.state.delayingBlurEvent) return;
4246
-
4247
- if (cm.state.focused) {
4248
- signal(cm, "blur", cm);
4249
- cm.state.focused = false;
4250
- rmClass(cm.display.wrapper, "CodeMirror-focused");
4251
- }
4252
- clearInterval(cm.display.blinker);
4253
- setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
4254
- }
4255
-
4256
- // CONTEXT MENU HANDLING
4257
-
4258
- // To make the context menu work, we need to briefly unhide the
4259
- // textarea (making it as unobtrusive as possible) to let the
4260
- // right-click take effect on it.
4261
- function onContextMenu(cm, e) {
4262
- if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
4263
- if (signalDOMEvent(cm, e, "contextmenu")) return;
4264
- cm.display.input.onContextMenu(e);
4265
- }
4266
-
4267
- function contextMenuInGutter(cm, e) {
4268
- if (!hasHandler(cm, "gutterContextMenu")) return false;
4269
- return gutterEvent(cm, e, "gutterContextMenu", false);
4270
- }
4271
-
4272
- // UPDATING
4273
-
4274
- // Compute the position of the end of a change (its 'to' property
4275
- // refers to the pre-change end).
4276
- var changeEnd = CodeMirror.changeEnd = function(change) {
4277
- if (!change.text) return change.to;
4278
- return Pos(change.from.line + change.text.length - 1,
4279
- lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
4280
- };
4281
-
4282
- // Adjust a position to refer to the post-change position of the
4283
- // same text, or the end of the change if the change covers it.
4284
- function adjustForChange(pos, change) {
4285
- if (cmp(pos, change.from) < 0) return pos;
4286
- if (cmp(pos, change.to) <= 0) return changeEnd(change);
4287
-
4288
- var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
4289
- if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;
4290
- return Pos(line, ch);
4291
- }
4292
-
4293
- function computeSelAfterChange(doc, change) {
4294
- var out = [];
4295
- for (var i = 0; i < doc.sel.ranges.length; i++) {
4296
- var range = doc.sel.ranges[i];
4297
- out.push(new Range(adjustForChange(range.anchor, change),
4298
- adjustForChange(range.head, change)));
4299
- }
4300
- return normalizeSelection(out, doc.sel.primIndex);
4301
- }
4302
-
4303
- function offsetPos(pos, old, nw) {
4304
- if (pos.line == old.line)
4305
- return Pos(nw.line, pos.ch - old.ch + nw.ch);
4306
- else
4307
- return Pos(nw.line + (pos.line - old.line), pos.ch);
4308
- }
4309
-
4310
- // Used by replaceSelections to allow moving the selection to the
4311
- // start or around the replaced test. Hint may be "start" or "around".
4312
- function computeReplacedSel(doc, changes, hint) {
4313
- var out = [];
4314
- var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
4315
- for (var i = 0; i < changes.length; i++) {
4316
- var change = changes[i];
4317
- var from = offsetPos(change.from, oldPrev, newPrev);
4318
- var to = offsetPos(changeEnd(change), oldPrev, newPrev);
4319
- oldPrev = change.to;
4320
- newPrev = to;
4321
- if (hint == "around") {
4322
- var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
4323
- out[i] = new Range(inv ? to : from, inv ? from : to);
4324
- } else {
4325
- out[i] = new Range(from, from);
4326
- }
4327
- }
4328
- return new Selection(out, doc.sel.primIndex);
4329
- }
4330
-
4331
- // Allow "beforeChange" event handlers to influence a change
4332
- function filterChange(doc, change, update) {
4333
- var obj = {
4334
- canceled: false,
4335
- from: change.from,
4336
- to: change.to,
4337
- text: change.text,
4338
- origin: change.origin,
4339
- cancel: function() { this.canceled = true; }
4340
- };
4341
- if (update) obj.update = function(from, to, text, origin) {
4342
- if (from) this.from = clipPos(doc, from);
4343
- if (to) this.to = clipPos(doc, to);
4344
- if (text) this.text = text;
4345
- if (origin !== undefined) this.origin = origin;
4346
- };
4347
- signal(doc, "beforeChange", doc, obj);
4348
- if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
4349
-
4350
- if (obj.canceled) return null;
4351
- return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
4352
- }
4353
-
4354
- // Apply a change to a document, and add it to the document's
4355
- // history, and propagating it to all linked documents.
4356
- function makeChange(doc, change, ignoreReadOnly) {
4357
- if (doc.cm) {
4358
- if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);
4359
- if (doc.cm.state.suppressEdits) return;
4360
- }
4361
-
4362
- if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
4363
- change = filterChange(doc, change, true);
4364
- if (!change) return;
4365
- }
4366
-
4367
- // Possibly split or suppress the update based on the presence
4368
- // of read-only spans in its range.
4369
- var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
4370
- if (split) {
4371
- for (var i = split.length - 1; i >= 0; --i)
4372
- makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});
4373
- } else {
4374
- makeChangeInner(doc, change);
4375
- }
4376
- }
4377
-
4378
- function makeChangeInner(doc, change) {
4379
- if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;
4380
- var selAfter = computeSelAfterChange(doc, change);
4381
- addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
4382
-
4383
- makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
4384
- var rebased = [];
4385
-
4386
- linkedDocs(doc, function(doc, sharedHist) {
4387
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
4388
- rebaseHist(doc.history, change);
4389
- rebased.push(doc.history);
4390
- }
4391
- makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
4392
- });
4393
- }
4394
-
4395
- // Revert a change stored in a document's history.
4396
- function makeChangeFromHistory(doc, type, allowSelectionOnly) {
4397
- if (doc.cm && doc.cm.state.suppressEdits) return;
4398
-
4399
- var hist = doc.history, event, selAfter = doc.sel;
4400
- var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
4401
-
4402
- // Verify that there is a useable event (so that ctrl-z won't
4403
- // needlessly clear selection events)
4404
- for (var i = 0; i < source.length; i++) {
4405
- event = source[i];
4406
- if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
4407
- break;
4408
- }
4409
- if (i == source.length) return;
4410
- hist.lastOrigin = hist.lastSelOrigin = null;
4411
-
4412
- for (;;) {
4413
- event = source.pop();
4414
- if (event.ranges) {
4415
- pushSelectionToHistory(event, dest);
4416
- if (allowSelectionOnly && !event.equals(doc.sel)) {
4417
- setSelection(doc, event, {clearRedo: false});
4418
- return;
4419
- }
4420
- selAfter = event;
4421
- }
4422
- else break;
4423
- }
4424
-
4425
- // Build up a reverse change object to add to the opposite history
4426
- // stack (redo when undoing, and vice versa).
4427
- var antiChanges = [];
4428
- pushSelectionToHistory(selAfter, dest);
4429
- dest.push({changes: antiChanges, generation: hist.generation});
4430
- hist.generation = event.generation || ++hist.maxGeneration;
4431
-
4432
- var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
4433
-
4434
- for (var i = event.changes.length - 1; i >= 0; --i) {
4435
- var change = event.changes[i];
4436
- change.origin = type;
4437
- if (filter && !filterChange(doc, change, false)) {
4438
- source.length = 0;
4439
- return;
4440
- }
4441
-
4442
- antiChanges.push(historyChangeFromChange(doc, change));
4443
-
4444
- var after = i ? computeSelAfterChange(doc, change) : lst(source);
4445
- makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
4446
- if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});
4447
- var rebased = [];
4448
-
4449
- // Propagate to the linked documents
4450
- linkedDocs(doc, function(doc, sharedHist) {
4451
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
4452
- rebaseHist(doc.history, change);
4453
- rebased.push(doc.history);
4454
- }
4455
- makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
4456
- });
4457
- }
4458
- }
4459
-
4460
- // Sub-views need their line numbers shifted when text is added
4461
- // above or below them in the parent document.
4462
- function shiftDoc(doc, distance) {
4463
- if (distance == 0) return;
4464
- doc.first += distance;
4465
- doc.sel = new Selection(map(doc.sel.ranges, function(range) {
4466
- return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
4467
- Pos(range.head.line + distance, range.head.ch));
4468
- }), doc.sel.primIndex);
4469
- if (doc.cm) {
4470
- regChange(doc.cm, doc.first, doc.first - distance, distance);
4471
- for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
4472
- regLineChange(doc.cm, l, "gutter");
4473
- }
4474
- }
4475
-
4476
- // More lower-level change function, handling only a single document
4477
- // (not linked ones).
4478
- function makeChangeSingleDoc(doc, change, selAfter, spans) {
4479
- if (doc.cm && !doc.cm.curOp)
4480
- return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
4481
-
4482
- if (change.to.line < doc.first) {
4483
- shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
4484
- return;
4485
- }
4486
- if (change.from.line > doc.lastLine()) return;
4487
-
4488
- // Clip the change to the size of this doc
4489
- if (change.from.line < doc.first) {
4490
- var shift = change.text.length - 1 - (doc.first - change.from.line);
4491
- shiftDoc(doc, shift);
4492
- change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
4493
- text: [lst(change.text)], origin: change.origin};
4494
- }
4495
- var last = doc.lastLine();
4496
- if (change.to.line > last) {
4497
- change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
4498
- text: [change.text[0]], origin: change.origin};
4499
- }
4500
-
4501
- change.removed = getBetween(doc, change.from, change.to);
4502
-
4503
- if (!selAfter) selAfter = computeSelAfterChange(doc, change);
4504
- if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
4505
- else updateDoc(doc, change, spans);
4506
- setSelectionNoUndo(doc, selAfter, sel_dontScroll);
4507
- }
4508
-
4509
- // Handle the interaction of a change to a document with the editor
4510
- // that this document is part of.
4511
- function makeChangeSingleDocInEditor(cm, change, spans) {
4512
- var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
4513
-
4514
- var recomputeMaxLength = false, checkWidthStart = from.line;
4515
- if (!cm.options.lineWrapping) {
4516
- checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
4517
- doc.iter(checkWidthStart, to.line + 1, function(line) {
4518
- if (line == display.maxLine) {
4519
- recomputeMaxLength = true;
4520
- return true;
4521
- }
4522
- });
4523
- }
4524
-
4525
- if (doc.sel.contains(change.from, change.to) > -1)
4526
- signalCursorActivity(cm);
4527
-
4528
- updateDoc(doc, change, spans, estimateHeight(cm));
4529
-
4530
- if (!cm.options.lineWrapping) {
4531
- doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
4532
- var len = lineLength(line);
4533
- if (len > display.maxLineLength) {
4534
- display.maxLine = line;
4535
- display.maxLineLength = len;
4536
- display.maxLineChanged = true;
4537
- recomputeMaxLength = false;
4538
- }
4539
- });
4540
- if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
4541
- }
4542
-
4543
- // Adjust frontier, schedule worker
4544
- doc.frontier = Math.min(doc.frontier, from.line);
4545
- startWorker(cm, 400);
4546
-
4547
- var lendiff = change.text.length - (to.line - from.line) - 1;
4548
- // Remember that these lines changed, for updating the display
4549
- if (change.full)
4550
- regChange(cm);
4551
- else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
4552
- regLineChange(cm, from.line, "text");
4553
- else
4554
- regChange(cm, from.line, to.line + 1, lendiff);
4555
-
4556
- var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
4557
- if (changeHandler || changesHandler) {
4558
- var obj = {
4559
- from: from, to: to,
4560
- text: change.text,
4561
- removed: change.removed,
4562
- origin: change.origin
4563
- };
4564
- if (changeHandler) signalLater(cm, "change", cm, obj);
4565
- if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
4566
- }
4567
- cm.display.selForContextMenu = null;
4568
- }
4569
-
4570
- function replaceRange(doc, code, from, to, origin) {
4571
- if (!to) to = from;
4572
- if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
4573
- if (typeof code == "string") code = doc.splitLines(code);
4574
- makeChange(doc, {from: from, to: to, text: code, origin: origin});
4575
- }
4576
-
4577
- // SCROLLING THINGS INTO VIEW
4578
-
4579
- // If an editor sits on the top or bottom of the window, partially
4580
- // scrolled out of view, this ensures that the cursor is visible.
4581
- function maybeScrollWindow(cm, coords) {
4582
- if (signalDOMEvent(cm, "scrollCursorIntoView")) return;
4583
-
4584
- var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
4585
- if (coords.top + box.top < 0) doScroll = true;
4586
- else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
4587
- if (doScroll != null && !phantom) {
4588
- var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
4589
- (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +
4590
- (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +
4591
- coords.left + "px; width: 2px;");
4592
- cm.display.lineSpace.appendChild(scrollNode);
4593
- scrollNode.scrollIntoView(doScroll);
4594
- cm.display.lineSpace.removeChild(scrollNode);
4595
- }
4596
- }
4597
-
4598
- // Scroll a given position into view (immediately), verifying that
4599
- // it actually became visible (as line heights are accurately
4600
- // measured, the position of something may 'drift' during drawing).
4601
- function scrollPosIntoView(cm, pos, end, margin) {
4602
- if (margin == null) margin = 0;
4603
- for (var limit = 0; limit < 5; limit++) {
4604
- var changed = false, coords = cursorCoords(cm, pos);
4605
- var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
4606
- var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
4607
- Math.min(coords.top, endCoords.top) - margin,
4608
- Math.max(coords.left, endCoords.left),
4609
- Math.max(coords.bottom, endCoords.bottom) + margin);
4610
- var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
4611
- if (scrollPos.scrollTop != null) {
4612
- setScrollTop(cm, scrollPos.scrollTop);
4613
- if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
4614
- }
4615
- if (scrollPos.scrollLeft != null) {
4616
- setScrollLeft(cm, scrollPos.scrollLeft);
4617
- if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
4618
- }
4619
- if (!changed) break;
4620
- }
4621
- return coords;
4622
- }
4623
-
4624
- // Scroll a given set of coordinates into view (immediately).
4625
- function scrollIntoView(cm, x1, y1, x2, y2) {
4626
- var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
4627
- if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
4628
- if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
4629
- }
4630
-
4631
- // Calculate a new scroll position needed to scroll the given
4632
- // rectangle into view. Returns an object with scrollTop and
4633
- // scrollLeft properties. When these are undefined, the
4634
- // vertical/horizontal position does not need to be adjusted.
4635
- function calculateScrollPos(cm, x1, y1, x2, y2) {
4636
- var display = cm.display, snapMargin = textHeight(cm.display);
4637
- if (y1 < 0) y1 = 0;
4638
- var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
4639
- var screen = displayHeight(cm), result = {};
4640
- if (y2 - y1 > screen) y2 = y1 + screen;
4641
- var docBottom = cm.doc.height + paddingVert(display);
4642
- var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
4643
- if (y1 < screentop) {
4644
- result.scrollTop = atTop ? 0 : y1;
4645
- } else if (y2 > screentop + screen) {
4646
- var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
4647
- if (newTop != screentop) result.scrollTop = newTop;
4648
- }
4649
-
4650
- var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
4651
- var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
4652
- var tooWide = x2 - x1 > screenw;
4653
- if (tooWide) x2 = x1 + screenw;
4654
- if (x1 < 10)
4655
- result.scrollLeft = 0;
4656
- else if (x1 < screenleft)
4657
- result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));
4658
- else if (x2 > screenw + screenleft - 3)
4659
- result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;
4660
- return result;
4661
- }
4662
-
4663
- // Store a relative adjustment to the scroll position in the current
4664
- // operation (to be applied when the operation finishes).
4665
- function addToScrollPos(cm, left, top) {
4666
- if (left != null || top != null) resolveScrollToPos(cm);
4667
- if (left != null)
4668
- cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;
4669
- if (top != null)
4670
- cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
4671
- }
4672
-
4673
- // Make sure that at the end of the operation the current cursor is
4674
- // shown.
4675
- function ensureCursorVisible(cm) {
4676
- resolveScrollToPos(cm);
4677
- var cur = cm.getCursor(), from = cur, to = cur;
4678
- if (!cm.options.lineWrapping) {
4679
- from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
4680
- to = Pos(cur.line, cur.ch + 1);
4681
- }
4682
- cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};
4683
- }
4684
-
4685
- // When an operation has its scrollToPos property set, and another
4686
- // scroll action is applied before the end of the operation, this
4687
- // 'simulates' scrolling that position into view in a cheap way, so
4688
- // that the effect of intermediate scroll commands is not ignored.
4689
- function resolveScrollToPos(cm) {
4690
- var range = cm.curOp.scrollToPos;
4691
- if (range) {
4692
- cm.curOp.scrollToPos = null;
4693
- var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
4694
- var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
4695
- Math.min(from.top, to.top) - range.margin,
4696
- Math.max(from.right, to.right),
4697
- Math.max(from.bottom, to.bottom) + range.margin);
4698
- cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
4699
- }
4700
- }
4701
-
4702
- // API UTILITIES
4703
-
4704
- // Indent the given line. The how parameter can be "smart",
4705
- // "add"/null, "subtract", or "prev". When aggressive is false
4706
- // (typically set to true for forced single-line indents), empty
4707
- // lines are not indented, and places where the mode returns Pass
4708
- // are left alone.
4709
- function indentLine(cm, n, how, aggressive) {
4710
- var doc = cm.doc, state;
4711
- if (how == null) how = "add";
4712
- if (how == "smart") {
4713
- // Fall back to "prev" when the mode doesn't have an indentation
4714
- // method.
4715
- if (!doc.mode.indent) how = "prev";
4716
- else state = getStateBefore(cm, n);
4717
- }
4718
-
4719
- var tabSize = cm.options.tabSize;
4720
- var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
4721
- if (line.stateAfter) line.stateAfter = null;
4722
- var curSpaceString = line.text.match(/^\s*/)[0], indentation;
4723
- if (!aggressive && !/\S/.test(line.text)) {
4724
- indentation = 0;
4725
- how = "not";
4726
- } else if (how == "smart") {
4727
- indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
4728
- if (indentation == Pass || indentation > 150) {
4729
- if (!aggressive) return;
4730
- how = "prev";
4731
- }
4732
- }
4733
- if (how == "prev") {
4734
- if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
4735
- else indentation = 0;
4736
- } else if (how == "add") {
4737
- indentation = curSpace + cm.options.indentUnit;
4738
- } else if (how == "subtract") {
4739
- indentation = curSpace - cm.options.indentUnit;
4740
- } else if (typeof how == "number") {
4741
- indentation = curSpace + how;
4742
- }
4743
- indentation = Math.max(0, indentation);
4744
-
4745
- var indentString = "", pos = 0;
4746
- if (cm.options.indentWithTabs)
4747
- for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
4748
- if (pos < indentation) indentString += spaceStr(indentation - pos);
4749
-
4750
- if (indentString != curSpaceString) {
4751
- replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
4752
- line.stateAfter = null;
4753
- return true;
4754
- } else {
4755
- // Ensure that, if the cursor was in the whitespace at the start
4756
- // of the line, it is moved to the end of that space.
4757
- for (var i = 0; i < doc.sel.ranges.length; i++) {
4758
- var range = doc.sel.ranges[i];
4759
- if (range.head.line == n && range.head.ch < curSpaceString.length) {
4760
- var pos = Pos(n, curSpaceString.length);
4761
- replaceOneSelection(doc, i, new Range(pos, pos));
4762
- break;
4763
- }
4764
- }
4765
- }
4766
- }
4767
-
4768
- // Utility for applying a change to a line by handle or number,
4769
- // returning the number and optionally registering the line as
4770
- // changed.
4771
- function changeLine(doc, handle, changeType, op) {
4772
- var no = handle, line = handle;
4773
- if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
4774
- else no = lineNo(handle);
4775
- if (no == null) return null;
4776
- if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);
4777
- return line;
4778
- }
4779
-
4780
- // Helper for deleting text near the selection(s), used to implement
4781
- // backspace, delete, and similar functionality.
4782
- function deleteNearSelection(cm, compute) {
4783
- var ranges = cm.doc.sel.ranges, kill = [];
4784
- // Build up a set of ranges to kill first, merging overlapping
4785
- // ranges.
4786
- for (var i = 0; i < ranges.length; i++) {
4787
- var toKill = compute(ranges[i]);
4788
- while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
4789
- var replaced = kill.pop();
4790
- if (cmp(replaced.from, toKill.from) < 0) {
4791
- toKill.from = replaced.from;
4792
- break;
4793
- }
4794
- }
4795
- kill.push(toKill);
4796
- }
4797
- // Next, remove those actual ranges.
4798
- runInOp(cm, function() {
4799
- for (var i = kill.length - 1; i >= 0; i--)
4800
- replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");
4801
- ensureCursorVisible(cm);
4802
- });
4803
- }
4804
-
4805
- // Used for horizontal relative motion. Dir is -1 or 1 (left or
4806
- // right), unit can be "char", "column" (like char, but doesn't
4807
- // cross line boundaries), "word" (across next word), or "group" (to
4808
- // the start of next group of word or non-word-non-whitespace
4809
- // chars). The visually param controls whether, in right-to-left
4810
- // text, direction 1 means to move towards the next index in the
4811
- // string, or towards the character to the right of the current
4812
- // position. The resulting position will have a hitSide=true
4813
- // property if it reached the end of the document.
4814
- function findPosH(doc, pos, dir, unit, visually) {
4815
- var line = pos.line, ch = pos.ch, origDir = dir;
4816
- var lineObj = getLine(doc, line);
4817
- var possible = true;
4818
- function findNextLine() {
4819
- var l = line + dir;
4820
- if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
4821
- line = l;
4822
- return lineObj = getLine(doc, l);
4823
- }
4824
- function moveOnce(boundToLine) {
4825
- var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
4826
- if (next == null) {
4827
- if (!boundToLine && findNextLine()) {
4828
- if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
4829
- else ch = dir < 0 ? lineObj.text.length : 0;
4830
- } else return (possible = false);
4831
- } else ch = next;
4832
- return true;
4833
- }
4834
-
4835
- if (unit == "char") moveOnce();
4836
- else if (unit == "column") moveOnce(true);
4837
- else if (unit == "word" || unit == "group") {
4838
- var sawType = null, group = unit == "group";
4839
- var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
4840
- for (var first = true;; first = false) {
4841
- if (dir < 0 && !moveOnce(!first)) break;
4842
- var cur = lineObj.text.charAt(ch) || "\n";
4843
- var type = isWordChar(cur, helper) ? "w"
4844
- : group && cur == "\n" ? "n"
4845
- : !group || /\s/.test(cur) ? null
4846
- : "p";
4847
- if (group && !first && !type) type = "s";
4848
- if (sawType && sawType != type) {
4849
- if (dir < 0) {dir = 1; moveOnce();}
4850
- break;
4851
- }
4852
-
4853
- if (type) sawType = type;
4854
- if (dir > 0 && !moveOnce(!first)) break;
4855
- }
4856
- }
4857
- var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true);
4858
- if (!possible) result.hitSide = true;
4859
- return result;
4860
- }
4861
-
4862
- // For relative vertical movement. Dir may be -1 or 1. Unit can be
4863
- // "page" or "line". The resulting position will have a hitSide=true
4864
- // property if it reached the end of the document.
4865
- function findPosV(cm, pos, dir, unit) {
4866
- var doc = cm.doc, x = pos.left, y;
4867
- if (unit == "page") {
4868
- var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
4869
- y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
4870
- } else if (unit == "line") {
4871
- y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
4872
- }
4873
- for (;;) {
4874
- var target = coordsChar(cm, x, y);
4875
- if (!target.outside) break;
4876
- if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
4877
- y += dir * 5;
4878
- }
4879
- return target;
4880
- }
4881
-
4882
- // EDITOR METHODS
4883
-
4884
- // The publicly visible API. Note that methodOp(f) means
4885
- // 'wrap f in an operation, performed on its `this` parameter'.
4886
-
4887
- // This is not the complete set of editor methods. Most of the
4888
- // methods defined on the Doc type are also injected into
4889
- // CodeMirror.prototype, for backwards compatibility and
4890
- // convenience.
4891
-
4892
- CodeMirror.prototype = {
4893
- constructor: CodeMirror,
4894
- focus: function(){window.focus(); this.display.input.focus();},
4895
-
4896
- setOption: function(option, value) {
4897
- var options = this.options, old = options[option];
4898
- if (options[option] == value && option != "mode") return;
4899
- options[option] = value;
4900
- if (optionHandlers.hasOwnProperty(option))
4901
- operation(this, optionHandlers[option])(this, value, old);
4902
- },
4903
-
4904
- getOption: function(option) {return this.options[option];},
4905
- getDoc: function() {return this.doc;},
4906
-
4907
- addKeyMap: function(map, bottom) {
4908
- this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
4909
- },
4910
- removeKeyMap: function(map) {
4911
- var maps = this.state.keyMaps;
4912
- for (var i = 0; i < maps.length; ++i)
4913
- if (maps[i] == map || maps[i].name == map) {
4914
- maps.splice(i, 1);
4915
- return true;
4916
- }
4917
- },
4918
-
4919
- addOverlay: methodOp(function(spec, options) {
4920
- var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
4921
- if (mode.startState) throw new Error("Overlays may not be stateful.");
4922
- this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
4923
- this.state.modeGen++;
4924
- regChange(this);
4925
- }),
4926
- removeOverlay: methodOp(function(spec) {
4927
- var overlays = this.state.overlays;
4928
- for (var i = 0; i < overlays.length; ++i) {
4929
- var cur = overlays[i].modeSpec;
4930
- if (cur == spec || typeof spec == "string" && cur.name == spec) {
4931
- overlays.splice(i, 1);
4932
- this.state.modeGen++;
4933
- regChange(this);
4934
- return;
4935
- }
4936
- }
4937
- }),
4938
-
4939
- indentLine: methodOp(function(n, dir, aggressive) {
4940
- if (typeof dir != "string" && typeof dir != "number") {
4941
- if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
4942
- else dir = dir ? "add" : "subtract";
4943
- }
4944
- if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
4945
- }),
4946
- indentSelection: methodOp(function(how) {
4947
- var ranges = this.doc.sel.ranges, end = -1;
4948
- for (var i = 0; i < ranges.length; i++) {
4949
- var range = ranges[i];
4950
- if (!range.empty()) {
4951
- var from = range.from(), to = range.to();
4952
- var start = Math.max(end, from.line);
4953
- end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
4954
- for (var j = start; j < end; ++j)
4955
- indentLine(this, j, how);
4956
- var newRanges = this.doc.sel.ranges;
4957
- if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
4958
- replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);
4959
- } else if (range.head.line > end) {
4960
- indentLine(this, range.head.line, how, true);
4961
- end = range.head.line;
4962
- if (i == this.doc.sel.primIndex) ensureCursorVisible(this);
4963
  }
4964
- }
4965
- }),
4966
-
4967
- // Fetch the parser token for a given character. Useful for hacks
4968
- // that want to inspect the mode state (say, for completion).
4969
- getTokenAt: function(pos, precise) {
4970
- return takeToken(this, pos, precise);
4971
- },
4972
-
4973
- getLineTokens: function(line, precise) {
4974
- return takeToken(this, Pos(line), precise, true);
4975
- },
4976
-
4977
- getTokenTypeAt: function(pos) {
4978
- pos = clipPos(this.doc, pos);
4979
- var styles = getLineStyles(this, getLine(this.doc, pos.line));
4980
- var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
4981
- var type;
4982
- if (ch == 0) type = styles[2];
4983
- else for (;;) {
4984
- var mid = (before + after) >> 1;
4985
- if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
4986
- else if (styles[mid * 2 + 1] < ch) before = mid + 1;
4987
- else { type = styles[mid * 2 + 2]; break; }
4988
- }
4989
- var cut = type ? type.indexOf("cm-overlay ") : -1;
4990
- return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);
4991
- },
4992
-
4993
- getModeAt: function(pos) {
4994
- var mode = this.doc.mode;
4995
- if (!mode.innerMode) return mode;
4996
- return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
4997
- },
4998
-
4999
- getHelper: function(pos, type) {
5000
- return this.getHelpers(pos, type)[0];
5001
- },
5002
-
5003
- getHelpers: function(pos, type) {
5004
- var found = [];
5005
- if (!helpers.hasOwnProperty(type)) return found;
5006
- var help = helpers[type], mode = this.getModeAt(pos);
5007
- if (typeof mode[type] == "string") {
5008
- if (help[mode[type]]) found.push(help[mode[type]]);
5009
- } else if (mode[type]) {
5010
- for (var i = 0; i < mode[type].length; i++) {
5011
- var val = help[mode[type][i]];
5012
- if (val) found.push(val);
5013
- }
5014
- } else if (mode.helperType && help[mode.helperType]) {
5015
- found.push(help[mode.helperType]);
5016
- } else if (help[mode.name]) {
5017
- found.push(help[mode.name]);
5018
- }
5019
- for (var i = 0; i < help._global.length; i++) {
5020
- var cur = help._global[i];
5021
- if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
5022
- found.push(cur.val);
5023
- }
5024
- return found;
5025
- },
5026
-
5027
- getStateAfter: function(line, precise) {
5028
- var doc = this.doc;
5029
- line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
5030
- return getStateBefore(this, line + 1, precise);
5031
- },
5032
-
5033
- cursorCoords: function(start, mode) {
5034
- var pos, range = this.doc.sel.primary();
5035
- if (start == null) pos = range.head;
5036
- else if (typeof start == "object") pos = clipPos(this.doc, start);
5037
- else pos = start ? range.from() : range.to();
5038
- return cursorCoords(this, pos, mode || "page");
5039
- },
5040
-
5041
- charCoords: function(pos, mode) {
5042
- return charCoords(this, clipPos(this.doc, pos), mode || "page");
5043
- },
5044
-
5045
- coordsChar: function(coords, mode) {
5046
- coords = fromCoordSystem(this, coords, mode || "page");
5047
- return coordsChar(this, coords.left, coords.top);
5048
- },
5049
-
5050
- lineAtHeight: function(height, mode) {
5051
- height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
5052
- return lineAtHeight(this.doc, height + this.display.viewOffset);
5053
- },
5054
- heightAtLine: function(line, mode) {
5055
- var end = false, lineObj;
5056
- if (typeof line == "number") {
5057
- var last = this.doc.first + this.doc.size - 1;
5058
- if (line < this.doc.first) line = this.doc.first;
5059
- else if (line > last) { line = last; end = true; }
5060
- lineObj = getLine(this.doc, line);
5061
- } else {
5062
- lineObj = line;
5063
- }
5064
- return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
5065
- (end ? this.doc.height - heightAtLine(lineObj) : 0);
5066
- },
5067
-
5068
- defaultTextHeight: function() { return textHeight(this.display); },
5069
- defaultCharWidth: function() { return charWidth(this.display); },
5070
-
5071
- setGutterMarker: methodOp(function(line, gutterID, value) {
5072
- return changeLine(this.doc, line, "gutter", function(line) {
5073
- var markers = line.gutterMarkers || (line.gutterMarkers = {});
5074
- markers[gutterID] = value;
5075
- if (!value && isEmpty(markers)) line.gutterMarkers = null;
5076
- return true;
5077
- });
5078
- }),
5079
-
5080
- clearGutter: methodOp(function(gutterID) {
5081
- var cm = this, doc = cm.doc, i = doc.first;
5082
- doc.iter(function(line) {
5083
- if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
5084
- line.gutterMarkers[gutterID] = null;
5085
- regLineChange(cm, i, "gutter");
5086
- if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
5087
- }
5088
- ++i;
5089
- });
5090
- }),
5091
-
5092
- lineInfo: function(line) {
5093
- if (typeof line == "number") {
5094
- if (!isLine(this.doc, line)) return null;
5095
- var n = line;
5096
- line = getLine(this.doc, line);
5097
- if (!line) return null;
5098
- } else {
5099
- var n = lineNo(line);
5100
- if (n == null) return null;
5101
- }
5102
- return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
5103
- textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
5104
- widgets: line.widgets};
5105
- },
5106
-
5107
- getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},
5108
-
5109
- addWidget: function(pos, node, scroll, vert, horiz) {
5110
- var display = this.display;
5111
- pos = cursorCoords(this, clipPos(this.doc, pos));
5112
- var top = pos.bottom, left = pos.left;
5113
- node.style.position = "absolute";
5114
- node.setAttribute("cm-ignore-events", "true");
5115
- this.display.input.setUneditable(node);
5116
- display.sizer.appendChild(node);
5117
- if (vert == "over") {
5118
- top = pos.top;
5119
- } else if (vert == "above" || vert == "near") {
5120
- var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
5121
- hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
5122
- // Default to positioning above (if specified and possible); otherwise default to positioning below
5123
- if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
5124
- top = pos.top - node.offsetHeight;
5125
- else if (pos.bottom + node.offsetHeight <= vspace)
5126
- top = pos.bottom;
5127
- if (left + node.offsetWidth > hspace)
5128
- left = hspace - node.offsetWidth;
5129
- }
5130
- node.style.top = top + "px";
5131
- node.style.left = node.style.right = "";
5132
- if (horiz == "right") {
5133
- left = display.sizer.clientWidth - node.offsetWidth;
5134
- node.style.right = "0px";
5135
- } else {
5136
- if (horiz == "left") left = 0;
5137
- else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
5138
- node.style.left = left + "px";
5139
- }
5140
- if (scroll)
5141
- scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
5142
- },
5143
-
5144
- triggerOnKeyDown: methodOp(onKeyDown),
5145
- triggerOnKeyPress: methodOp(onKeyPress),
5146
- triggerOnKeyUp: onKeyUp,
5147
-
5148
- execCommand: function(cmd) {
5149
- if (commands.hasOwnProperty(cmd))
5150
- return commands[cmd].call(null, this);
5151
- },
5152
-
5153
- triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
5154
-
5155
- findPosH: function(from, amount, unit, visually) {
5156
- var dir = 1;
5157
- if (amount < 0) { dir = -1; amount = -amount; }
5158
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
5159
- cur = findPosH(this.doc, cur, dir, unit, visually);
5160
- if (cur.hitSide) break;
5161
- }
5162
- return cur;
5163
- },
5164
-
5165
- moveH: methodOp(function(dir, unit) {
5166
- var cm = this;
5167
- cm.extendSelectionsBy(function(range) {
5168
- if (cm.display.shift || cm.doc.extend || range.empty())
5169
- return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);
5170
- else
5171
- return dir < 0 ? range.from() : range.to();
5172
- }, sel_move);
5173
- }),
5174
-
5175
- deleteH: methodOp(function(dir, unit) {
5176
- var sel = this.doc.sel, doc = this.doc;
5177
- if (sel.somethingSelected())
5178
- doc.replaceSelection("", null, "+delete");
5179
- else
5180
- deleteNearSelection(this, function(range) {
5181
- var other = findPosH(doc, range.head, dir, unit, false);
5182
- return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
5183
- });
5184
- }),
5185
-
5186
- findPosV: function(from, amount, unit, goalColumn) {
5187
- var dir = 1, x = goalColumn;
5188
- if (amount < 0) { dir = -1; amount = -amount; }
5189
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
5190
- var coords = cursorCoords(this, cur, "div");
5191
- if (x == null) x = coords.left;
5192
- else coords.left = x;
5193
- cur = findPosV(this, coords, dir, unit);
5194
- if (cur.hitSide) break;
5195
- }
5196
- return cur;
5197
- },
5198
-
5199
- moveV: methodOp(function(dir, unit) {
5200
- var cm = this, doc = this.doc, goals = [];
5201
- var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();
5202
- doc.extendSelectionsBy(function(range) {
5203
- if (collapse)
5204
- return dir < 0 ? range.from() : range.to();
5205
- var headPos = cursorCoords(cm, range.head, "div");
5206
- if (range.goalColumn != null) headPos.left = range.goalColumn;
5207
- goals.push(headPos.left);
5208
- var pos = findPosV(cm, headPos, dir, unit);
5209
- if (unit == "page" && range == doc.sel.primary())
5210
- addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);
5211
- return pos;
5212
- }, sel_move);
5213
- if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
5214
- doc.sel.ranges[i].goalColumn = goals[i];
5215
- }),
5216
-
5217
- // Find the word at the given position (as returned by coordsChar).
5218
- findWordAt: function(pos) {
5219
- var doc = this.doc, line = getLine(doc, pos.line).text;
5220
- var start = pos.ch, end = pos.ch;
5221
- if (line) {
5222
- var helper = this.getHelper(pos, "wordChars");
5223
- if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
5224
- var startChar = line.charAt(start);
5225
- var check = isWordChar(startChar, helper)
5226
- ? function(ch) { return isWordChar(ch, helper); }
5227
- : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
5228
- : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
5229
- while (start > 0 && check(line.charAt(start - 1))) --start;
5230
- while (end < line.length && check(line.charAt(end))) ++end;
5231
- }
5232
- return new Range(Pos(pos.line, start), Pos(pos.line, end));
5233
- },
5234
-
5235
- toggleOverwrite: function(value) {
5236
- if (value != null && value == this.state.overwrite) return;
5237
- if (this.state.overwrite = !this.state.overwrite)
5238
- addClass(this.display.cursorDiv, "CodeMirror-overwrite");
5239
- else
5240
- rmClass(this.display.cursorDiv, "CodeMirror-overwrite");
5241
-
5242
- signal(this, "overwriteToggle", this, this.state.overwrite);
5243
- },
5244
- hasFocus: function() { return this.display.input.getField() == activeElt(); },
5245
- isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit); },
5246
-
5247
- scrollTo: methodOp(function(x, y) {
5248
- if (x != null || y != null) resolveScrollToPos(this);
5249
- if (x != null) this.curOp.scrollLeft = x;
5250
- if (y != null) this.curOp.scrollTop = y;
5251
- }),
5252
- getScrollInfo: function() {
5253
- var scroller = this.display.scroller;
5254
- return {left: scroller.scrollLeft, top: scroller.scrollTop,
5255
- height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
5256
- width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
5257
- clientHeight: displayHeight(this), clientWidth: displayWidth(this)};
5258
- },
5259
-
5260
- scrollIntoView: methodOp(function(range, margin) {
5261
- if (range == null) {
5262
- range = {from: this.doc.sel.primary().head, to: null};
5263
- if (margin == null) margin = this.options.cursorScrollMargin;
5264
- } else if (typeof range == "number") {
5265
- range = {from: Pos(range, 0), to: null};
5266
- } else if (range.from == null) {
5267
- range = {from: range, to: null};
5268
- }
5269
- if (!range.to) range.to = range.from;
5270
- range.margin = margin || 0;
5271
-
5272
- if (range.from.line != null) {
5273
- resolveScrollToPos(this);
5274
- this.curOp.scrollToPos = range;
5275
- } else {
5276
- var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
5277
- Math.min(range.from.top, range.to.top) - range.margin,
5278
- Math.max(range.from.right, range.to.right),
5279
- Math.max(range.from.bottom, range.to.bottom) + range.margin);
5280
- this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
5281
- }
5282
- }),
5283
-
5284
- setSize: methodOp(function(width, height) {
5285
- var cm = this;
5286
- function interpret(val) {
5287
- return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
5288
- }
5289
- if (width != null) cm.display.wrapper.style.width = interpret(width);
5290
- if (height != null) cm.display.wrapper.style.height = interpret(height);
5291
- if (cm.options.lineWrapping) clearLineMeasurementCache(this);
5292
- var lineNo = cm.display.viewFrom;
5293
- cm.doc.iter(lineNo, cm.display.viewTo, function(line) {
5294
- if (line.widgets) for (var i = 0; i < line.widgets.length; i++)
5295
- if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; }
5296
- ++lineNo;
5297
- });
5298
- cm.curOp.forceUpdate = true;
5299
- signal(cm, "refresh", this);
5300
- }),
5301
-
5302
- operation: function(f){return runInOp(this, f);},
5303
-
5304
- refresh: methodOp(function() {
5305
- var oldHeight = this.display.cachedTextHeight;
5306
- regChange(this);
5307
- this.curOp.forceUpdate = true;
5308
- clearCaches(this);
5309
- this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
5310
- updateGutterSpace(this);
5311
- if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
5312
- estimateLineHeights(this);
5313
- signal(this, "refresh", this);
5314
- }),
5315
-
5316
- swapDoc: methodOp(function(doc) {
5317
- var old = this.doc;
5318
- old.cm = null;
5319
- attachDoc(this, doc);
5320
- clearCaches(this);
5321
- this.display.input.reset();
5322
- this.scrollTo(doc.scrollLeft, doc.scrollTop);
5323
- this.curOp.forceScroll = true;
5324
- signalLater(this, "swapDoc", this, old);
5325
- return old;
5326
- }),
5327
-
5328
- getInputField: function(){return this.display.input.getField();},
5329
- getWrapperElement: function(){return this.display.wrapper;},
5330
- getScrollerElement: function(){return this.display.scroller;},
5331
- getGutterElement: function(){return this.display.gutters;}
5332
- };
5333
- eventMixin(CodeMirror);
5334
-
5335
- // OPTION DEFAULTS
5336
-
5337
- // The default configuration options.
5338
- var defaults = CodeMirror.defaults = {};
5339
- // Functions to run when options are changed.
5340
- var optionHandlers = CodeMirror.optionHandlers = {};
5341
-
5342
- function option(name, deflt, handle, notOnInit) {
5343
- CodeMirror.defaults[name] = deflt;
5344
- if (handle) optionHandlers[name] =
5345
- notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
5346
- }
5347
-
5348
- // Passed to option handlers when there is no old value.
5349
- var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
5350
-
5351
- // These two are, on init, called from the constructor because they
5352
- // have to be initialized before the editor can start at all.
5353
- option("value", "", function(cm, val) {
5354
- cm.setValue(val);
5355
- }, true);
5356
- option("mode", null, function(cm, val) {
5357
- cm.doc.modeOption = val;
5358
- loadMode(cm);
5359
- }, true);
5360
-
5361
- option("indentUnit", 2, loadMode, true);
5362
- option("indentWithTabs", false);
5363
- option("smartIndent", true);
5364
- option("tabSize", 4, function(cm) {
5365
- resetModeState(cm);
5366
- clearCaches(cm);
5367
- regChange(cm);
5368
- }, true);
5369
- option("lineSeparator", null, function(cm, val) {
5370
- cm.doc.lineSep = val;
5371
- if (!val) return;
5372
- var newBreaks = [], lineNo = cm.doc.first;
5373
- cm.doc.iter(function(line) {
5374
- for (var pos = 0;;) {
5375
- var found = line.text.indexOf(val, pos);
5376
- if (found == -1) break;
5377
- pos = found + val.length;
5378
- newBreaks.push(Pos(lineNo, found));
5379
- }
5380
- lineNo++;
5381
- });
5382
- for (var i = newBreaks.length - 1; i >= 0; i--)
5383
- replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))
5384
- });
5385
- option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
5386
- cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
5387
- if (old != CodeMirror.Init) cm.refresh();
5388
- });
5389
- option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
5390
- option("electricChars", true);
5391
- option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
5392
- throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME
5393
- }, true);
5394
- option("rtlMoveVisually", !windows);
5395
- option("wholeLineUpdateBefore", true);
5396
-
5397
- option("theme", "default", function(cm) {
5398
- themeChanged(cm);
5399
- guttersChanged(cm);
5400
- }, true);
5401
- option("keyMap", "default", function(cm, val, old) {
5402
- var next = getKeyMap(val);
5403
- var prev = old != CodeMirror.Init && getKeyMap(old);
5404
- if (prev && prev.detach) prev.detach(cm, next);
5405
- if (next.attach) next.attach(cm, prev || null);
5406
- });
5407
- option("extraKeys", null);
5408
-
5409
- option("lineWrapping", false, wrappingChanged, true);
5410
- option("gutters", [], function(cm) {
5411
- setGuttersForLineNumbers(cm.options);
5412
- guttersChanged(cm);
5413
- }, true);
5414
- option("fixedGutter", true, function(cm, val) {
5415
- cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
5416
- cm.refresh();
5417
- }, true);
5418
- option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);
5419
- option("scrollbarStyle", "native", function(cm) {
5420
- initScrollbars(cm);
5421
- updateScrollbars(cm);
5422
- cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
5423
- cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
5424
- }, true);
5425
- option("lineNumbers", false, function(cm) {
5426
- setGuttersForLineNumbers(cm.options);
5427
- guttersChanged(cm);
5428
- }, true);
5429
- option("firstLineNumber", 1, guttersChanged, true);
5430
- option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
5431
- option("showCursorWhenSelecting", false, updateSelection, true);
5432
-
5433
- option("resetSelectionOnContextMenu", true);
5434
- option("lineWiseCopyCut", true);
5435
-
5436
- option("readOnly", false, function(cm, val) {
5437
- if (val == "nocursor") {
5438
- onBlur(cm);
5439
- cm.display.input.blur();
5440
- cm.display.disabled = true;
5441
- } else {
5442
- cm.display.disabled = false;
5443
- }
5444
- cm.display.input.readOnlyChanged(val)
5445
- });
5446
- option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
5447
- option("dragDrop", true, dragDropChanged);
5448
- option("allowDropFileTypes", null);
5449
-
5450
- option("cursorBlinkRate", 530);
5451
- option("cursorScrollMargin", 0);
5452
- option("cursorHeight", 1, updateSelection, true);
5453
- option("singleCursorHeightPerLine", true, updateSelection, true);
5454
- option("workTime", 100);
5455
- option("workDelay", 100);
5456
- option("flattenSpans", true, resetModeState, true);
5457
- option("addModeClass", false, resetModeState, true);
5458
- option("pollInterval", 100);
5459
- option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});
5460
- option("historyEventDelay", 1250);
5461
- option("viewportMargin", 10, function(cm){cm.refresh();}, true);
5462
- option("maxHighlightLength", 10000, resetModeState, true);
5463
- option("moveInputWithCursor", true, function(cm, val) {
5464
- if (!val) cm.display.input.resetPosition();
5465
- });
5466
-
5467
- option("tabindex", null, function(cm, val) {
5468
- cm.display.input.getField().tabIndex = val || "";
5469
- });
5470
- option("autofocus", null);
5471
-
5472
- // MODE DEFINITION AND QUERYING
5473
-
5474
- // Known modes, by name and by MIME
5475
- var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
5476
-
5477
- // Extra arguments are stored as the mode's dependencies, which is
5478
- // used by (legacy) mechanisms like loadmode.js to automatically
5479
- // load a mode. (Preferred mechanism is the require/define calls.)
5480
- CodeMirror.defineMode = function(name, mode) {
5481
- if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
5482
- if (arguments.length > 2)
5483
- mode.dependencies = Array.prototype.slice.call(arguments, 2);
5484
- modes[name] = mode;
5485
- };
5486
-
5487
- CodeMirror.defineMIME = function(mime, spec) {
5488
- mimeModes[mime] = spec;
5489
- };
5490
-
5491
- // Given a MIME type, a {name, ...options} config object, or a name
5492
- // string, return a mode config object.
5493
- CodeMirror.resolveMode = function(spec) {
5494
- if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
5495
- spec = mimeModes[spec];
5496
- } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
5497
- var found = mimeModes[spec.name];
5498
- if (typeof found == "string") found = {name: found};
5499
- spec = createObj(found, spec);
5500
- spec.name = found.name;
5501
- } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
5502
- return CodeMirror.resolveMode("application/xml");
5503
- }
5504
- if (typeof spec == "string") return {name: spec};
5505
- else return spec || {name: "null"};
5506
- };
5507
-
5508
- // Given a mode spec (anything that resolveMode accepts), find and
5509
- // initialize an actual mode object.
5510
- CodeMirror.getMode = function(options, spec) {
5511
- var spec = CodeMirror.resolveMode(spec);
5512
- var mfactory = modes[spec.name];
5513
- if (!mfactory) return CodeMirror.getMode(options, "text/plain");
5514
- var modeObj = mfactory(options, spec);
5515
- if (modeExtensions.hasOwnProperty(spec.name)) {
5516
- var exts = modeExtensions[spec.name];
5517
- for (var prop in exts) {
5518
- if (!exts.hasOwnProperty(prop)) continue;
5519
- if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
5520
- modeObj[prop] = exts[prop];
5521
- }
5522
- }
5523
- modeObj.name = spec.name;
5524
- if (spec.helperType) modeObj.helperType = spec.helperType;
5525
- if (spec.modeProps) for (var prop in spec.modeProps)
5526
- modeObj[prop] = spec.modeProps[prop];
5527
-
5528
- return modeObj;
5529
- };
5530
-
5531
- // Minimal default mode.
5532
- CodeMirror.defineMode("null", function() {
5533
- return {token: function(stream) {stream.skipToEnd();}};
5534
- });
5535
- CodeMirror.defineMIME("text/plain", "null");
5536
-
5537
- // This can be used to attach properties to mode objects from
5538
- // outside the actual mode definition.
5539
- var modeExtensions = CodeMirror.modeExtensions = {};
5540
- CodeMirror.extendMode = function(mode, properties) {
5541
- var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
5542
- copyObj(properties, exts);
5543
- };
5544
-
5545
- // EXTENSIONS
5546
-
5547
- CodeMirror.defineExtension = function(name, func) {
5548
- CodeMirror.prototype[name] = func;
5549
- };
5550
- CodeMirror.defineDocExtension = function(name, func) {
5551
- Doc.prototype[name] = func;
5552
- };
5553
- CodeMirror.defineOption = option;
5554
-
5555
- var initHooks = [];
5556
- CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
5557
-
5558
- var helpers = CodeMirror.helpers = {};
5559
- CodeMirror.registerHelper = function(type, name, value) {
5560
- if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
5561
- helpers[type][name] = value;
5562
- };
5563
- CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
5564
- CodeMirror.registerHelper(type, name, value);
5565
- helpers[type]._global.push({pred: predicate, val: value});
5566
- };
5567
-
5568
- // MODE STATE HANDLING
5569
-
5570
- // Utility functions for working with state. Exported because nested
5571
- // modes need to do this for their inner modes.
5572
-
5573
- var copyState = CodeMirror.copyState = function(mode, state) {
5574
- if (state === true) return state;
5575
- if (mode.copyState) return mode.copyState(state);
5576
- var nstate = {};
5577
- for (var n in state) {
5578
- var val = state[n];
5579
- if (val instanceof Array) val = val.concat([]);
5580
- nstate[n] = val;
5581
- }
5582
- return nstate;
5583
- };
5584
-
5585
- var startState = CodeMirror.startState = function(mode, a1, a2) {
5586
- return mode.startState ? mode.startState(a1, a2) : true;
5587
- };
5588
-
5589
- // Given a mode and a state (for that mode), find the inner mode and
5590
- // state at the position that the state refers to.
5591
- CodeMirror.innerMode = function(mode, state) {
5592
- while (mode.innerMode) {
5593
- var info = mode.innerMode(state);
5594
- if (!info || info.mode == mode) break;
5595
- state = info.state;
5596
- mode = info.mode;
5597
- }
5598
- return info || {mode: mode, state: state};
5599
- };
5600
-
5601
- // STANDARD COMMANDS
5602
-
5603
- // Commands are parameter-less actions that can be performed on an
5604
- // editor, mostly used for keybindings.
5605
- var commands = CodeMirror.commands = {
5606
- selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},
5607
- singleSelection: function(cm) {
5608
- cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);
5609
- },
5610
- killLine: function(cm) {
5611
- deleteNearSelection(cm, function(range) {
5612
- if (range.empty()) {
5613
- var len = getLine(cm.doc, range.head.line).text.length;
5614
- if (range.head.ch == len && range.head.line < cm.lastLine())
5615
- return {from: range.head, to: Pos(range.head.line + 1, 0)};
5616
- else
5617
- return {from: range.head, to: Pos(range.head.line, len)};
5618
- } else {
5619
- return {from: range.from(), to: range.to()};
5620
- }
5621
- });
5622
- },
5623
- deleteLine: function(cm) {
5624
- deleteNearSelection(cm, function(range) {
5625
- return {from: Pos(range.from().line, 0),
5626
- to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};
5627
- });
5628
- },
5629
- delLineLeft: function(cm) {
5630
- deleteNearSelection(cm, function(range) {
5631
- return {from: Pos(range.from().line, 0), to: range.from()};
5632
- });
5633
- },
5634
- delWrappedLineLeft: function(cm) {
5635
- deleteNearSelection(cm, function(range) {
5636
- var top = cm.charCoords(range.head, "div").top + 5;
5637
- var leftPos = cm.coordsChar({left: 0, top: top}, "div");
5638
- return {from: leftPos, to: range.from()};
5639
- });
5640
- },
5641
- delWrappedLineRight: function(cm) {
5642
- deleteNearSelection(cm, function(range) {
5643
- var top = cm.charCoords(range.head, "div").top + 5;
5644
- var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
5645
- return {from: range.from(), to: rightPos };
5646
- });
5647
- },
5648
- undo: function(cm) {cm.undo();},
5649
- redo: function(cm) {cm.redo();},
5650
- undoSelection: function(cm) {cm.undoSelection();},
5651
- redoSelection: function(cm) {cm.redoSelection();},
5652
- goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
5653
- goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
5654
- goLineStart: function(cm) {
5655
- cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },
5656
- {origin: "+move", bias: 1});
5657
- },
5658
- goLineStartSmart: function(cm) {
5659
- cm.extendSelectionsBy(function(range) {
5660
- return lineStartSmart(cm, range.head);
5661
- }, {origin: "+move", bias: 1});
5662
- },
5663
- goLineEnd: function(cm) {
5664
- cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },
5665
- {origin: "+move", bias: -1});
5666
- },
5667
- goLineRight: function(cm) {
5668
- cm.extendSelectionsBy(function(range) {
5669
- var top = cm.charCoords(range.head, "div").top + 5;
5670
- return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
5671
- }, sel_move);
5672
- },
5673
- goLineLeft: function(cm) {
5674
- cm.extendSelectionsBy(function(range) {
5675
- var top = cm.charCoords(range.head, "div").top + 5;
5676
- return cm.coordsChar({left: 0, top: top}, "div");
5677
- }, sel_move);
5678
- },
5679
- goLineLeftSmart: function(cm) {
5680
- cm.extendSelectionsBy(function(range) {
5681
- var top = cm.charCoords(range.head, "div").top + 5;
5682
- var pos = cm.coordsChar({left: 0, top: top}, "div");
5683
- if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head);
5684
- return pos;
5685
- }, sel_move);
5686
- },
5687
- goLineUp: function(cm) {cm.moveV(-1, "line");},
5688
- goLineDown: function(cm) {cm.moveV(1, "line");},
5689
- goPageUp: function(cm) {cm.moveV(-1, "page");},
5690
- goPageDown: function(cm) {cm.moveV(1, "page");},
5691
- goCharLeft: function(cm) {cm.moveH(-1, "char");},
5692
- goCharRight: function(cm) {cm.moveH(1, "char");},
5693
- goColumnLeft: function(cm) {cm.moveH(-1, "column");},
5694
- goColumnRight: function(cm) {cm.moveH(1, "column");},
5695
- goWordLeft: function(cm) {cm.moveH(-1, "word");},
5696
- goGroupRight: function(cm) {cm.moveH(1, "group");},
5697
- goGroupLeft: function(cm) {cm.moveH(-1, "group");},
5698
- goWordRight: function(cm) {cm.moveH(1, "word");},
5699
- delCharBefore: function(cm) {cm.deleteH(-1, "char");},
5700
- delCharAfter: function(cm) {cm.deleteH(1, "char");},
5701
- delWordBefore: function(cm) {cm.deleteH(-1, "word");},
5702
- delWordAfter: function(cm) {cm.deleteH(1, "word");},
5703
- delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
5704
- delGroupAfter: function(cm) {cm.deleteH(1, "group");},
5705
- indentAuto: function(cm) {cm.indentSelection("smart");},
5706
- indentMore: function(cm) {cm.indentSelection("add");},
5707
- indentLess: function(cm) {cm.indentSelection("subtract");},
5708
- insertTab: function(cm) {cm.replaceSelection("\t");},
5709
- insertSoftTab: function(cm) {
5710
- var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
5711
- for (var i = 0; i < ranges.length; i++) {
5712
- var pos = ranges[i].from();
5713
- var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
5714
- spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
5715
- }
5716
- cm.replaceSelections(spaces);
5717
- },
5718
- defaultTab: function(cm) {
5719
- if (cm.somethingSelected()) cm.indentSelection("add");
5720
- else cm.execCommand("insertTab");
5721
- },
5722
- transposeChars: function(cm) {
5723
- runInOp(cm, function() {
5724
- var ranges = cm.listSelections(), newSel = [];
5725
- for (var i = 0; i < ranges.length; i++) {
5726
- var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
5727
- if (line) {
5728
- if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
5729
- if (cur.ch > 0) {
5730
- cur = new Pos(cur.line, cur.ch + 1);
5731
- cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
5732
- Pos(cur.line, cur.ch - 2), cur, "+transpose");
5733
- } else if (cur.line > cm.doc.first) {
5734
- var prev = getLine(cm.doc, cur.line - 1).text;
5735
- if (prev)
5736
- cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
5737
- prev.charAt(prev.length - 1),
5738
- Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
5739
- }
5740
- }
5741
- newSel.push(new Range(cur, cur));
5742
- }
5743
- cm.setSelections(newSel);
5744
- });
5745
- },
5746
- newlineAndIndent: function(cm) {
5747
- runInOp(cm, function() {
5748
- var len = cm.listSelections().length;
5749
- for (var i = 0; i < len; i++) {
5750
- var range = cm.listSelections()[i];
5751
- cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input");
5752
- cm.indentLine(range.from().line + 1, null, true);
5753
- }
5754
- ensureCursorVisible(cm);
5755
- });
5756
- },
5757
- toggleOverwrite: function(cm) {cm.toggleOverwrite();}
5758
- };
5759
-
5760
-
5761
- // STANDARD KEYMAPS
5762
-
5763
- var keyMap = CodeMirror.keyMap = {};
5764
-
5765
- keyMap.basic = {
5766
- "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
5767
- "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
5768
- "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
5769
- "Tab": "defaultTab", "Shift-Tab": "indentAuto",
5770
- "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
5771
- "Esc": "singleSelection"
5772
- };
5773
- // Note that the save and find-related commands aren't defined by
5774
- // default. User code or addons can define them. Unknown commands
5775
- // are simply ignored.
5776
- keyMap.pcDefault = {
5777
- "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
5778
- "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
5779
- "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
5780
- "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
5781
- "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
5782
- "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
5783
- "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
5784
- fallthrough: "basic"
5785
- };
5786
- // Very basic readline/emacs-style bindings, which are standard on Mac.
5787
- keyMap.emacsy = {
5788
- "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
5789
- "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
5790
- "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
5791
- "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
5792
- };
5793
- keyMap.macDefault = {
5794
- "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
5795
- "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
5796
- "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
5797
- "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
5798
- "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
5799
- "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
5800
- "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
5801
- fallthrough: ["basic", "emacsy"]
5802
- };
5803
- keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
5804
-
5805
- // KEYMAP DISPATCH
5806
-
5807
- function normalizeKeyName(name) {
5808
- var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
5809
- var alt, ctrl, shift, cmd;
5810
- for (var i = 0; i < parts.length - 1; i++) {
5811
- var mod = parts[i];
5812
- if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
5813
- else if (/^a(lt)?$/i.test(mod)) alt = true;
5814
- else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
5815
- else if (/^s(hift)$/i.test(mod)) shift = true;
5816
- else throw new Error("Unrecognized modifier name: " + mod);
5817
- }
5818
- if (alt) name = "Alt-" + name;
5819
- if (ctrl) name = "Ctrl-" + name;
5820
- if (cmd) name = "Cmd-" + name;
5821
- if (shift) name = "Shift-" + name;
5822
- return name;
5823
- }
5824
-
5825
- // This is a kludge to keep keymaps mostly working as raw objects
5826
- // (backwards compatibility) while at the same time support features
5827
- // like normalization and multi-stroke key bindings. It compiles a
5828
- // new normalized keymap, and then updates the old object to reflect
5829
- // this.
5830
- CodeMirror.normalizeKeyMap = function(keymap) {
5831
- var copy = {};
5832
- for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
5833
- var value = keymap[keyname];
5834
- if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
5835
- if (value == "...") { delete keymap[keyname]; continue; }
5836
-
5837
- var keys = map(keyname.split(" "), normalizeKeyName);
5838
- for (var i = 0; i < keys.length; i++) {
5839
- var val, name;
5840
- if (i == keys.length - 1) {
5841
- name = keys.join(" ");
5842
- val = value;
5843
- } else {
5844
- name = keys.slice(0, i + 1).join(" ");
5845
- val = "...";
5846
- }
5847
- var prev = copy[name];
5848
- if (!prev) copy[name] = val;
5849
- else if (prev != val) throw new Error("Inconsistent bindings for " + name);
5850
- }
5851
- delete keymap[keyname];
5852
- }
5853
- for (var prop in copy) keymap[prop] = copy[prop];
5854
- return keymap;
5855
- };
5856
-
5857
- var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {
5858
- map = getKeyMap(map);
5859
- var found = map.call ? map.call(key, context) : map[key];
5860
- if (found === false) return "nothing";
5861
- if (found === "...") return "multi";
5862
- if (found != null && handle(found)) return "handled";
5863
-
5864
- if (map.fallthrough) {
5865
- if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
5866
- return lookupKey(key, map.fallthrough, handle, context);
5867
- for (var i = 0; i < map.fallthrough.length; i++) {
5868
- var result = lookupKey(key, map.fallthrough[i], handle, context);
5869
- if (result) return result;
5870
- }
5871
- }
5872
- };
5873
-
5874
- // Modifier key presses don't count as 'real' key presses for the
5875
- // purpose of keymap fallthrough.
5876
- var isModifierKey = CodeMirror.isModifierKey = function(value) {
5877
- var name = typeof value == "string" ? value : keyNames[value.keyCode];
5878
- return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
5879
- };
5880
-
5881
- // Look up the name of a key as indicated by an event object.
5882
- var keyName = CodeMirror.keyName = function(event, noShift) {
5883
- if (presto && event.keyCode == 34 && event["char"]) return false;
5884
- var base = keyNames[event.keyCode], name = base;
5885
- if (name == null || event.altGraphKey) return false;
5886
- if (event.altKey && base != "Alt") name = "Alt-" + name;
5887
- if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
5888
- if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
5889
- if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;
5890
- return name;
5891
- };
5892
-
5893
- function getKeyMap(val) {
5894
- return typeof val == "string" ? keyMap[val] : val;
5895
- }
5896
-
5897
- // FROMTEXTAREA
5898
-
5899
- CodeMirror.fromTextArea = function(textarea, options) {
5900
- options = options ? copyObj(options) : {};
5901
- options.value = textarea.value;
5902
- if (!options.tabindex && textarea.tabIndex)
5903
- options.tabindex = textarea.tabIndex;
5904
- if (!options.placeholder && textarea.placeholder)
5905
- options.placeholder = textarea.placeholder;
5906
- // Set autofocus to true if this textarea is focused, or if it has
5907
- // autofocus and no other element is focused.
5908
- if (options.autofocus == null) {
5909
- var hasFocus = activeElt();
5910
- options.autofocus = hasFocus == textarea ||
5911
- textarea.getAttribute("autofocus") != null && hasFocus == document.body;
5912
- }
5913
-
5914
- function save() {textarea.value = cm.getValue();}
5915
- if (textarea.form) {
5916
- on(textarea.form, "submit", save);
5917
- // Deplorable hack to make the submit method do the right thing.
5918
- if (!options.leaveSubmitMethodAlone) {
5919
- var form = textarea.form, realSubmit = form.submit;
5920
- try {
5921
- var wrappedSubmit = form.submit = function() {
5922
- save();
5923
- form.submit = realSubmit;
5924
- form.submit();
5925
- form.submit = wrappedSubmit;
5926
- };
5927
- } catch(e) {}
5928
- }
5929
- }
5930
-
5931
- options.finishInit = function(cm) {
5932
- cm.save = save;
5933
- cm.getTextArea = function() { return textarea; };
5934
- cm.toTextArea = function() {
5935
- cm.toTextArea = isNaN; // Prevent this from being ran twice
5936
- save();
5937
- textarea.parentNode.removeChild(cm.getWrapperElement());
5938
- textarea.style.display = "";
5939
- if (textarea.form) {
5940
- off(textarea.form, "submit", save);
5941
- if (typeof textarea.form.submit == "function")
5942
- textarea.form.submit = realSubmit;
5943
- }
5944
- };
5945
- };
5946
-
5947
- textarea.style.display = "none";
5948
- var cm = CodeMirror(function(node) {
5949
- textarea.parentNode.insertBefore(node, textarea.nextSibling);
5950
- }, options);
5951
- return cm;
5952
- };
5953
-
5954
- // STRING STREAM
5955
-
5956
- // Fed to the mode parsers, provides helper functions to make
5957
- // parsers more succinct.
5958
-
5959
- var StringStream = CodeMirror.StringStream = function(string, tabSize) {
5960
- this.pos = this.start = 0;
5961
- this.string = string;
5962
- this.tabSize = tabSize || 8;
5963
- this.lastColumnPos = this.lastColumnValue = 0;
5964
- this.lineStart = 0;
5965
- };
5966
-
5967
- StringStream.prototype = {
5968
- eol: function() {return this.pos >= this.string.length;},
5969
- sol: function() {return this.pos == this.lineStart;},
5970
- peek: function() {return this.string.charAt(this.pos) || undefined;},
5971
- next: function() {
5972
- if (this.pos < this.string.length)
5973
- return this.string.charAt(this.pos++);
5974
- },
5975
- eat: function(match) {
5976
- var ch = this.string.charAt(this.pos);
5977
- if (typeof match == "string") var ok = ch == match;
5978
- else var ok = ch && (match.test ? match.test(ch) : match(ch));
5979
- if (ok) {++this.pos; return ch;}
5980
- },
5981
- eatWhile: function(match) {
5982
- var start = this.pos;
5983
- while (this.eat(match)){}
5984
- return this.pos > start;
5985
- },
5986
- eatSpace: function() {
5987
- var start = this.pos;
5988
- while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
5989
- return this.pos > start;
5990
- },
5991
- skipToEnd: function() {this.pos = this.string.length;},
5992
- skipTo: function(ch) {
5993
- var found = this.string.indexOf(ch, this.pos);
5994
- if (found > -1) {this.pos = found; return true;}
5995
- },
5996
- backUp: function(n) {this.pos -= n;},
5997
- column: function() {
5998
- if (this.lastColumnPos < this.start) {
5999
- this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
6000
- this.lastColumnPos = this.start;
6001
- }
6002
- return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
6003
- },
6004
- indentation: function() {
6005
- return countColumn(this.string, null, this.tabSize) -
6006
- (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
6007
- },
6008
- match: function(pattern, consume, caseInsensitive) {
6009
- if (typeof pattern == "string") {
6010
- var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
6011
- var substr = this.string.substr(this.pos, pattern.length);
6012
- if (cased(substr) == cased(pattern)) {
6013
- if (consume !== false) this.pos += pattern.length;
6014
- return true;
6015
- }
6016
- } else {
6017
- var match = this.string.slice(this.pos).match(pattern);
6018
- if (match && match.index > 0) return null;
6019
- if (match && consume !== false) this.pos += match[0].length;
6020
- return match;
6021
- }
6022
- },
6023
- current: function(){return this.string.slice(this.start, this.pos);},
6024
- hideFirstChars: function(n, inner) {
6025
- this.lineStart += n;
6026
- try { return inner(); }
6027
- finally { this.lineStart -= n; }
6028
- }
6029
- };
6030
-
6031
- // TEXTMARKERS
6032
-
6033
- // Created with markText and setBookmark methods. A TextMarker is a
6034
- // handle that can be used to clear or find a marked position in the
6035
- // document. Line objects hold arrays (markedSpans) containing
6036
- // {from, to, marker} object pointing to such marker objects, and
6037
- // indicating that such a marker is present on that line. Multiple
6038
- // lines may point to the same marker when it spans across lines.
6039
- // The spans will have null for their from/to properties when the
6040
- // marker continues beyond the start/end of the line. Markers have
6041
- // links back to the lines they currently touch.
6042
-
6043
- var nextMarkerId = 0;
6044
-
6045
- var TextMarker = CodeMirror.TextMarker = function(doc, type) {
6046
- this.lines = [];
6047
- this.type = type;
6048
- this.doc = doc;
6049
- this.id = ++nextMarkerId;
6050
- };
6051
- eventMixin(TextMarker);
6052
-
6053
- // Clear the marker.
6054
- TextMarker.prototype.clear = function() {
6055
- if (this.explicitlyCleared) return;
6056
- var cm = this.doc.cm, withOp = cm && !cm.curOp;
6057
- if (withOp) startOperation(cm);
6058
- if (hasHandler(this, "clear")) {
6059
- var found = this.find();
6060
- if (found) signalLater(this, "clear", found.from, found.to);
6061
- }
6062
- var min = null, max = null;
6063
- for (var i = 0; i < this.lines.length; ++i) {
6064
- var line = this.lines[i];
6065
- var span = getMarkedSpanFor(line.markedSpans, this);
6066
- if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");
6067
- else if (cm) {
6068
- if (span.to != null) max = lineNo(line);
6069
- if (span.from != null) min = lineNo(line);
6070
- }
6071
- line.markedSpans = removeMarkedSpan(line.markedSpans, span);
6072
- if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
6073
- updateLineHeight(line, textHeight(cm.display));
6074
- }
6075
- if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
6076
- var visual = visualLine(this.lines[i]), len = lineLength(visual);
6077
- if (len > cm.display.maxLineLength) {
6078
- cm.display.maxLine = visual;
6079
- cm.display.maxLineLength = len;
6080
- cm.display.maxLineChanged = true;
6081
- }
6082
- }
6083
-
6084
- if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);
6085
- this.lines.length = 0;
6086
- this.explicitlyCleared = true;
6087
- if (this.atomic && this.doc.cantEdit) {
6088
- this.doc.cantEdit = false;
6089
- if (cm) reCheckSelection(cm.doc);
6090
- }
6091
- if (cm) signalLater(cm, "markerCleared", cm, this);
6092
- if (withOp) endOperation(cm);
6093
- if (this.parent) this.parent.clear();
6094
- };
6095
-
6096
- // Find the position of the marker in the document. Returns a {from,
6097
- // to} object by default. Side can be passed to get a specific side
6098
- // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
6099
- // Pos objects returned contain a line object, rather than a line
6100
- // number (used to prevent looking up the same line twice).
6101
- TextMarker.prototype.find = function(side, lineObj) {
6102
- if (side == null && this.type == "bookmark") side = 1;
6103
- var from, to;
6104
- for (var i = 0; i < this.lines.length; ++i) {
6105
- var line = this.lines[i];
6106
- var span = getMarkedSpanFor(line.markedSpans, this);
6107
- if (span.from != null) {
6108
- from = Pos(lineObj ? line : lineNo(line), span.from);
6109
- if (side == -1) return from;
6110
- }
6111
- if (span.to != null) {
6112
- to = Pos(lineObj ? line : lineNo(line), span.to);
6113
- if (side == 1) return to;
6114
- }
6115
- }
6116
- return from && {from: from, to: to};
6117
- };
6118
-
6119
- // Signals that the marker's widget changed, and surrounding layout
6120
- // should be recomputed.
6121
- TextMarker.prototype.changed = function() {
6122
- var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
6123
- if (!pos || !cm) return;
6124
- runInOp(cm, function() {
6125
- var line = pos.line, lineN = lineNo(pos.line);
6126
- var view = findViewForLine(cm, lineN);
6127
- if (view) {
6128
- clearLineMeasurementCacheFor(view);
6129
- cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
6130
- }
6131
- cm.curOp.updateMaxLine = true;
6132
- if (!lineIsHidden(widget.doc, line) && widget.height != null) {
6133
- var oldHeight = widget.height;
6134
- widget.height = null;
6135
- var dHeight = widgetHeight(widget) - oldHeight;
6136
- if (dHeight)
6137
- updateLineHeight(line, line.height + dHeight);
6138
- }
6139
- });
6140
- };
6141
-
6142
- TextMarker.prototype.attachLine = function(line) {
6143
- if (!this.lines.length && this.doc.cm) {
6144
- var op = this.doc.cm.curOp;
6145
- if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
6146
- (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
6147
- }
6148
- this.lines.push(line);
6149
- };
6150
- TextMarker.prototype.detachLine = function(line) {
6151
- this.lines.splice(indexOf(this.lines, line), 1);
6152
- if (!this.lines.length && this.doc.cm) {
6153
- var op = this.doc.cm.curOp;
6154
- (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
6155
- }
6156
- };
6157
-
6158
- // Collapsed markers have unique ids, in order to be able to order
6159
- // them, which is needed for uniquely determining an outer marker
6160
- // when they overlap (they may nest, but not partially overlap).
6161
- var nextMarkerId = 0;
6162
-
6163
- // Create a marker, wire it up to the right lines, and
6164
- function markText(doc, from, to, options, type) {
6165
- // Shared markers (across linked documents) are handled separately
6166
- // (markTextShared will call out to this again, once per
6167
- // document).
6168
- if (options && options.shared) return markTextShared(doc, from, to, options, type);
6169
- // Ensure we are in an operation.
6170
- if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
6171
-
6172
- var marker = new TextMarker(doc, type), diff = cmp(from, to);
6173
- if (options) copyObj(options, marker, false);
6174
- // Don't connect empty markers unless clearWhenEmpty is false
6175
- if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
6176
- return marker;
6177
- if (marker.replacedWith) {
6178
- // Showing up as a widget implies collapsed (widget replaces text)
6179
- marker.collapsed = true;
6180
- marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");
6181
- if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");
6182
- if (options.insertLeft) marker.widgetNode.insertLeft = true;
6183
- }
6184
- if (marker.collapsed) {
6185
- if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
6186
- from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
6187
- throw new Error("Inserting collapsed marker partially overlapping an existing one");
6188
- sawCollapsedSpans = true;
6189
- }
6190
-
6191
- if (marker.addToHistory)
6192
- addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);
6193
-
6194
- var curLine = from.line, cm = doc.cm, updateMaxLine;
6195
- doc.iter(curLine, to.line + 1, function(line) {
6196
- if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
6197
- updateMaxLine = true;
6198
- if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
6199
- addMarkedSpan(line, new MarkedSpan(marker,
6200
- curLine == from.line ? from.ch : null,
6201
- curLine == to.line ? to.ch : null));
6202
- ++curLine;
6203
- });
6204
- // lineIsHidden depends on the presence of the spans, so needs a second pass
6205
- if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
6206
- if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
6207
- });
6208
-
6209
- if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
6210
-
6211
- if (marker.readOnly) {
6212
- sawReadOnlySpans = true;
6213
- if (doc.history.done.length || doc.history.undone.length)
6214
- doc.clearHistory();
6215
- }
6216
- if (marker.collapsed) {
6217
- marker.id = ++nextMarkerId;
6218
- marker.atomic = true;
6219
- }
6220
- if (cm) {
6221
- // Sync editor state
6222
- if (updateMaxLine) cm.curOp.updateMaxLine = true;
6223
- if (marker.collapsed)
6224
- regChange(cm, from.line, to.line + 1);
6225
- else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
6226
- for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
6227
- if (marker.atomic) reCheckSelection(cm.doc);
6228
- signalLater(cm, "markerAdded", cm, marker);
6229
- }
6230
- return marker;
6231
- }
6232
-
6233
- // SHARED TEXTMARKERS
6234
-
6235
- // A shared marker spans multiple linked documents. It is
6236
- // implemented as a meta-marker-object controlling multiple normal
6237
- // markers.
6238
- var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
6239
- this.markers = markers;
6240
- this.primary = primary;
6241
- for (var i = 0; i < markers.length; ++i)
6242
- markers[i].parent = this;
6243
- };
6244
- eventMixin(SharedTextMarker);
6245
-
6246
- SharedTextMarker.prototype.clear = function() {
6247
- if (this.explicitlyCleared) return;
6248
- this.explicitlyCleared = true;
6249
- for (var i = 0; i < this.markers.length; ++i)
6250
- this.markers[i].clear();
6251
- signalLater(this, "clear");
6252
- };
6253
- SharedTextMarker.prototype.find = function(side, lineObj) {
6254
- return this.primary.find(side, lineObj);
6255
- };
6256
-
6257
- function markTextShared(doc, from, to, options, type) {
6258
- options = copyObj(options);
6259
- options.shared = false;
6260
- var markers = [markText(doc, from, to, options, type)], primary = markers[0];
6261
- var widget = options.widgetNode;
6262
- linkedDocs(doc, function(doc) {
6263
- if (widget) options.widgetNode = widget.cloneNode(true);
6264
- markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
6265
- for (var i = 0; i < doc.linked.length; ++i)
6266
- if (doc.linked[i].isParent) return;
6267
- primary = lst(markers);
6268
- });
6269
- return new SharedTextMarker(markers, primary);
6270
- }
6271
-
6272
- function findSharedMarkers(doc) {
6273
- return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),
6274
- function(m) { return m.parent; });
6275
- }
6276
-
6277
- function copySharedMarkers(doc, markers) {
6278
- for (var i = 0; i < markers.length; i++) {
6279
- var marker = markers[i], pos = marker.find();
6280
- var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
6281
- if (cmp(mFrom, mTo)) {
6282
- var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
6283
- marker.markers.push(subMark);
6284
- subMark.parent = marker;
6285
- }
6286
- }
6287
- }
6288
-
6289
- function detachSharedMarkers(markers) {
6290
- for (var i = 0; i < markers.length; i++) {
6291
- var marker = markers[i], linked = [marker.primary.doc];;
6292
- linkedDocs(marker.primary.doc, function(d) { linked.push(d); });
6293
- for (var j = 0; j < marker.markers.length; j++) {
6294
- var subMarker = marker.markers[j];
6295
- if (indexOf(linked, subMarker.doc) == -1) {
6296
- subMarker.parent = null;
6297
- marker.markers.splice(j--, 1);
6298
- }
6299
- }
6300
- }
6301
- }
6302
-
6303
- // TEXTMARKER SPANS
6304
-
6305
- function MarkedSpan(marker, from, to) {
6306
- this.marker = marker;
6307
- this.from = from; this.to = to;
6308
- }
6309
-
6310
- // Search an array of spans for a span matching the given marker.
6311
- function getMarkedSpanFor(spans, marker) {
6312
- if (spans) for (var i = 0; i < spans.length; ++i) {
6313
- var span = spans[i];
6314
- if (span.marker == marker) return span;
6315
- }
6316
- }
6317
- // Remove a span from an array, returning undefined if no spans are
6318
- // left (we don't store arrays for lines without spans).
6319
- function removeMarkedSpan(spans, span) {
6320
- for (var r, i = 0; i < spans.length; ++i)
6321
- if (spans[i] != span) (r || (r = [])).push(spans[i]);
6322
- return r;
6323
- }
6324
- // Add a span to a line.
6325
- function addMarkedSpan(line, span) {
6326
- line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
6327
- span.marker.attachLine(line);
6328
- }
6329
-
6330
- // Used for the algorithm that adjusts markers for a change in the
6331
- // document. These functions cut an array of spans at a given
6332
- // character position, returning an array of remaining chunks (or
6333
- // undefined if nothing remains).
6334
- function markedSpansBefore(old, startCh, isInsert) {
6335
- if (old) for (var i = 0, nw; i < old.length; ++i) {
6336
- var span = old[i], marker = span.marker;
6337
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
6338
- if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
6339
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
6340
- (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
6341
- }
6342
- }
6343
- return nw;
6344
- }
6345
- function markedSpansAfter(old, endCh, isInsert) {
6346
- if (old) for (var i = 0, nw; i < old.length; ++i) {
6347
- var span = old[i], marker = span.marker;
6348
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
6349
- if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
6350
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
6351
- (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
6352
- span.to == null ? null : span.to - endCh));
6353
- }
6354
- }
6355
- return nw;
6356
- }
6357
-
6358
- // Given a change object, compute the new set of marker spans that
6359
- // cover the line in which the change took place. Removes spans
6360
- // entirely within the change, reconnects spans belonging to the
6361
- // same marker that appear on both sides of the change, and cuts off
6362
- // spans partially within the change. Returns an array of span
6363
- // arrays with one element for each line in (after) the change.
6364
- function stretchSpansOverChange(doc, change) {
6365
- if (change.full) return null;
6366
- var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
6367
- var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
6368
- if (!oldFirst && !oldLast) return null;
6369
-
6370
- var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
6371
- // Get the spans that 'stick out' on both sides
6372
- var first = markedSpansBefore(oldFirst, startCh, isInsert);
6373
- var last = markedSpansAfter(oldLast, endCh, isInsert);
6374
-
6375
- // Next, merge those two ends
6376
- var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
6377
- if (first) {
6378
- // Fix up .to properties of first
6379
- for (var i = 0; i < first.length; ++i) {
6380
- var span = first[i];
6381
- if (span.to == null) {
6382
- var found = getMarkedSpanFor(last, span.marker);
6383
- if (!found) span.to = startCh;
6384
- else if (sameLine) span.to = found.to == null ? null : found.to + offset;
6385
- }
6386
- }
6387
- }
6388
- if (last) {
6389
- // Fix up .from in last (or move them into first in case of sameLine)
6390
- for (var i = 0; i < last.length; ++i) {
6391
- var span = last[i];
6392
- if (span.to != null) span.to += offset;
6393
- if (span.from == null) {
6394
- var found = getMarkedSpanFor(first, span.marker);
6395
- if (!found) {
6396
- span.from = offset;
6397
- if (sameLine) (first || (first = [])).push(span);
6398
- }
6399
- } else {
6400
- span.from += offset;
6401
- if (sameLine) (first || (first = [])).push(span);
6402
- }
6403
- }
6404
- }
6405
- // Make sure we didn't create any zero-length spans
6406
- if (first) first = clearEmptySpans(first);
6407
- if (last && last != first) last = clearEmptySpans(last);
6408
-
6409
- var newMarkers = [first];
6410
- if (!sameLine) {
6411
- // Fill gap with whole-line-spans
6412
- var gap = change.text.length - 2, gapMarkers;
6413
- if (gap > 0 && first)
6414
- for (var i = 0; i < first.length; ++i)
6415
- if (first[i].to == null)
6416
- (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));
6417
- for (var i = 0; i < gap; ++i)
6418
- newMarkers.push(gapMarkers);
6419
- newMarkers.push(last);
6420
- }
6421
- return newMarkers;
6422
- }
6423
-
6424
- // Remove spans that are empty and don't have a clearWhenEmpty
6425
- // option of false.
6426
- function clearEmptySpans(spans) {
6427
- for (var i = 0; i < spans.length; ++i) {
6428
- var span = spans[i];
6429
- if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
6430
- spans.splice(i--, 1);
6431
- }
6432
- if (!spans.length) return null;
6433
- return spans;
6434
- }
6435
-
6436
- // Used for un/re-doing changes from the history. Combines the
6437
- // result of computing the existing spans with the set of spans that
6438
- // existed in the history (so that deleting around a span and then
6439
- // undoing brings back the span).
6440
- function mergeOldSpans(doc, change) {
6441
- var old = getOldSpans(doc, change);
6442
- var stretched = stretchSpansOverChange(doc, change);
6443
- if (!old) return stretched;
6444
- if (!stretched) return old;
6445
-
6446
- for (var i = 0; i < old.length; ++i) {
6447
- var oldCur = old[i], stretchCur = stretched[i];
6448
- if (oldCur && stretchCur) {
6449
- spans: for (var j = 0; j < stretchCur.length; ++j) {
6450
- var span = stretchCur[j];
6451
- for (var k = 0; k < oldCur.length; ++k)
6452
- if (oldCur[k].marker == span.marker) continue spans;
6453
- oldCur.push(span);
6454
- }
6455
- } else if (stretchCur) {
6456
- old[i] = stretchCur;
6457
- }
6458
- }
6459
- return old;
6460
- }
6461
-
6462
- // Used to 'clip' out readOnly ranges when making a change.
6463
- function removeReadOnlyRanges(doc, from, to) {
6464
- var markers = null;
6465
- doc.iter(from.line, to.line + 1, function(line) {
6466
- if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
6467
- var mark = line.markedSpans[i].marker;
6468
- if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
6469
- (markers || (markers = [])).push(mark);
6470
- }
6471
- });
6472
- if (!markers) return null;
6473
- var parts = [{from: from, to: to}];
6474
- for (var i = 0; i < markers.length; ++i) {
6475
- var mk = markers[i], m = mk.find(0);
6476
- for (var j = 0; j < parts.length; ++j) {
6477
- var p = parts[j];
6478
- if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;
6479
- var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
6480
- if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
6481
- newParts.push({from: p.from, to: m.from});
6482
- if (dto > 0 || !mk.inclusiveRight && !dto)
6483
- newParts.push({from: m.to, to: p.to});
6484
- parts.splice.apply(parts, newParts);
6485
- j += newParts.length - 1;
6486
- }
6487
- }
6488
- return parts;
6489
- }
6490
-
6491
- // Connect or disconnect spans from a line.
6492
- function detachMarkedSpans(line) {
6493
- var spans = line.markedSpans;
6494
- if (!spans) return;
6495
- for (var i = 0; i < spans.length; ++i)
6496
- spans[i].marker.detachLine(line);
6497
- line.markedSpans = null;
6498
- }
6499
- function attachMarkedSpans(line, spans) {
6500
- if (!spans) return;
6501
- for (var i = 0; i < spans.length; ++i)
6502
- spans[i].marker.attachLine(line);
6503
- line.markedSpans = spans;
6504
- }
6505
-
6506
- // Helpers used when computing which overlapping collapsed span
6507
- // counts as the larger one.
6508
- function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
6509
- function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
6510
-
6511
- // Returns a number indicating which of two overlapping collapsed
6512
- // spans is larger (and thus includes the other). Falls back to
6513
- // comparing ids when the spans cover exactly the same range.
6514
- function compareCollapsedMarkers(a, b) {
6515
- var lenDiff = a.lines.length - b.lines.length;
6516
- if (lenDiff != 0) return lenDiff;
6517
- var aPos = a.find(), bPos = b.find();
6518
- var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
6519
- if (fromCmp) return -fromCmp;
6520
- var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
6521
- if (toCmp) return toCmp;
6522
- return b.id - a.id;
6523
- }
6524
-
6525
- // Find out whether a line ends or starts in a collapsed span. If
6526
- // so, return the marker for that span.
6527
- function collapsedSpanAtSide(line, start) {
6528
- var sps = sawCollapsedSpans && line.markedSpans, found;
6529
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
6530
- sp = sps[i];
6531
- if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
6532
- (!found || compareCollapsedMarkers(found, sp.marker) < 0))
6533
- found = sp.marker;
6534
- }
6535
- return found;
6536
- }
6537
- function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
6538
- function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
6539
-
6540
- // Test whether there exists a collapsed span that partially
6541
- // overlaps (covers the start or end, but not both) of a new span.
6542
- // Such overlap is not allowed.
6543
- function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
6544
- var line = getLine(doc, lineNo);
6545
- var sps = sawCollapsedSpans && line.markedSpans;
6546
- if (sps) for (var i = 0; i < sps.length; ++i) {
6547
- var sp = sps[i];
6548
- if (!sp.marker.collapsed) continue;
6549
- var found = sp.marker.find(0);
6550
- var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
6551
- var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
6552
- if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
6553
- if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||
6554
- fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))
6555
- return true;
6556
- }
6557
- }
6558
-
6559
- // A visual line is a line as drawn on the screen. Folding, for
6560
- // example, can cause multiple logical lines to appear on the same
6561
- // visual line. This finds the start of the visual line that the
6562
- // given line is part of (usually that is the line itself).
6563
- function visualLine(line) {
6564
- var merged;
6565
- while (merged = collapsedSpanAtStart(line))
6566
- line = merged.find(-1, true).line;
6567
- return line;
6568
- }
6569
-
6570
- // Returns an array of logical lines that continue the visual line
6571
- // started by the argument, or undefined if there are no such lines.
6572
- function visualLineContinued(line) {
6573
- var merged, lines;
6574
- while (merged = collapsedSpanAtEnd(line)) {
6575
- line = merged.find(1, true).line;
6576
- (lines || (lines = [])).push(line);
6577
- }
6578
- return lines;
6579
- }
6580
-
6581
- // Get the line number of the start of the visual line that the
6582
- // given line number is part of.
6583
- function visualLineNo(doc, lineN) {
6584
- var line = getLine(doc, lineN), vis = visualLine(line);
6585
- if (line == vis) return lineN;
6586
- return lineNo(vis);
6587
- }
6588
- // Get the line number of the start of the next visual line after
6589
- // the given line.
6590
- function visualLineEndNo(doc, lineN) {
6591
- if (lineN > doc.lastLine()) return lineN;
6592
- var line = getLine(doc, lineN), merged;
6593
- if (!lineIsHidden(doc, line)) return lineN;
6594
- while (merged = collapsedSpanAtEnd(line))
6595
- line = merged.find(1, true).line;
6596
- return lineNo(line) + 1;
6597
- }
6598
-
6599
- // Compute whether a line is hidden. Lines count as hidden when they
6600
- // are part of a visual line that starts with another line, or when
6601
- // they are entirely covered by collapsed, non-widget span.
6602
- function lineIsHidden(doc, line) {
6603
- var sps = sawCollapsedSpans && line.markedSpans;
6604
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
6605
- sp = sps[i];
6606
- if (!sp.marker.collapsed) continue;
6607
- if (sp.from == null) return true;
6608
- if (sp.marker.widgetNode) continue;
6609
- if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
6610
- return true;
6611
- }
6612
- }
6613
- function lineIsHiddenInner(doc, line, span) {
6614
- if (span.to == null) {
6615
- var end = span.marker.find(1, true);
6616
- return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));
6617
- }
6618
- if (span.marker.inclusiveRight && span.to == line.text.length)
6619
- return true;
6620
- for (var sp, i = 0; i < line.markedSpans.length; ++i) {
6621
- sp = line.markedSpans[i];
6622
- if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
6623
- (sp.to == null || sp.to != span.from) &&
6624
- (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
6625
- lineIsHiddenInner(doc, line, sp)) return true;
6626
- }
6627
- }
6628
-
6629
- // LINE WIDGETS
6630
-
6631
- // Line widgets are block elements displayed above or below a line.
6632
-
6633
- var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {
6634
- if (options) for (var opt in options) if (options.hasOwnProperty(opt))
6635
- this[opt] = options[opt];
6636
- this.doc = doc;
6637
- this.node = node;
6638
- };
6639
- eventMixin(LineWidget);
6640
-
6641
- function adjustScrollWhenAboveVisible(cm, line, diff) {
6642
- if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
6643
- addToScrollPos(cm, null, diff);
6644
- }
6645
-
6646
- LineWidget.prototype.clear = function() {
6647
- var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
6648
- if (no == null || !ws) return;
6649
- for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
6650
- if (!ws.length) line.widgets = null;
6651
- var height = widgetHeight(this);
6652
- updateLineHeight(line, Math.max(0, line.height - height));
6653
- if (cm) runInOp(cm, function() {
6654
- adjustScrollWhenAboveVisible(cm, line, -height);
6655
- regLineChange(cm, no, "widget");
6656
- });
6657
- };
6658
- LineWidget.prototype.changed = function() {
6659
- var oldH = this.height, cm = this.doc.cm, line = this.line;
6660
- this.height = null;
6661
- var diff = widgetHeight(this) - oldH;
6662
- if (!diff) return;
6663
- updateLineHeight(line, line.height + diff);
6664
- if (cm) runInOp(cm, function() {
6665
- cm.curOp.forceUpdate = true;
6666
- adjustScrollWhenAboveVisible(cm, line, diff);
6667
- });
6668
- };
6669
-
6670
- function widgetHeight(widget) {
6671
- if (widget.height != null) return widget.height;
6672
- var cm = widget.doc.cm;
6673
- if (!cm) return 0;
6674
- if (!contains(document.body, widget.node)) {
6675
- var parentStyle = "position: relative;";
6676
- if (widget.coverGutter)
6677
- parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;";
6678
- if (widget.noHScroll)
6679
- parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
6680
- removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
6681
- }
6682
- return widget.height = widget.node.parentNode.offsetHeight;
6683
- }
6684
-
6685
- function addLineWidget(doc, handle, node, options) {
6686
- var widget = new LineWidget(doc, node, options);
6687
- var cm = doc.cm;
6688
- if (cm && widget.noHScroll) cm.display.alignWidgets = true;
6689
- changeLine(doc, handle, "widget", function(line) {
6690
- var widgets = line.widgets || (line.widgets = []);
6691
- if (widget.insertAt == null) widgets.push(widget);
6692
- else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
6693
- widget.line = line;
6694
- if (cm && !lineIsHidden(doc, line)) {
6695
- var aboveVisible = heightAtLine(line) < doc.scrollTop;
6696
- updateLineHeight(line, line.height + widgetHeight(widget));
6697
- if (aboveVisible) addToScrollPos(cm, null, widget.height);
6698
- cm.curOp.forceUpdate = true;
6699
- }
6700
- return true;
6701
- });
6702
- return widget;
6703
- }
6704
-
6705
- // LINE DATA STRUCTURE
6706
-
6707
- // Line objects. These hold state related to a line, including
6708
- // highlighting info (the styles array).
6709
- var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
6710
- this.text = text;
6711
- attachMarkedSpans(this, markedSpans);
6712
- this.height = estimateHeight ? estimateHeight(this) : 1;
6713
- };
6714
- eventMixin(Line);
6715
- Line.prototype.lineNo = function() { return lineNo(this); };
6716
-
6717
- // Change the content (text, markers) of a line. Automatically
6718
- // invalidates cached information and tries to re-estimate the
6719
- // line's height.
6720
- function updateLine(line, text, markedSpans, estimateHeight) {
6721
- line.text = text;
6722
- if (line.stateAfter) line.stateAfter = null;
6723
- if (line.styles) line.styles = null;
6724
- if (line.order != null) line.order = null;
6725
- detachMarkedSpans(line);
6726
- attachMarkedSpans(line, markedSpans);
6727
- var estHeight = estimateHeight ? estimateHeight(line) : 1;
6728
- if (estHeight != line.height) updateLineHeight(line, estHeight);
6729
- }
6730
-
6731
- // Detach a line from the document tree and its markers.
6732
- function cleanUpLine(line) {
6733
- line.parent = null;
6734
- detachMarkedSpans(line);
6735
- }
6736
-
6737
- function extractLineClasses(type, output) {
6738
- if (type) for (;;) {
6739
- var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
6740
- if (!lineClass) break;
6741
- type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
6742
- var prop = lineClass[1] ? "bgClass" : "textClass";
6743
- if (output[prop] == null)
6744
- output[prop] = lineClass[2];
6745
- else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
6746
- output[prop] += " " + lineClass[2];
6747
- }
6748
- return type;
6749
- }
6750
-
6751
- function callBlankLine(mode, state) {
6752
- if (mode.blankLine) return mode.blankLine(state);
6753
- if (!mode.innerMode) return;
6754
- var inner = CodeMirror.innerMode(mode, state);
6755
- if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
6756
- }
6757
-
6758
- function readToken(mode, stream, state, inner) {
6759
- for (var i = 0; i < 10; i++) {
6760
- if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;
6761
- var style = mode.token(stream, state);
6762
- if (stream.pos > stream.start) return style;
6763
- }
6764
- throw new Error("Mode " + mode.name + " failed to advance stream.");
6765
- }
6766
-
6767
- // Utility for getTokenAt and getLineTokens
6768
- function takeToken(cm, pos, precise, asArray) {
6769
- function getObj(copy) {
6770
- return {start: stream.start, end: stream.pos,
6771
- string: stream.current(),
6772
- type: style || null,
6773
- state: copy ? copyState(doc.mode, state) : state};
6774
- }
6775
-
6776
- var doc = cm.doc, mode = doc.mode, style;
6777
- pos = clipPos(doc, pos);
6778
- var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
6779
- var stream = new StringStream(line.text, cm.options.tabSize), tokens;
6780
- if (asArray) tokens = [];
6781
- while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
6782
- stream.start = stream.pos;
6783
- style = readToken(mode, stream, state);
6784
- if (asArray) tokens.push(getObj(true));
6785
- }
6786
- return asArray ? tokens : getObj();
6787
- }
6788
-
6789
- // Run the given mode's parser over a line, calling f for each token.
6790
- function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
6791
- var flattenSpans = mode.flattenSpans;
6792
- if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
6793
- var curStart = 0, curStyle = null;
6794
- var stream = new StringStream(text, cm.options.tabSize), style;
6795
- var inner = cm.options.addModeClass && [null];
6796
- if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
6797
- while (!stream.eol()) {
6798
- if (stream.pos > cm.options.maxHighlightLength) {
6799
- flattenSpans = false;
6800
- if (forceToEnd) processLine(cm, text, state, stream.pos);
6801
- stream.pos = text.length;
6802
- style = null;
6803
- } else {
6804
- style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);
6805
- }
6806
- if (inner) {
6807
- var mName = inner[0].name;
6808
- if (mName) style = "m-" + (style ? mName + " " + style : mName);
6809
- }
6810
- if (!flattenSpans || curStyle != style) {
6811
- while (curStart < stream.start) {
6812
- curStart = Math.min(stream.start, curStart + 50000);
6813
- f(curStart, curStyle);
6814
- }
6815
- curStyle = style;
6816
- }
6817
- stream.start = stream.pos;
6818
- }
6819
- while (curStart < stream.pos) {
6820
- // Webkit seems to refuse to render text nodes longer than 57444 characters
6821
- var pos = Math.min(stream.pos, curStart + 50000);
6822
- f(pos, curStyle);
6823
- curStart = pos;
6824
- }
6825
- }
6826
-
6827
- // Compute a style array (an array starting with a mode generation
6828
- // -- for invalidation -- followed by pairs of end positions and
6829
- // style strings), which is used to highlight the tokens on the
6830
- // line.
6831
- function highlightLine(cm, line, state, forceToEnd) {
6832
- // A styles array always starts with a number identifying the
6833
- // mode/overlays that it is based on (for easy invalidation).
6834
- var st = [cm.state.modeGen], lineClasses = {};
6835
- // Compute the base array of styles
6836
- runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
6837
- st.push(end, style);
6838
- }, lineClasses, forceToEnd);
6839
-
6840
- // Run overlays, adjust style array.
6841
- for (var o = 0; o < cm.state.overlays.length; ++o) {
6842
- var overlay = cm.state.overlays[o], i = 1, at = 0;
6843
- runMode(cm, line.text, overlay.mode, true, function(end, style) {
6844
- var start = i;
6845
- // Ensure there's a token end at the current position, and that i points at it
6846
- while (at < end) {
6847
- var i_end = st[i];
6848
- if (i_end > end)
6849
- st.splice(i, 1, end, st[i+1], i_end);
6850
- i += 2;
6851
- at = Math.min(end, i_end);
6852
- }
6853
- if (!style) return;
6854
- if (overlay.opaque) {
6855
- st.splice(start, i - start, end, "cm-overlay " + style);
6856
- i = start + 2;
6857
- } else {
6858
- for (; start < i; start += 2) {
6859
- var cur = st[start+1];
6860
- st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;
6861
- }
6862
- }
6863
- }, lineClasses);
6864
- }
6865
-
6866
- return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
6867
- }
6868
-
6869
- function getLineStyles(cm, line, updateFrontier) {
6870
- if (!line.styles || line.styles[0] != cm.state.modeGen) {
6871
- var state = getStateBefore(cm, lineNo(line));
6872
- var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state);
6873
- line.stateAfter = state;
6874
- line.styles = result.styles;
6875
- if (result.classes) line.styleClasses = result.classes;
6876
- else if (line.styleClasses) line.styleClasses = null;
6877
- if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;
6878
- }
6879
- return line.styles;
6880
- }
6881
-
6882
- // Lightweight form of highlight -- proceed over this line and
6883
- // update state, but don't save a style array. Used for lines that
6884
- // aren't currently visible.
6885
- function processLine(cm, text, state, startAt) {
6886
- var mode = cm.doc.mode;
6887
- var stream = new StringStream(text, cm.options.tabSize);
6888
- stream.start = stream.pos = startAt || 0;
6889
- if (text == "") callBlankLine(mode, state);
6890
- while (!stream.eol()) {
6891
- readToken(mode, stream, state);
6892
- stream.start = stream.pos;
6893
- }
6894
- }
6895
-
6896
- // Convert a style as returned by a mode (either null, or a string
6897
- // containing one or more styles) to a CSS style. This is cached,
6898
- // and also looks for line-wide styles.
6899
- var styleToClassCache = {}, styleToClassCacheWithMode = {};
6900
- function interpretTokenStyle(style, options) {
6901
- if (!style || /^\s*$/.test(style)) return null;
6902
- var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
6903
- return cache[style] ||
6904
- (cache[style] = style.replace(/\S+/g, "cm-$&"));
6905
- }
6906
-
6907
- // Render the DOM representation of the text of a line. Also builds
6908
- // up a 'line map', which points at the DOM nodes that represent
6909
- // specific stretches of text, and is used by the measuring code.
6910
- // The returned object contains the DOM node, this map, and
6911
- // information about line-wide styles that were set by the mode.
6912
- function buildLineContent(cm, lineView) {
6913
- // The padding-right forces the element to have a 'border', which
6914
- // is needed on Webkit to be able to get line-level bounding
6915
- // rectangles for it (in measureChar).
6916
- var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
6917
- var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
6918
- col: 0, pos: 0, cm: cm,
6919
- splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
6920
- lineView.measure = {};
6921
-
6922
- // Iterate over the logical lines that make up this visual line.
6923
- for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
6924
- var line = i ? lineView.rest[i - 1] : lineView.line, order;
6925
- builder.pos = 0;
6926
- builder.addToken = buildToken;
6927
- // Optionally wire in some hacks into the token-rendering
6928
- // algorithm, to deal with browser quirks.
6929
- if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
6930
- builder.addToken = buildTokenBadBidi(builder.addToken, order);
6931
- builder.map = [];
6932
- var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
6933
- insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
6934
- if (line.styleClasses) {
6935
- if (line.styleClasses.bgClass)
6936
- builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
6937
- if (line.styleClasses.textClass)
6938
- builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");
6939
- }
6940
-
6941
- // Ensure at least a single node is present, for measuring.
6942
- if (builder.map.length == 0)
6943
- builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));
6944
-
6945
- // Store the map and a cache object for the current logical line
6946
- if (i == 0) {
6947
- lineView.measure.map = builder.map;
6948
- lineView.measure.cache = {};
6949
- } else {
6950
- (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);
6951
- (lineView.measure.caches || (lineView.measure.caches = [])).push({});
6952
- }
6953
- }
6954
-
6955
- // See issue #2901
6956
- if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
6957
- builder.content.className = "cm-tab-wrap-hack";
6958
-
6959
- signal(cm, "renderLine", cm, lineView.line, builder.pre);
6960
- if (builder.pre.className)
6961
- builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
6962
-
6963
- return builder;
6964
- }
6965
-
6966
- function defaultSpecialCharPlaceholder(ch) {
6967
- var token = elt("span", "\u2022", "cm-invalidchar");
6968
- token.title = "\\u" + ch.charCodeAt(0).toString(16);
6969
- token.setAttribute("aria-label", token.title);
6970
- return token;
6971
- }
6972
-
6973
- // Build up the DOM representation for a single token, and add it to
6974
- // the line map. Takes care to render special characters separately.
6975
- function buildToken(builder, text, style, startStyle, endStyle, title, css) {
6976
- if (!text) return;
6977
- var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;
6978
- var special = builder.cm.state.specialChars, mustWrap = false;
6979
- if (!special.test(text)) {
6980
- builder.col += text.length;
6981
- var content = document.createTextNode(displayText);
6982
- builder.map.push(builder.pos, builder.pos + text.length, content);
6983
- if (ie && ie_version < 9) mustWrap = true;
6984
- builder.pos += text.length;
6985
- } else {
6986
- var content = document.createDocumentFragment(), pos = 0;
6987
- while (true) {
6988
- special.lastIndex = pos;
6989
- var m = special.exec(text);
6990
- var skipped = m ? m.index - pos : text.length - pos;
6991
- if (skipped) {
6992
- var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
6993
- if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
6994
- else content.appendChild(txt);
6995
- builder.map.push(builder.pos, builder.pos + skipped, txt);
6996
- builder.col += skipped;
6997
- builder.pos += skipped;
6998
- }
6999
- if (!m) break;
7000
- pos += skipped + 1;
7001
- if (m[0] == "\t") {
7002
- var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
7003
- var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
7004
- txt.setAttribute("role", "presentation");
7005
- txt.setAttribute("cm-text", "\t");
7006
- builder.col += tabWidth;
7007
- } else if (m[0] == "\r" || m[0] == "\n") {
7008
- var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
7009
- txt.setAttribute("cm-text", m[0]);
7010
- builder.col += 1;
7011
- } else {
7012
- var txt = builder.cm.options.specialCharPlaceholder(m[0]);
7013
- txt.setAttribute("cm-text", m[0]);
7014
- if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
7015
- else content.appendChild(txt);
7016
- builder.col += 1;
7017
- }
7018
- builder.map.push(builder.pos, builder.pos + 1, txt);
7019
- builder.pos++;
7020
- }
7021
- }
7022
- if (style || startStyle || endStyle || mustWrap || css) {
7023
- var fullStyle = style || "";
7024
- if (startStyle) fullStyle += startStyle;
7025
- if (endStyle) fullStyle += endStyle;
7026
- var token = elt("span", [content], fullStyle, css);
7027
- if (title) token.title = title;
7028
- return builder.content.appendChild(token);
7029
- }
7030
- builder.content.appendChild(content);
7031
- }
7032
-
7033
- function splitSpaces(old) {
7034
- var out = " ";
7035
- for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
7036
- out += " ";
7037
- return out;
7038
- }
7039
-
7040
- // Work around nonsense dimensions being reported for stretches of
7041
- // right-to-left text.
7042
- function buildTokenBadBidi(inner, order) {
7043
- return function(builder, text, style, startStyle, endStyle, title, css) {
7044
- style = style ? style + " cm-force-border" : "cm-force-border";
7045
- var start = builder.pos, end = start + text.length;
7046
- for (;;) {
7047
- // Find the part that overlaps with the start of this text
7048
- for (var i = 0; i < order.length; i++) {
7049
- var part = order[i];
7050
- if (part.to > start && part.from <= start) break;
7051
- }
7052
- if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
7053
- inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
7054
- startStyle = null;
7055
- text = text.slice(part.to - start);
7056
- start = part.to;
7057
- }
7058
- };
7059
- }
7060
-
7061
- function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
7062
- var widget = !ignoreWidget && marker.widgetNode;
7063
- if (widget) builder.map.push(builder.pos, builder.pos + size, widget);
7064
- if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
7065
- if (!widget)
7066
- widget = builder.content.appendChild(document.createElement("span"));
7067
- widget.setAttribute("cm-marker", marker.id);
7068
- }
7069
- if (widget) {
7070
- builder.cm.display.input.setUneditable(widget);
7071
- builder.content.appendChild(widget);
7072
- }
7073
- builder.pos += size;
7074
- }
7075
-
7076
- // Outputs a number of spans to make up a line, taking highlighting
7077
- // and marked text into account.
7078
- function insertLineContent(line, builder, styles) {
7079
- var spans = line.markedSpans, allText = line.text, at = 0;
7080
- if (!spans) {
7081
- for (var i = 1; i < styles.length; i+=2)
7082
- builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));
7083
- return;
7084
- }
7085
-
7086
- var len = allText.length, pos = 0, i = 1, text = "", style, css;
7087
- var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
7088
- for (;;) {
7089
- if (nextChange == pos) { // Update current marker set
7090
- spanStyle = spanEndStyle = spanStartStyle = title = css = "";
7091
- collapsed = null; nextChange = Infinity;
7092
- var foundBookmarks = [], endStyles
7093
- for (var j = 0; j < spans.length; ++j) {
7094
- var sp = spans[j], m = sp.marker;
7095
- if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
7096
- foundBookmarks.push(m);
7097
- } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
7098
- if (sp.to != null && sp.to != pos && nextChange > sp.to) {
7099
- nextChange = sp.to;
7100
- spanEndStyle = "";
7101
- }
7102
- if (m.className) spanStyle += " " + m.className;
7103
- if (m.css) css = (css ? css + ";" : "") + m.css;
7104
- if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
7105
- if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to)
7106
- if (m.title && !title) title = m.title;
7107
- if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
7108
- collapsed = sp;
7109
- } else if (sp.from > pos && nextChange > sp.from) {
7110
- nextChange = sp.from;
7111
- }
7112
- }
7113
- if (endStyles) for (var j = 0; j < endStyles.length; j += 2)
7114
- if (endStyles[j + 1] == nextChange) spanEndStyle += " " + endStyles[j]
7115
-
7116
- if (collapsed && (collapsed.from || 0) == pos) {
7117
- buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
7118
- collapsed.marker, collapsed.from == null);
7119
- if (collapsed.to == null) return;
7120
- if (collapsed.to == pos) collapsed = false;
7121
- }
7122
- if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
7123
- buildCollapsedSpan(builder, 0, foundBookmarks[j]);
7124
- }
7125
- if (pos >= len) break;
7126
-
7127
- var upto = Math.min(len, nextChange);
7128
- while (true) {
7129
- if (text) {
7130
- var end = pos + text.length;
7131
- if (!collapsed) {
7132
- var tokenText = end > upto ? text.slice(0, upto - pos) : text;
7133
- builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
7134
- spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);
7135
- }
7136
- if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
7137
- pos = end;
7138
- spanStartStyle = "";
7139
- }
7140
- text = allText.slice(at, at = styles[i++]);
7141
- style = interpretTokenStyle(styles[i++], builder.cm.options);
7142
- }
7143
- }
7144
- }
7145
-
7146
- // DOCUMENT DATA STRUCTURE
7147
-
7148
- // By default, updates that start and end at the beginning of a line
7149
- // are treated specially, in order to make the association of line
7150
- // widgets and marker elements with the text behave more intuitive.
7151
- function isWholeLineUpdate(doc, change) {
7152
- return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
7153
- (!doc.cm || doc.cm.options.wholeLineUpdateBefore);
7154
- }
7155
-
7156
- // Perform a change on the document data structure.
7157
- function updateDoc(doc, change, markedSpans, estimateHeight) {
7158
- function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
7159
- function update(line, text, spans) {
7160
- updateLine(line, text, spans, estimateHeight);
7161
- signalLater(line, "change", line, change);
7162
- }
7163
- function linesFor(start, end) {
7164
- for (var i = start, result = []; i < end; ++i)
7165
- result.push(new Line(text[i], spansFor(i), estimateHeight));
7166
- return result;
7167
- }
7168
-
7169
- var from = change.from, to = change.to, text = change.text;
7170
- var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
7171
- var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
7172
-
7173
- // Adjust the line structure
7174
- if (change.full) {
7175
- doc.insert(0, linesFor(0, text.length));
7176
- doc.remove(text.length, doc.size - text.length);
7177
- } else if (isWholeLineUpdate(doc, change)) {
7178
- // This is a whole-line replace. Treated specially to make
7179
- // sure line objects move the way they are supposed to.
7180
- var added = linesFor(0, text.length - 1);
7181
- update(lastLine, lastLine.text, lastSpans);
7182
- if (nlines) doc.remove(from.line, nlines);
7183
- if (added.length) doc.insert(from.line, added);
7184
- } else if (firstLine == lastLine) {
7185
- if (text.length == 1) {
7186
- update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
7187
- } else {
7188
- var added = linesFor(1, text.length - 1);
7189
- added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
7190
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
7191
- doc.insert(from.line + 1, added);
7192
- }
7193
- } else if (text.length == 1) {
7194
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
7195
- doc.remove(from.line + 1, nlines);
7196
- } else {
7197
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
7198
- update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
7199
- var added = linesFor(1, text.length - 1);
7200
- if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
7201
- doc.insert(from.line + 1, added);
7202
- }
7203
-
7204
- signalLater(doc, "change", doc, change);
7205
- }
7206
-
7207
- // The document is represented as a BTree consisting of leaves, with
7208
- // chunk of lines in them, and branches, with up to ten leaves or
7209
- // other branch nodes below them. The top node is always a branch
7210
- // node, and is the document object itself (meaning it has
7211
- // additional methods and properties).
7212
- //
7213
- // All nodes have parent links. The tree is used both to go from
7214
- // line numbers to line objects, and to go from objects to numbers.
7215
- // It also indexes by height, and is used to convert between height
7216
- // and line object, and to find the total height of the document.
7217
- //
7218
- // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
7219
-
7220
- function LeafChunk(lines) {
7221
- this.lines = lines;
7222
- this.parent = null;
7223
- for (var i = 0, height = 0; i < lines.length; ++i) {
7224
- lines[i].parent = this;
7225
- height += lines[i].height;
7226
- }
7227
- this.height = height;
7228
- }
7229
-
7230
- LeafChunk.prototype = {
7231
- chunkSize: function() { return this.lines.length; },
7232
- // Remove the n lines at offset 'at'.
7233
- removeInner: function(at, n) {
7234
- for (var i = at, e = at + n; i < e; ++i) {
7235
- var line = this.lines[i];
7236
- this.height -= line.height;
7237
- cleanUpLine(line);
7238
- signalLater(line, "delete");
7239
- }
7240
- this.lines.splice(at, n);
7241
- },
7242
- // Helper used to collapse a small branch into a single leaf.
7243
- collapse: function(lines) {
7244
- lines.push.apply(lines, this.lines);
7245
- },
7246
- // Insert the given array of lines at offset 'at', count them as
7247
- // having the given height.
7248
- insertInner: function(at, lines, height) {
7249
- this.height += height;
7250
- this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
7251
- for (var i = 0; i < lines.length; ++i) lines[i].parent = this;
7252
- },
7253
- // Used to iterate over a part of the tree.
7254
- iterN: function(at, n, op) {
7255
- for (var e = at + n; at < e; ++at)
7256
- if (op(this.lines[at])) return true;
7257
- }
7258
- };
7259
-
7260
- function BranchChunk(children) {
7261
- this.children = children;
7262
- var size = 0, height = 0;
7263
- for (var i = 0; i < children.length; ++i) {
7264
- var ch = children[i];
7265
- size += ch.chunkSize(); height += ch.height;
7266
- ch.parent = this;
7267
- }
7268
- this.size = size;
7269
- this.height = height;
7270
- this.parent = null;
7271
- }
7272
-
7273
- BranchChunk.prototype = {
7274
- chunkSize: function() { return this.size; },
7275
- removeInner: function(at, n) {
7276
- this.size -= n;
7277
- for (var i = 0; i < this.children.length; ++i) {
7278
- var child = this.children[i], sz = child.chunkSize();
7279
- if (at < sz) {
7280
- var rm = Math.min(n, sz - at), oldHeight = child.height;
7281
- child.removeInner(at, rm);
7282
- this.height -= oldHeight - child.height;
7283
- if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
7284
- if ((n -= rm) == 0) break;
7285
- at = 0;
7286
- } else at -= sz;
7287
- }
7288
- // If the result is smaller than 25 lines, ensure that it is a
7289
- // single leaf node.
7290
- if (this.size - n < 25 &&
7291
- (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
7292
- var lines = [];
7293
- this.collapse(lines);
7294
- this.children = [new LeafChunk(lines)];
7295
- this.children[0].parent = this;
7296
- }
7297
- },
7298
- collapse: function(lines) {
7299
- for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);
7300
- },
7301
- insertInner: function(at, lines, height) {
7302
- this.size += lines.length;
7303
- this.height += height;
7304
- for (var i = 0; i < this.children.length; ++i) {
7305
- var child = this.children[i], sz = child.chunkSize();
7306
- if (at <= sz) {
7307
- child.insertInner(at, lines, height);
7308
- if (child.lines && child.lines.length > 50) {
7309
- while (child.lines.length > 50) {
7310
- var spilled = child.lines.splice(child.lines.length - 25, 25);
7311
- var newleaf = new LeafChunk(spilled);
7312
- child.height -= newleaf.height;
7313
- this.children.splice(i + 1, 0, newleaf);
7314
- newleaf.parent = this;
7315
- }
7316
- this.maybeSpill();
7317
- }
7318
- break;
7319
- }
7320
- at -= sz;
7321
- }
7322
- },
7323
- // When a node has grown, check whether it should be split.
7324
- maybeSpill: function() {
7325
- if (this.children.length <= 10) return;
7326
- var me = this;
7327
- do {
7328
- var spilled = me.children.splice(me.children.length - 5, 5);
7329
- var sibling = new BranchChunk(spilled);
7330
- if (!me.parent) { // Become the parent node
7331
- var copy = new BranchChunk(me.children);
7332
- copy.parent = me;
7333
- me.children = [copy, sibling];
7334
- me = copy;
7335
- } else {
7336
- me.size -= sibling.size;
7337
- me.height -= sibling.height;
7338
- var myIndex = indexOf(me.parent.children, me);
7339
- me.parent.children.splice(myIndex + 1, 0, sibling);
7340
- }
7341
- sibling.parent = me.parent;
7342
- } while (me.children.length > 10);
7343
- me.parent.maybeSpill();
7344
- },
7345
- iterN: function(at, n, op) {
7346
- for (var i = 0; i < this.children.length; ++i) {
7347
- var child = this.children[i], sz = child.chunkSize();
7348
- if (at < sz) {
7349
- var used = Math.min(n, sz - at);
7350
- if (child.iterN(at, used, op)) return true;
7351
- if ((n -= used) == 0) break;
7352
- at = 0;
7353
- } else at -= sz;
7354
- }
7355
- }
7356
- };
7357
-
7358
- var nextDocId = 0;
7359
- var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) {
7360
- if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep);
7361
- if (firstLine == null) firstLine = 0;
7362
-
7363
- BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
7364
- this.first = firstLine;
7365
- this.scrollTop = this.scrollLeft = 0;
7366
- this.cantEdit = false;
7367
- this.cleanGeneration = 1;
7368
- this.frontier = firstLine;
7369
- var start = Pos(firstLine, 0);
7370
- this.sel = simpleSelection(start);
7371
- this.history = new History(null);
7372
- this.id = ++nextDocId;
7373
- this.modeOption = mode;
7374
- this.lineSep = lineSep;
7375
- this.extend = false;
7376
-
7377
- if (typeof text == "string") text = this.splitLines(text);
7378
- updateDoc(this, {from: start, to: start, text: text});
7379
- setSelection(this, simpleSelection(start), sel_dontScroll);
7380
- };
7381
-
7382
- Doc.prototype = createObj(BranchChunk.prototype, {
7383
- constructor: Doc,
7384
- // Iterate over the document. Supports two forms -- with only one
7385
- // argument, it calls that for each line in the document. With
7386
- // three, it iterates over the range given by the first two (with
7387
- // the second being non-inclusive).
7388
- iter: function(from, to, op) {
7389
- if (op) this.iterN(from - this.first, to - from, op);
7390
- else this.iterN(this.first, this.first + this.size, from);
7391
- },
7392
-
7393
- // Non-public interface for adding and removing lines.
7394
- insert: function(at, lines) {
7395
- var height = 0;
7396
- for (var i = 0; i < lines.length; ++i) height += lines[i].height;
7397
- this.insertInner(at - this.first, lines, height);
7398
- },
7399
- remove: function(at, n) { this.removeInner(at - this.first, n); },
7400
-
7401
- // From here, the methods are part of the public interface. Most
7402
- // are also available from CodeMirror (editor) instances.
7403
-
7404
- getValue: function(lineSep) {
7405
- var lines = getLines(this, this.first, this.first + this.size);
7406
- if (lineSep === false) return lines;
7407
- return lines.join(lineSep || this.lineSeparator());
7408
- },
7409
- setValue: docMethodOp(function(code) {
7410
- var top = Pos(this.first, 0), last = this.first + this.size - 1;
7411
- makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
7412
- text: this.splitLines(code), origin: "setValue", full: true}, true);
7413
- setSelection(this, simpleSelection(top));
7414
- }),
7415
- replaceRange: function(code, from, to, origin) {
7416
- from = clipPos(this, from);
7417
- to = to ? clipPos(this, to) : from;
7418
- replaceRange(this, code, from, to, origin);
7419
- },
7420
- getRange: function(from, to, lineSep) {
7421
- var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
7422
- if (lineSep === false) return lines;
7423
- return lines.join(lineSep || this.lineSeparator());
7424
- },
7425
-
7426
- getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
7427
-
7428
- getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
7429
- getLineNumber: function(line) {return lineNo(line);},
7430
-
7431
- getLineHandleVisualStart: function(line) {
7432
- if (typeof line == "number") line = getLine(this, line);
7433
- return visualLine(line);
7434
- },
7435
-
7436
- lineCount: function() {return this.size;},
7437
- firstLine: function() {return this.first;},
7438
- lastLine: function() {return this.first + this.size - 1;},
7439
-
7440
- clipPos: function(pos) {return clipPos(this, pos);},
7441
-
7442
- getCursor: function(start) {
7443
- var range = this.sel.primary(), pos;
7444
- if (start == null || start == "head") pos = range.head;
7445
- else if (start == "anchor") pos = range.anchor;
7446
- else if (start == "end" || start == "to" || start === false) pos = range.to();
7447
- else pos = range.from();
7448
- return pos;
7449
- },
7450
- listSelections: function() { return this.sel.ranges; },
7451
- somethingSelected: function() {return this.sel.somethingSelected();},
7452
-
7453
- setCursor: docMethodOp(function(line, ch, options) {
7454
- setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
7455
- }),
7456
- setSelection: docMethodOp(function(anchor, head, options) {
7457
- setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
7458
- }),
7459
- extendSelection: docMethodOp(function(head, other, options) {
7460
- extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
7461
- }),
7462
- extendSelections: docMethodOp(function(heads, options) {
7463
- extendSelections(this, clipPosArray(this, heads), options);
7464
- }),
7465
- extendSelectionsBy: docMethodOp(function(f, options) {
7466
- var heads = map(this.sel.ranges, f);
7467
- extendSelections(this, clipPosArray(this, heads), options);
7468
- }),
7469
- setSelections: docMethodOp(function(ranges, primary, options) {
7470
- if (!ranges.length) return;
7471
- for (var i = 0, out = []; i < ranges.length; i++)
7472
- out[i] = new Range(clipPos(this, ranges[i].anchor),
7473
- clipPos(this, ranges[i].head));
7474
- if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);
7475
- setSelection(this, normalizeSelection(out, primary), options);
7476
- }),
7477
- addSelection: docMethodOp(function(anchor, head, options) {
7478
- var ranges = this.sel.ranges.slice(0);
7479
- ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
7480
- setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);
7481
- }),
7482
-
7483
- getSelection: function(lineSep) {
7484
- var ranges = this.sel.ranges, lines;
7485
- for (var i = 0; i < ranges.length; i++) {
7486
- var sel = getBetween(this, ranges[i].from(), ranges[i].to());
7487
- lines = lines ? lines.concat(sel) : sel;
7488
- }
7489
- if (lineSep === false) return lines;
7490
- else return lines.join(lineSep || this.lineSeparator());
7491
- },
7492
- getSelections: function(lineSep) {
7493
- var parts = [], ranges = this.sel.ranges;
7494
- for (var i = 0; i < ranges.length; i++) {
7495
- var sel = getBetween(this, ranges[i].from(), ranges[i].to());
7496
- if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator());
7497
- parts[i] = sel;
7498
- }
7499
- return parts;
7500
- },
7501
- replaceSelection: function(code, collapse, origin) {
7502
- var dup = [];
7503
- for (var i = 0; i < this.sel.ranges.length; i++)
7504
- dup[i] = code;
7505
- this.replaceSelections(dup, collapse, origin || "+input");
7506
- },
7507
- replaceSelections: docMethodOp(function(code, collapse, origin) {
7508
- var changes = [], sel = this.sel;
7509
- for (var i = 0; i < sel.ranges.length; i++) {
7510
- var range = sel.ranges[i];
7511
- changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
7512
- }
7513
- var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
7514
- for (var i = changes.length - 1; i >= 0; i--)
7515
- makeChange(this, changes[i]);
7516
- if (newSel) setSelectionReplaceHistory(this, newSel);
7517
- else if (this.cm) ensureCursorVisible(this.cm);
7518
- }),
7519
- undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
7520
- redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
7521
- undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
7522
- redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
7523
-
7524
- setExtending: function(val) {this.extend = val;},
7525
- getExtending: function() {return this.extend;},
7526
-
7527
- historySize: function() {
7528
- var hist = this.history, done = 0, undone = 0;
7529
- for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;
7530
- for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;
7531
- return {undo: done, redo: undone};
7532
- },
7533
- clearHistory: function() {this.history = new History(this.history.maxGeneration);},
7534
-
7535
- markClean: function() {
7536
- this.cleanGeneration = this.changeGeneration(true);
7537
- },
7538
- changeGeneration: function(forceSplit) {
7539
- if (forceSplit)
7540
- this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;
7541
- return this.history.generation;
7542
- },
7543
- isClean: function (gen) {
7544
- return this.history.generation == (gen || this.cleanGeneration);
7545
- },
7546
-
7547
- getHistory: function() {
7548
- return {done: copyHistoryArray(this.history.done),
7549
- undone: copyHistoryArray(this.history.undone)};
7550
- },
7551
- setHistory: function(histData) {
7552
- var hist = this.history = new History(this.history.maxGeneration);
7553
- hist.done = copyHistoryArray(histData.done.slice(0), null, true);
7554
- hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
7555
- },
7556
-
7557
- addLineClass: docMethodOp(function(handle, where, cls) {
7558
- return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
7559
- var prop = where == "text" ? "textClass"
7560
- : where == "background" ? "bgClass"
7561
- : where == "gutter" ? "gutterClass" : "wrapClass";
7562
- if (!line[prop]) line[prop] = cls;
7563
- else if (classTest(cls).test(line[prop])) return false;
7564
- else line[prop] += " " + cls;
7565
- return true;
7566
- });
7567
- }),
7568
- removeLineClass: docMethodOp(function(handle, where, cls) {
7569
- return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
7570
- var prop = where == "text" ? "textClass"
7571
- : where == "background" ? "bgClass"
7572
- : where == "gutter" ? "gutterClass" : "wrapClass";
7573
- var cur = line[prop];
7574
- if (!cur) return false;
7575
- else if (cls == null) line[prop] = null;
7576
- else {
7577
- var found = cur.match(classTest(cls));
7578
- if (!found) return false;
7579
- var end = found.index + found[0].length;
7580
- line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
7581
- }
7582
- return true;
7583
- });
7584
- }),
7585
-
7586
- addLineWidget: docMethodOp(function(handle, node, options) {
7587
- return addLineWidget(this, handle, node, options);
7588
- }),
7589
- removeLineWidget: function(widget) { widget.clear(); },
7590
-
7591
- markText: function(from, to, options) {
7592
- return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range");
7593
- },
7594
- setBookmark: function(pos, options) {
7595
- var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
7596
- insertLeft: options && options.insertLeft,
7597
- clearWhenEmpty: false, shared: options && options.shared,
7598
- handleMouseEvents: options && options.handleMouseEvents};
7599
- pos = clipPos(this, pos);
7600
- return markText(this, pos, pos, realOpts, "bookmark");
7601
- },
7602
- findMarksAt: function(pos) {
7603
- pos = clipPos(this, pos);
7604
- var markers = [], spans = getLine(this, pos.line).markedSpans;
7605
- if (spans) for (var i = 0; i < spans.length; ++i) {
7606
- var span = spans[i];
7607
- if ((span.from == null || span.from <= pos.ch) &&
7608
- (span.to == null || span.to >= pos.ch))
7609
- markers.push(span.marker.parent || span.marker);
7610
- }
7611
- return markers;
7612
- },
7613
- findMarks: function(from, to, filter) {
7614
- from = clipPos(this, from); to = clipPos(this, to);
7615
- var found = [], lineNo = from.line;
7616
- this.iter(from.line, to.line + 1, function(line) {
7617
- var spans = line.markedSpans;
7618
- if (spans) for (var i = 0; i < spans.length; i++) {
7619
- var span = spans[i];
7620
- if (!(lineNo == from.line && from.ch > span.to ||
7621
- span.from == null && lineNo != from.line||
7622
- lineNo == to.line && span.from > to.ch) &&
7623
- (!filter || filter(span.marker)))
7624
- found.push(span.marker.parent || span.marker);
7625
- }
7626
- ++lineNo;
7627
- });
7628
- return found;
7629
- },
7630
- getAllMarks: function() {
7631
- var markers = [];
7632
- this.iter(function(line) {
7633
- var sps = line.markedSpans;
7634
- if (sps) for (var i = 0; i < sps.length; ++i)
7635
- if (sps[i].from != null) markers.push(sps[i].marker);
7636
- });
7637
- return markers;
7638
- },
7639
-
7640
- posFromIndex: function(off) {
7641
- var ch, lineNo = this.first;
7642
- this.iter(function(line) {
7643
- var sz = line.text.length + 1;
7644
- if (sz > off) { ch = off; return true; }
7645
- off -= sz;
7646
- ++lineNo;
7647
- });
7648
- return clipPos(this, Pos(lineNo, ch));
7649
- },
7650
- indexFromPos: function (coords) {
7651
- coords = clipPos(this, coords);
7652
- var index = coords.ch;
7653
- if (coords.line < this.first || coords.ch < 0) return 0;
7654
- this.iter(this.first, coords.line, function (line) {
7655
- index += line.text.length + 1;
7656
- });
7657
- return index;
7658
- },
7659
-
7660
- copy: function(copyHistory) {
7661
- var doc = new Doc(getLines(this, this.first, this.first + this.size),
7662
- this.modeOption, this.first, this.lineSep);
7663
- doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
7664
- doc.sel = this.sel;
7665
- doc.extend = false;
7666
- if (copyHistory) {
7667
- doc.history.undoDepth = this.history.undoDepth;
7668
- doc.setHistory(this.getHistory());
7669
- }
7670
- return doc;
7671
- },
7672
-
7673
- linkedDoc: function(options) {
7674
- if (!options) options = {};
7675
- var from = this.first, to = this.first + this.size;
7676
- if (options.from != null && options.from > from) from = options.from;
7677
- if (options.to != null && options.to < to) to = options.to;
7678
- var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep);
7679
- if (options.sharedHist) copy.history = this.history;
7680
- (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
7681
- copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
7682
- copySharedMarkers(copy, findSharedMarkers(this));
7683
- return copy;
7684
- },
7685
- unlinkDoc: function(other) {
7686
- if (other instanceof CodeMirror) other = other.doc;
7687
- if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
7688
- var link = this.linked[i];
7689
- if (link.doc != other) continue;
7690
- this.linked.splice(i, 1);
7691
- other.unlinkDoc(this);
7692
- detachSharedMarkers(findSharedMarkers(this));
7693
- break;
7694
- }
7695
- // If the histories were shared, split them again
7696
- if (other.history == this.history) {
7697
- var splitIds = [other.id];
7698
- linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
7699
- other.history = new History(null);
7700
- other.history.done = copyHistoryArray(this.history.done, splitIds);
7701
- other.history.undone = copyHistoryArray(this.history.undone, splitIds);
7702
- }
7703
- },
7704
- iterLinkedDocs: function(f) {linkedDocs(this, f);},
7705
-
7706
- getMode: function() {return this.mode;},
7707
- getEditor: function() {return this.cm;},
7708
-
7709
- splitLines: function(str) {
7710
- if (this.lineSep) return str.split(this.lineSep);
7711
- return splitLinesAuto(str);
7712
- },
7713
- lineSeparator: function() { return this.lineSep || "\n"; }
7714
- });
7715
-
7716
- // Public alias.
7717
- Doc.prototype.eachLine = Doc.prototype.iter;
7718
-
7719
- // Set up methods on CodeMirror's prototype to redirect to the editor's document.
7720
- var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
7721
- for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
7722
- CodeMirror.prototype[prop] = (function(method) {
7723
- return function() {return method.apply(this.doc, arguments);};
7724
- })(Doc.prototype[prop]);
7725
-
7726
- eventMixin(Doc);
7727
-
7728
- // Call f for all linked documents.
7729
- function linkedDocs(doc, f, sharedHistOnly) {
7730
- function propagate(doc, skip, sharedHist) {
7731
- if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
7732
- var rel = doc.linked[i];
7733
- if (rel.doc == skip) continue;
7734
- var shared = sharedHist && rel.sharedHist;
7735
- if (sharedHistOnly && !shared) continue;
7736
- f(rel.doc, shared);
7737
- propagate(rel.doc, doc, shared);
7738
- }
7739
- }
7740
- propagate(doc, null, true);
7741
- }
7742
-
7743
- // Attach a document to an editor.
7744
- function attachDoc(cm, doc) {
7745
- if (doc.cm) throw new Error("This document is already in use.");
7746
- cm.doc = doc;
7747
- doc.cm = cm;
7748
- estimateLineHeights(cm);
7749
- loadMode(cm);
7750
- if (!cm.options.lineWrapping) findMaxLine(cm);
7751
- cm.options.mode = doc.modeOption;
7752
- regChange(cm);
7753
- }
7754
-
7755
- // LINE UTILITIES
7756
-
7757
- // Find the line object corresponding to the given line number.
7758
- function getLine(doc, n) {
7759
- n -= doc.first;
7760
- if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");
7761
- for (var chunk = doc; !chunk.lines;) {
7762
- for (var i = 0;; ++i) {
7763
- var child = chunk.children[i], sz = child.chunkSize();
7764
- if (n < sz) { chunk = child; break; }
7765
- n -= sz;
7766
- }
7767
- }
7768
- return chunk.lines[n];
7769
- }
7770
-
7771
- // Get the part of a document between two positions, as an array of
7772
- // strings.
7773
- function getBetween(doc, start, end) {
7774
- var out = [], n = start.line;
7775
- doc.iter(start.line, end.line + 1, function(line) {
7776
- var text = line.text;
7777
- if (n == end.line) text = text.slice(0, end.ch);
7778
- if (n == start.line) text = text.slice(start.ch);
7779
- out.push(text);
7780
- ++n;
7781
- });
7782
- return out;
7783
- }
7784
- // Get the lines between from and to, as array of strings.
7785
- function getLines(doc, from, to) {
7786
- var out = [];
7787
- doc.iter(from, to, function(line) { out.push(line.text); });
7788
- return out;
7789
- }
7790
-
7791
- // Update the height of a line, propagating the height change
7792
- // upwards to parent nodes.
7793
- function updateLineHeight(line, height) {
7794
- var diff = height - line.height;
7795
- if (diff) for (var n = line; n; n = n.parent) n.height += diff;
7796
- }
7797
-
7798
- // Given a line object, find its line number by walking up through
7799
- // its parent links.
7800
- function lineNo(line) {
7801
- if (line.parent == null) return null;
7802
- var cur = line.parent, no = indexOf(cur.lines, line);
7803
- for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
7804
- for (var i = 0;; ++i) {
7805
- if (chunk.children[i] == cur) break;
7806
- no += chunk.children[i].chunkSize();
7807
- }
7808
- }
7809
- return no + cur.first;
7810
- }
7811
-
7812
- // Find the line at the given vertical position, using the height
7813
- // information in the document tree.
7814
- function lineAtHeight(chunk, h) {
7815
- var n = chunk.first;
7816
- outer: do {
7817
- for (var i = 0; i < chunk.children.length; ++i) {
7818
- var child = chunk.children[i], ch = child.height;
7819
- if (h < ch) { chunk = child; continue outer; }
7820
- h -= ch;
7821
- n += child.chunkSize();
7822
- }
7823
- return n;
7824
- } while (!chunk.lines);
7825
- for (var i = 0; i < chunk.lines.length; ++i) {
7826
- var line = chunk.lines[i], lh = line.height;
7827
- if (h < lh) break;
7828
- h -= lh;
7829
- }
7830
- return n + i;
7831
- }
7832
-
7833
-
7834
- // Find the height above the given line.
7835
- function heightAtLine(lineObj) {
7836
- lineObj = visualLine(lineObj);
7837
-
7838
- var h = 0, chunk = lineObj.parent;
7839
- for (var i = 0; i < chunk.lines.length; ++i) {
7840
- var line = chunk.lines[i];
7841
- if (line == lineObj) break;
7842
- else h += line.height;
7843
- }
7844
- for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
7845
- for (var i = 0; i < p.children.length; ++i) {
7846
- var cur = p.children[i];
7847
- if (cur == chunk) break;
7848
- else h += cur.height;
7849
- }
7850
- }
7851
- return h;
7852
- }
7853
-
7854
- // Get the bidi ordering for the given line (and cache it). Returns
7855
- // false for lines that are fully left-to-right, and an array of
7856
- // BidiSpan objects otherwise.
7857
- function getOrder(line) {
7858
- var order = line.order;
7859
- if (order == null) order = line.order = bidiOrdering(line.text);
7860
- return order;
7861
- }
7862
-
7863
- // HISTORY
7864
-
7865
- function History(startGen) {
7866
- // Arrays of change events and selections. Doing something adds an
7867
- // event to done and clears undo. Undoing moves events from done
7868
- // to undone, redoing moves them in the other direction.
7869
- this.done = []; this.undone = [];
7870
- this.undoDepth = Infinity;
7871
- // Used to track when changes can be merged into a single undo
7872
- // event
7873
- this.lastModTime = this.lastSelTime = 0;
7874
- this.lastOp = this.lastSelOp = null;
7875
- this.lastOrigin = this.lastSelOrigin = null;
7876
- // Used by the isClean() method
7877
- this.generation = this.maxGeneration = startGen || 1;
7878
- }
7879
-
7880
- // Create a history change event from an updateDoc-style change
7881
- // object.
7882
- function historyChangeFromChange(doc, change) {
7883
- var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
7884
- attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
7885
- linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
7886
- return histChange;
7887
- }
7888
-
7889
- // Pop all selection events off the end of a history array. Stop at
7890
- // a change event.
7891
- function clearSelectionEvents(array) {
7892
- while (array.length) {
7893
- var last = lst(array);
7894
- if (last.ranges) array.pop();
7895
- else break;
7896
- }
7897
- }
7898
-
7899
- // Find the top change event in the history. Pop off selection
7900
- // events that are in the way.
7901
- function lastChangeEvent(hist, force) {
7902
- if (force) {
7903
- clearSelectionEvents(hist.done);
7904
- return lst(hist.done);
7905
- } else if (hist.done.length && !lst(hist.done).ranges) {
7906
- return lst(hist.done);
7907
- } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
7908
- hist.done.pop();
7909
- return lst(hist.done);
7910
- }
7911
- }
7912
-
7913
- // Register a change in the history. Merges changes that are within
7914
- // a single operation, ore are close together with an origin that
7915
- // allows merging (starting with "+") into a single event.
7916
- function addChangeToHistory(doc, change, selAfter, opId) {
7917
- var hist = doc.history;
7918
- hist.undone.length = 0;
7919
- var time = +new Date, cur;
7920
-
7921
- if ((hist.lastOp == opId ||
7922
- hist.lastOrigin == change.origin && change.origin &&
7923
- ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
7924
- change.origin.charAt(0) == "*")) &&
7925
- (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
7926
- // Merge this change into the last event
7927
- var last = lst(cur.changes);
7928
- if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
7929
- // Optimized case for simple insertion -- don't want to add
7930
- // new changesets for every character typed
7931
- last.to = changeEnd(change);
7932
- } else {
7933
- // Add new sub-event
7934
- cur.changes.push(historyChangeFromChange(doc, change));
7935
- }
7936
- } else {
7937
- // Can not be merged, start a new event.
7938
- var before = lst(hist.done);
7939
- if (!before || !before.ranges)
7940
- pushSelectionToHistory(doc.sel, hist.done);
7941
- cur = {changes: [historyChangeFromChange(doc, change)],
7942
- generation: hist.generation};
7943
- hist.done.push(cur);
7944
- while (hist.done.length > hist.undoDepth) {
7945
- hist.done.shift();
7946
- if (!hist.done[0].ranges) hist.done.shift();
7947
- }
7948
- }
7949
- hist.done.push(selAfter);
7950
- hist.generation = ++hist.maxGeneration;
7951
- hist.lastModTime = hist.lastSelTime = time;
7952
- hist.lastOp = hist.lastSelOp = opId;
7953
- hist.lastOrigin = hist.lastSelOrigin = change.origin;
7954
-
7955
- if (!last) signal(doc, "historyAdded");
7956
- }
7957
-
7958
- function selectionEventCanBeMerged(doc, origin, prev, sel) {
7959
- var ch = origin.charAt(0);
7960
- return ch == "*" ||
7961
- ch == "+" &&
7962
- prev.ranges.length == sel.ranges.length &&
7963
- prev.somethingSelected() == sel.somethingSelected() &&
7964
- new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
7965
- }
7966
-
7967
- // Called whenever the selection changes, sets the new selection as
7968
- // the pending selection in the history, and pushes the old pending
7969
- // selection into the 'done' array when it was significantly
7970
- // different (in number of selected ranges, emptiness, or time).
7971
- function addSelectionToHistory(doc, sel, opId, options) {
7972
- var hist = doc.history, origin = options && options.origin;
7973
-
7974
- // A new event is started when the previous origin does not match
7975
- // the current, or the origins don't allow matching. Origins
7976
- // starting with * are always merged, those starting with + are
7977
- // merged when similar and close together in time.
7978
- if (opId == hist.lastSelOp ||
7979
- (origin && hist.lastSelOrigin == origin &&
7980
- (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
7981
- selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
7982
- hist.done[hist.done.length - 1] = sel;
7983
- else
7984
- pushSelectionToHistory(sel, hist.done);
7985
-
7986
- hist.lastSelTime = +new Date;
7987
- hist.lastSelOrigin = origin;
7988
- hist.lastSelOp = opId;
7989
- if (options && options.clearRedo !== false)
7990
- clearSelectionEvents(hist.undone);
7991
- }
7992
-
7993
- function pushSelectionToHistory(sel, dest) {
7994
- var top = lst(dest);
7995
- if (!(top && top.ranges && top.equals(sel)))
7996
- dest.push(sel);
7997
- }
7998
-
7999
- // Used to store marked span information in the history.
8000
- function attachLocalSpans(doc, change, from, to) {
8001
- var existing = change["spans_" + doc.id], n = 0;
8002
- doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
8003
- if (line.markedSpans)
8004
- (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
8005
- ++n;
8006
- });
8007
- }
8008
-
8009
- // When un/re-doing restores text containing marked spans, those
8010
- // that have been explicitly cleared should not be restored.
8011
- function removeClearedSpans(spans) {
8012
- if (!spans) return null;
8013
- for (var i = 0, out; i < spans.length; ++i) {
8014
- if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
8015
- else if (out) out.push(spans[i]);
8016
- }
8017
- return !out ? spans : out.length ? out : null;
8018
- }
8019
-
8020
- // Retrieve and filter the old marked spans stored in a change event.
8021
- function getOldSpans(doc, change) {
8022
- var found = change["spans_" + doc.id];
8023
- if (!found) return null;
8024
- for (var i = 0, nw = []; i < change.text.length; ++i)
8025
- nw.push(removeClearedSpans(found[i]));
8026
- return nw;
8027
- }
8028
-
8029
- // Used both to provide a JSON-safe object in .getHistory, and, when
8030
- // detaching a document, to split the history in two
8031
- function copyHistoryArray(events, newGroup, instantiateSel) {
8032
- for (var i = 0, copy = []; i < events.length; ++i) {
8033
- var event = events[i];
8034
- if (event.ranges) {
8035
- copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
8036
- continue;
8037
- }
8038
- var changes = event.changes, newChanges = [];
8039
- copy.push({changes: newChanges});
8040
- for (var j = 0; j < changes.length; ++j) {
8041
- var change = changes[j], m;
8042
- newChanges.push({from: change.from, to: change.to, text: change.text});
8043
- if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
8044
- if (indexOf(newGroup, Number(m[1])) > -1) {
8045
- lst(newChanges)[prop] = change[prop];
8046
- delete change[prop];
8047
- }
8048
- }
8049
- }
8050
- }
8051
- return copy;
8052
- }
8053
-
8054
- // Rebasing/resetting history to deal with externally-sourced changes
8055
-
8056
- function rebaseHistSelSingle(pos, from, to, diff) {
8057
- if (to < pos.line) {
8058
- pos.line += diff;
8059
- } else if (from < pos.line) {
8060
- pos.line = from;
8061
- pos.ch = 0;
8062
- }
8063
- }
8064
-
8065
- // Tries to rebase an array of history events given a change in the
8066
- // document. If the change touches the same lines as the event, the
8067
- // event, and everything 'behind' it, is discarded. If the change is
8068
- // before the event, the event's positions are updated. Uses a
8069
- // copy-on-write scheme for the positions, to avoid having to
8070
- // reallocate them all on every rebase, but also avoid problems with
8071
- // shared position objects being unsafely updated.
8072
- function rebaseHistArray(array, from, to, diff) {
8073
- for (var i = 0; i < array.length; ++i) {
8074
- var sub = array[i], ok = true;
8075
- if (sub.ranges) {
8076
- if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
8077
- for (var j = 0; j < sub.ranges.length; j++) {
8078
- rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
8079
- rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
8080
- }
8081
- continue;
8082
- }
8083
- for (var j = 0; j < sub.changes.length; ++j) {
8084
- var cur = sub.changes[j];
8085
- if (to < cur.from.line) {
8086
- cur.from = Pos(cur.from.line + diff, cur.from.ch);
8087
- cur.to = Pos(cur.to.line + diff, cur.to.ch);
8088
- } else if (from <= cur.to.line) {
8089
- ok = false;
8090
- break;
8091
- }
8092
- }
8093
- if (!ok) {
8094
- array.splice(0, i + 1);
8095
- i = 0;
8096
- }
8097
- }
8098
- }
8099
-
8100
- function rebaseHist(hist, change) {
8101
- var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
8102
- rebaseHistArray(hist.done, from, to, diff);
8103
- rebaseHistArray(hist.undone, from, to, diff);
8104
- }
8105
-
8106
- // EVENT UTILITIES
8107
-
8108
- // Due to the fact that we still support jurassic IE versions, some
8109
- // compatibility wrappers are needed.
8110
-
8111
- var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
8112
- if (e.preventDefault) e.preventDefault();
8113
- else e.returnValue = false;
8114
- };
8115
- var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
8116
- if (e.stopPropagation) e.stopPropagation();
8117
- else e.cancelBubble = true;
8118
- };
8119
- function e_defaultPrevented(e) {
8120
- return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
8121
- }
8122
- var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
8123
-
8124
- function e_target(e) {return e.target || e.srcElement;}
8125
- function e_button(e) {
8126
- var b = e.which;
8127
- if (b == null) {
8128
- if (e.button & 1) b = 1;
8129
- else if (e.button & 2) b = 3;
8130
- else if (e.button & 4) b = 2;
8131
- }
8132
- if (mac && e.ctrlKey && b == 1) b = 3;
8133
- return b;
8134
- }
8135
-
8136
- // EVENT HANDLING
8137
-
8138
- // Lightweight event framework. on/off also work on DOM nodes,
8139
- // registering native DOM handlers.
8140
-
8141
- var on = CodeMirror.on = function(emitter, type, f) {
8142
- if (emitter.addEventListener)
8143
- emitter.addEventListener(type, f, false);
8144
- else if (emitter.attachEvent)
8145
- emitter.attachEvent("on" + type, f);
8146
- else {
8147
- var map = emitter._handlers || (emitter._handlers = {});
8148
- var arr = map[type] || (map[type] = []);
8149
- arr.push(f);
8150
- }
8151
- };
8152
-
8153
- var noHandlers = []
8154
- function getHandlers(emitter, type, copy) {
8155
- var arr = emitter._handlers && emitter._handlers[type]
8156
- if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers
8157
- else return arr || noHandlers
8158
- }
8159
-
8160
- var off = CodeMirror.off = function(emitter, type, f) {
8161
- if (emitter.removeEventListener)
8162
- emitter.removeEventListener(type, f, false);
8163
- else if (emitter.detachEvent)
8164
- emitter.detachEvent("on" + type, f);
8165
- else {
8166
- var handlers = getHandlers(emitter, type, false)
8167
- for (var i = 0; i < handlers.length; ++i)
8168
- if (handlers[i] == f) { handlers.splice(i, 1); break; }
8169
- }
8170
- };
8171
-
8172
- var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
8173
- var handlers = getHandlers(emitter, type, true)
8174
- if (!handlers.length) return;
8175
- var args = Array.prototype.slice.call(arguments, 2);
8176
- for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);
8177
- };
8178
-
8179
- var orphanDelayedCallbacks = null;
8180
-
8181
- // Often, we want to signal events at a point where we are in the
8182
- // middle of some work, but don't want the handler to start calling
8183
- // other methods on the editor, which might be in an inconsistent
8184
- // state or simply not expect any other events to happen.
8185
- // signalLater looks whether there are any handlers, and schedules
8186
- // them to be executed when the last operation ends, or, if no
8187
- // operation is active, when a timeout fires.
8188
- function signalLater(emitter, type /*, values...*/) {
8189
- var arr = getHandlers(emitter, type, false)
8190
- if (!arr.length) return;
8191
- var args = Array.prototype.slice.call(arguments, 2), list;
8192
- if (operationGroup) {
8193
- list = operationGroup.delayedCallbacks;
8194
- } else if (orphanDelayedCallbacks) {
8195
- list = orphanDelayedCallbacks;
8196
- } else {
8197
- list = orphanDelayedCallbacks = [];
8198
- setTimeout(fireOrphanDelayed, 0);
8199
- }
8200
- function bnd(f) {return function(){f.apply(null, args);};};
8201
- for (var i = 0; i < arr.length; ++i)
8202
- list.push(bnd(arr[i]));
8203
- }
8204
-
8205
- function fireOrphanDelayed() {
8206
- var delayed = orphanDelayedCallbacks;
8207
- orphanDelayedCallbacks = null;
8208
- for (var i = 0; i < delayed.length; ++i) delayed[i]();
8209
- }
8210
-
8211
- // The DOM events that CodeMirror handles can be overridden by
8212
- // registering a (non-DOM) handler on the editor for the event name,
8213
- // and preventDefault-ing the event in that handler.
8214
- function signalDOMEvent(cm, e, override) {
8215
- if (typeof e == "string")
8216
- e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
8217
- signal(cm, override || e.type, cm, e);
8218
- return e_defaultPrevented(e) || e.codemirrorIgnore;
8219
- }
8220
-
8221
- function signalCursorActivity(cm) {
8222
- var arr = cm._handlers && cm._handlers.cursorActivity;
8223
- if (!arr) return;
8224
- var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
8225
- for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
8226
- set.push(arr[i]);
8227
- }
8228
-
8229
- function hasHandler(emitter, type) {
8230
- return getHandlers(emitter, type).length > 0
8231
- }
8232
-
8233
- // Add on and off methods to a constructor's prototype, to make
8234
- // registering events on such objects more convenient.
8235
- function eventMixin(ctor) {
8236
- ctor.prototype.on = function(type, f) {on(this, type, f);};
8237
- ctor.prototype.off = function(type, f) {off(this, type, f);};
8238
- }
8239
-
8240
- // MISC UTILITIES
8241
-
8242
- // Number of pixels added to scroller and sizer to hide scrollbar
8243
- var scrollerGap = 30;
8244
-
8245
- // Returned or thrown by various protocols to signal 'I'm not
8246
- // handling this'.
8247
- var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
8248
-
8249
- // Reused option objects for setSelection & friends
8250
- var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
8251
-
8252
- function Delayed() {this.id = null;}
8253
- Delayed.prototype.set = function(ms, f) {
8254
- clearTimeout(this.id);
8255
- this.id = setTimeout(f, ms);
8256
- };
8257
-
8258
- // Counts the column offset in a string, taking tabs into account.
8259
- // Used mostly to find indentation.
8260
- var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
8261
- if (end == null) {
8262
- end = string.search(/[^\s\u00a0]/);
8263
- if (end == -1) end = string.length;
8264
- }
8265
- for (var i = startIndex || 0, n = startValue || 0;;) {
8266
- var nextTab = string.indexOf("\t", i);
8267
- if (nextTab < 0 || nextTab >= end)
8268
- return n + (end - i);
8269
- n += nextTab - i;
8270
- n += tabSize - (n % tabSize);
8271
- i = nextTab + 1;
8272
- }
8273
- };
8274
-
8275
- // The inverse of countColumn -- find the offset that corresponds to
8276
- // a particular column.
8277
- var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) {
8278
- for (var pos = 0, col = 0;;) {
8279
- var nextTab = string.indexOf("\t", pos);
8280
- if (nextTab == -1) nextTab = string.length;
8281
- var skipped = nextTab - pos;
8282
- if (nextTab == string.length || col + skipped >= goal)
8283
- return pos + Math.min(skipped, goal - col);
8284
- col += nextTab - pos;
8285
- col += tabSize - (col % tabSize);
8286
- pos = nextTab + 1;
8287
- if (col >= goal) return pos;
8288
- }
8289
- }
8290
-
8291
- var spaceStrs = [""];
8292
- function spaceStr(n) {
8293
- while (spaceStrs.length <= n)
8294
- spaceStrs.push(lst(spaceStrs) + " ");
8295
- return spaceStrs[n];
8296
- }
8297
-
8298
- function lst(arr) { return arr[arr.length-1]; }
8299
-
8300
- var selectInput = function(node) { node.select(); };
8301
- if (ios) // Mobile Safari apparently has a bug where select() is broken.
8302
- selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
8303
- else if (ie) // Suppress mysterious IE10 errors
8304
- selectInput = function(node) { try { node.select(); } catch(_e) {} };
8305
-
8306
- function indexOf(array, elt) {
8307
- for (var i = 0; i < array.length; ++i)
8308
- if (array[i] == elt) return i;
8309
- return -1;
8310
- }
8311
- function map(array, f) {
8312
- var out = [];
8313
- for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
8314
- return out;
8315
- }
8316
-
8317
- function nothing() {}
8318
-
8319
- function createObj(base, props) {
8320
- var inst;
8321
- if (Object.create) {
8322
- inst = Object.create(base);
8323
- } else {
8324
- nothing.prototype = base;
8325
- inst = new nothing();
8326
- }
8327
- if (props) copyObj(props, inst);
8328
- return inst;
8329
- };
8330
-
8331
- function copyObj(obj, target, overwrite) {
8332
- if (!target) target = {};
8333
- for (var prop in obj)
8334
- if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
8335
- target[prop] = obj[prop];
8336
- return target;
8337
- }
8338
-
8339
- function bind(f) {
8340
- var args = Array.prototype.slice.call(arguments, 1);
8341
- return function(){return f.apply(null, args);};
8342
- }
8343
-
8344
- var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
8345
- var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
8346
- return /\w/.test(ch) || ch > "\x80" &&
8347
- (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
8348
- };
8349
- function isWordChar(ch, helper) {
8350
- if (!helper) return isWordCharBasic(ch);
8351
- if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
8352
- return helper.test(ch);
8353
- }
8354
-
8355
- function isEmpty(obj) {
8356
- for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
8357
- return true;
8358
- }
8359
-
8360
- // Extending unicode characters. A series of a non-extending char +
8361
- // any number of extending chars is treated as a single unit as far
8362
- // as editing and measuring is concerned. This is not fully correct,
8363
- // since some scripts/fonts/browsers also treat other configurations
8364
- // of code points as a group.
8365
- var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
8366
- function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
8367
-
8368
- // DOM UTILITIES
8369
-
8370
- function elt(tag, content, className, style) {
8371
- var e = document.createElement(tag);
8372
- if (className) e.className = className;
8373
- if (style) e.style.cssText = style;
8374
- if (typeof content == "string") e.appendChild(document.createTextNode(content));
8375
- else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
8376
- return e;
8377
- }
8378
-
8379
- var range;
8380
- if (document.createRange) range = function(node, start, end, endNode) {
8381
- var r = document.createRange();
8382
- r.setEnd(endNode || node, end);
8383
- r.setStart(node, start);
8384
- return r;
8385
- };
8386
- else range = function(node, start, end) {
8387
- var r = document.body.createTextRange();
8388
- try { r.moveToElementText(node.parentNode); }
8389
- catch(e) { return r; }
8390
- r.collapse(true);
8391
- r.moveEnd("character", end);
8392
- r.moveStart("character", start);
8393
- return r;
8394
- };
8395
-
8396
- function removeChildren(e) {
8397
- for (var count = e.childNodes.length; count > 0; --count)
8398
- e.removeChild(e.firstChild);
8399
- return e;
8400
- }
8401
-
8402
- function removeChildrenAndAdd(parent, e) {
8403
- return removeChildren(parent).appendChild(e);
8404
- }
8405
-
8406
- var contains = CodeMirror.contains = function(parent, child) {
8407
- if (child.nodeType == 3) // Android browser always returns false when child is a textnode
8408
- child = child.parentNode;
8409
- if (parent.contains)
8410
- return parent.contains(child);
8411
- do {
8412
- if (child.nodeType == 11) child = child.host;
8413
- if (child == parent) return true;
8414
- } while (child = child.parentNode);
8415
- };
8416
-
8417
- function activeElt() {
8418
- var activeElement = document.activeElement;
8419
- while (activeElement && activeElement.root && activeElement.root.activeElement)
8420
- activeElement = activeElement.root.activeElement;
8421
- return activeElement;
8422
- }
8423
- // Older versions of IE throws unspecified error when touching
8424
- // document.activeElement in some cases (during loading, in iframe)
8425
- if (ie && ie_version < 11) activeElt = function() {
8426
- try { return document.activeElement; }
8427
- catch(e) { return document.body; }
8428
- };
8429
-
8430
- function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
8431
- var rmClass = CodeMirror.rmClass = function(node, cls) {
8432
- var current = node.className;
8433
- var match = classTest(cls).exec(current);
8434
- if (match) {
8435
- var after = current.slice(match.index + match[0].length);
8436
- node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
8437
- }
8438
- };
8439
- var addClass = CodeMirror.addClass = function(node, cls) {
8440
- var current = node.className;
8441
- if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
8442
- };
8443
- function joinClasses(a, b) {
8444
- var as = a.split(" ");
8445
- for (var i = 0; i < as.length; i++)
8446
- if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
8447
- return b;
8448
- }
8449
-
8450
- // WINDOW-WIDE EVENTS
8451
-
8452
- // These must be handled carefully, because naively registering a
8453
- // handler for each editor will cause the editors to never be
8454
- // garbage collected.
8455
-
8456
- function forEachCodeMirror(f) {
8457
- if (!document.body.getElementsByClassName) return;
8458
- var byClass = document.body.getElementsByClassName("CodeMirror");
8459
- for (var i = 0; i < byClass.length; i++) {
8460
- var cm = byClass[i].CodeMirror;
8461
- if (cm) f(cm);
8462
- }
8463
- }
8464
-
8465
- var globalsRegistered = false;
8466
- function ensureGlobalHandlers() {
8467
- if (globalsRegistered) return;
8468
- registerGlobalHandlers();
8469
- globalsRegistered = true;
8470
- }
8471
- function registerGlobalHandlers() {
8472
- // When the window resizes, we need to refresh active editors.
8473
- var resizeTimer;
8474
- on(window, "resize", function() {
8475
- if (resizeTimer == null) resizeTimer = setTimeout(function() {
8476
- resizeTimer = null;
8477
- forEachCodeMirror(onResize);
8478
- }, 100);
8479
- });
8480
- // When the window loses focus, we want to show the editor as blurred
8481
- on(window, "blur", function() {
8482
- forEachCodeMirror(onBlur);
8483
- });
8484
- }
8485
-
8486
- // FEATURE DETECTION
8487
-
8488
- // Detect drag-and-drop
8489
- var dragAndDrop = function() {
8490
- // There is *some* kind of drag-and-drop support in IE6-8, but I
8491
- // couldn't get it to work yet.
8492
- if (ie && ie_version < 9) return false;
8493
- var div = elt('div');
8494
- return "draggable" in div || "dragDrop" in div;
8495
- }();
8496
-
8497
- var zwspSupported;
8498
- function zeroWidthElement(measure) {
8499
- if (zwspSupported == null) {
8500
- var test = elt("span", "\u200b");
8501
- removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
8502
- if (measure.firstChild.offsetHeight != 0)
8503
- zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);
8504
- }
8505
- var node = zwspSupported ? elt("span", "\u200b") :
8506
- elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
8507
- node.setAttribute("cm-text", "");
8508
- return node;
8509
- }
8510
-
8511
- // Feature-detect IE's crummy client rect reporting for bidi text
8512
- var badBidiRects;
8513
- function hasBadBidiRects(measure) {
8514
- if (badBidiRects != null) return badBidiRects;
8515
- var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
8516
- var r0 = range(txt, 0, 1).getBoundingClientRect();
8517
- if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
8518
- var r1 = range(txt, 1, 2).getBoundingClientRect();
8519
- return badBidiRects = (r1.right - r0.right < 3);
8520
- }
8521
-
8522
- // See if "".split is the broken IE version, if so, provide an
8523
- // alternative way to split lines.
8524
- var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
8525
- var pos = 0, result = [], l = string.length;
8526
- while (pos <= l) {
8527
- var nl = string.indexOf("\n", pos);
8528
- if (nl == -1) nl = string.length;
8529
- var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
8530
- var rt = line.indexOf("\r");
8531
- if (rt != -1) {
8532
- result.push(line.slice(0, rt));
8533
- pos += rt + 1;
8534
- } else {
8535
- result.push(line);
8536
- pos = nl + 1;
8537
- }
8538
- }
8539
- return result;
8540
- } : function(string){return string.split(/\r\n?|\n/);};
8541
-
8542
- var hasSelection = window.getSelection ? function(te) {
8543
- try { return te.selectionStart != te.selectionEnd; }
8544
- catch(e) { return false; }
8545
- } : function(te) {
8546
- try {var range = te.ownerDocument.selection.createRange();}
8547
- catch(e) {}
8548
- if (!range || range.parentElement() != te) return false;
8549
- return range.compareEndPoints("StartToEnd", range) != 0;
8550
- };
8551
-
8552
- var hasCopyEvent = (function() {
8553
- var e = elt("div");
8554
- if ("oncopy" in e) return true;
8555
- e.setAttribute("oncopy", "return;");
8556
- return typeof e.oncopy == "function";
8557
- })();
8558
-
8559
- var badZoomedRects = null;
8560
- function hasBadZoomedRects(measure) {
8561
- if (badZoomedRects != null) return badZoomedRects;
8562
- var node = removeChildrenAndAdd(measure, elt("span", "x"));
8563
- var normal = node.getBoundingClientRect();
8564
- var fromRange = range(node, 0, 1).getBoundingClientRect();
8565
- return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;
8566
- }
8567
-
8568
- // KEY NAMES
8569
-
8570
- var keyNames = CodeMirror.keyNames = {
8571
- 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
8572
- 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
8573
- 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
8574
- 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
8575
- 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
8576
- 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
8577
- 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
8578
- 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
8579
- };
8580
- (function() {
8581
- // Number keys
8582
- for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
8583
- // Alphabetic keys
8584
- for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
8585
- // Function keys
8586
- for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
8587
- })();
8588
-
8589
- // BIDI HELPERS
8590
-
8591
- function iterateBidiSections(order, from, to, f) {
8592
- if (!order) return f(from, to, "ltr");
8593
- var found = false;
8594
- for (var i = 0; i < order.length; ++i) {
8595
- var part = order[i];
8596
- if (part.from < to && part.to > from || from == to && part.to == from) {
8597
- f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
8598
- found = true;
8599
- }
8600
- }
8601
- if (!found) f(from, to, "ltr");
8602
- }
8603
-
8604
- function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
8605
- function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
8606
-
8607
- function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
8608
- function lineRight(line) {
8609
- var order = getOrder(line);
8610
- if (!order) return line.text.length;
8611
- return bidiRight(lst(order));
8612
- }
8613
-
8614
- function lineStart(cm, lineN) {
8615
- var line = getLine(cm.doc, lineN);
8616
- var visual = visualLine(line);
8617
- if (visual != line) lineN = lineNo(visual);
8618
- var order = getOrder(visual);
8619
- var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
8620
- return Pos(lineN, ch);
8621
- }
8622
- function lineEnd(cm, lineN) {
8623
- var merged, line = getLine(cm.doc, lineN);
8624
- while (merged = collapsedSpanAtEnd(line)) {
8625
- line = merged.find(1, true).line;
8626
- lineN = null;
8627
- }
8628
- var order = getOrder(line);
8629
- var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
8630
- return Pos(lineN == null ? lineNo(line) : lineN, ch);
8631
- }
8632
- function lineStartSmart(cm, pos) {
8633
- var start = lineStart(cm, pos.line);
8634
- var line = getLine(cm.doc, start.line);
8635
- var order = getOrder(line);
8636
- if (!order || order[0].level == 0) {
8637
- var firstNonWS = Math.max(0, line.text.search(/\S/));
8638
- var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
8639
- return Pos(start.line, inWS ? 0 : firstNonWS);
8640
- }
8641
- return start;
8642
- }
8643
-
8644
- function compareBidiLevel(order, a, b) {
8645
- var linedir = order[0].level;
8646
- if (a == linedir) return true;
8647
- if (b == linedir) return false;
8648
- return a < b;
8649
- }
8650
- var bidiOther;
8651
- function getBidiPartAt(order, pos) {
8652
- bidiOther = null;
8653
- for (var i = 0, found; i < order.length; ++i) {
8654
- var cur = order[i];
8655
- if (cur.from < pos && cur.to > pos) return i;
8656
- if ((cur.from == pos || cur.to == pos)) {
8657
- if (found == null) {
8658
- found = i;
8659
- } else if (compareBidiLevel(order, cur.level, order[found].level)) {
8660
- if (cur.from != cur.to) bidiOther = found;
8661
- return i;
8662
- } else {
8663
- if (cur.from != cur.to) bidiOther = i;
8664
- return found;
8665
- }
8666
- }
8667
- }
8668
- return found;
8669
- }
8670
-
8671
- function moveInLine(line, pos, dir, byUnit) {
8672
- if (!byUnit) return pos + dir;
8673
- do pos += dir;
8674
- while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
8675
- return pos;
8676
- }
8677
-
8678
- // This is needed in order to move 'visually' through bi-directional
8679
- // text -- i.e., pressing left should make the cursor go left, even
8680
- // when in RTL text. The tricky part is the 'jumps', where RTL and
8681
- // LTR text touch each other. This often requires the cursor offset
8682
- // to move more than one unit, in order to visually move one unit.
8683
- function moveVisually(line, start, dir, byUnit) {
8684
- var bidi = getOrder(line);
8685
- if (!bidi) return moveLogically(line, start, dir, byUnit);
8686
- var pos = getBidiPartAt(bidi, start), part = bidi[pos];
8687
- var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
8688
-
8689
- for (;;) {
8690
- if (target > part.from && target < part.to) return target;
8691
- if (target == part.from || target == part.to) {
8692
- if (getBidiPartAt(bidi, target) == pos) return target;
8693
- part = bidi[pos += dir];
8694
- return (dir > 0) == part.level % 2 ? part.to : part.from;
8695
- } else {
8696
- part = bidi[pos += dir];
8697
- if (!part) return null;
8698
- if ((dir > 0) == part.level % 2)
8699
- target = moveInLine(line, part.to, -1, byUnit);
8700
- else
8701
- target = moveInLine(line, part.from, 1, byUnit);
8702
- }
8703
- }
8704
- }
8705
-
8706
- function moveLogically(line, start, dir, byUnit) {
8707
- var target = start + dir;
8708
- if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
8709
- return target < 0 || target > line.text.length ? null : target;
8710
- }
8711
-
8712
- // Bidirectional ordering algorithm
8713
- // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
8714
- // that this (partially) implements.
8715
-
8716
- // One-char codes used for character types:
8717
- // L (L): Left-to-Right
8718
- // R (R): Right-to-Left
8719
- // r (AL): Right-to-Left Arabic
8720
- // 1 (EN): European Number
8721
- // + (ES): European Number Separator
8722
- // % (ET): European Number Terminator
8723
- // n (AN): Arabic Number
8724
- // , (CS): Common Number Separator
8725
- // m (NSM): Non-Spacing Mark
8726
- // b (BN): Boundary Neutral
8727
- // s (B): Paragraph Separator
8728
- // t (S): Segment Separator
8729
- // w (WS): Whitespace
8730
- // N (ON): Other Neutrals
8731
-
8732
- // Returns null if characters are ordered as they appear
8733
- // (left-to-right), or an array of sections ({from, to, level}
8734
- // objects) in the order in which they occur visually.
8735
- var bidiOrdering = (function() {
8736
- // Character types for codepoints 0 to 0xff
8737
- var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
8738
- // Character types for codepoints 0x600 to 0x6ff
8739
- var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";
8740
- function charType(code) {
8741
- if (code <= 0xf7) return lowTypes.charAt(code);
8742
- else if (0x590 <= code && code <= 0x5f4) return "R";
8743
- else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);
8744
- else if (0x6ee <= code && code <= 0x8ac) return "r";
8745
- else if (0x2000 <= code && code <= 0x200b) return "w";
8746
- else if (code == 0x200c) return "b";
8747
- else return "L";
8748
- }
8749
-
8750
- var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
8751
- var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
8752
- // Browsers seem to always treat the boundaries of block elements as being L.
8753
- var outerType = "L";
8754
-
8755
- function BidiSpan(level, from, to) {
8756
- this.level = level;
8757
- this.from = from; this.to = to;
8758
- }
8759
-
8760
- return function(str) {
8761
- if (!bidiRE.test(str)) return false;
8762
- var len = str.length, types = [];
8763
- for (var i = 0, type; i < len; ++i)
8764
- types.push(type = charType(str.charCodeAt(i)));
8765
-
8766
- // W1. Examine each non-spacing mark (NSM) in the level run, and
8767
- // change the type of the NSM to the type of the previous
8768
- // character. If the NSM is at the start of the level run, it will
8769
- // get the type of sor.
8770
- for (var i = 0, prev = outerType; i < len; ++i) {
8771
- var type = types[i];
8772
- if (type == "m") types[i] = prev;
8773
- else prev = type;
8774
- }
8775
-
8776
- // W2. Search backwards from each instance of a European number
8777
- // until the first strong type (R, L, AL, or sor) is found. If an
8778
- // AL is found, change the type of the European number to Arabic
8779
- // number.
8780
- // W3. Change all ALs to R.
8781
- for (var i = 0, cur = outerType; i < len; ++i) {
8782
- var type = types[i];
8783
- if (type == "1" && cur == "r") types[i] = "n";
8784
- else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
8785
- }
8786
-
8787
- // W4. A single European separator between two European numbers
8788
- // changes to a European number. A single common separator between
8789
- // two numbers of the same type changes to that type.
8790
- for (var i = 1, prev = types[0]; i < len - 1; ++i) {
8791
- var type = types[i];
8792
- if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
8793
- else if (type == "," && prev == types[i+1] &&
8794
- (prev == "1" || prev == "n")) types[i] = prev;
8795
- prev = type;
8796
- }
8797
-
8798
- // W5. A sequence of European terminators adjacent to European
8799
- // numbers changes to all European numbers.
8800
- // W6. Otherwise, separators and terminators change to Other
8801
- // Neutral.
8802
- for (var i = 0; i < len; ++i) {
8803
- var type = types[i];
8804
- if (type == ",") types[i] = "N";
8805
- else if (type == "%") {
8806
- for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
8807
- var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
8808
- for (var j = i; j < end; ++j) types[j] = replace;
8809
- i = end - 1;
8810
- }
8811
- }
8812
-
8813
- // W7. Search backwards from each instance of a European number
8814
- // until the first strong type (R, L, or sor) is found. If an L is
8815
- // found, then change the type of the European number to L.
8816
- for (var i = 0, cur = outerType; i < len; ++i) {
8817
- var type = types[i];
8818
- if (cur == "L" && type == "1") types[i] = "L";
8819
- else if (isStrong.test(type)) cur = type;
8820
- }
8821
-
8822
- // N1. A sequence of neutrals takes the direction of the
8823
- // surrounding strong text if the text on both sides has the same
8824
- // direction. European and Arabic numbers act as if they were R in
8825
- // terms of their influence on neutrals. Start-of-level-run (sor)
8826
- // and end-of-level-run (eor) are used at level run boundaries.
8827
- // N2. Any remaining neutrals take the embedding direction.
8828
- for (var i = 0; i < len; ++i) {
8829
- if (isNeutral.test(types[i])) {
8830
- for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
8831
- var before = (i ? types[i-1] : outerType) == "L";
8832
- var after = (end < len ? types[end] : outerType) == "L";
8833
- var replace = before || after ? "L" : "R";
8834
- for (var j = i; j < end; ++j) types[j] = replace;
8835
- i = end - 1;
8836
- }
8837
- }
8838
-
8839
- // Here we depart from the documented algorithm, in order to avoid
8840
- // building up an actual levels array. Since there are only three
8841
- // levels (0, 1, 2) in an implementation that doesn't take
8842
- // explicit embedding into account, we can build up the order on
8843
- // the fly, without following the level-based algorithm.
8844
- var order = [], m;
8845
- for (var i = 0; i < len;) {
8846
- if (countsAsLeft.test(types[i])) {
8847
- var start = i;
8848
- for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
8849
- order.push(new BidiSpan(0, start, i));
8850
- } else {
8851
- var pos = i, at = order.length;
8852
- for (++i; i < len && types[i] != "L"; ++i) {}
8853
- for (var j = pos; j < i;) {
8854
- if (countsAsNum.test(types[j])) {
8855
- if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));
8856
- var nstart = j;
8857
- for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
8858
- order.splice(at, 0, new BidiSpan(2, nstart, j));
8859
- pos = j;
8860
- } else ++j;
8861
- }
8862
- if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));
8863
- }
8864
- }
8865
- if (order[0].level == 1 && (m = str.match(/^\s+/))) {
8866
- order[0].from = m[0].length;
8867
- order.unshift(new BidiSpan(0, 0, m[0].length));
8868
- }
8869
- if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
8870
- lst(order).to -= m[0].length;
8871
- order.push(new BidiSpan(0, len - m[0].length, len));
8872
- }
8873
- if (order[0].level == 2)
8874
- order.unshift(new BidiSpan(1, order[0].to, order[0].to));
8875
- if (order[0].level != lst(order).level)
8876
- order.push(new BidiSpan(order[0].level, len, len));
8877
-
8878
- return order;
8879
- };
8880
- })();
8881
-
8882
- // THE END
8883
-
8884
- CodeMirror.version = "5.10.0";
8885
-
8886
- return CodeMirror;
8887
- });
7
  // You can find some technical background for some of the code below
8
  // at http://marijnhaverbeke.nl/blog/#cm-internals .
9
 
10
+ (function (global, factory) {
11
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
12
+ typeof define === 'function' && define.amd ? define(factory) :
13
+ (global.CodeMirror = factory());
14
+ }(this, (function () { 'use strict';
15
+
16
+ // Kludges for bugs and behavior differences that can't be feature
17
+ // detected are enabled based on userAgent etc sniffing.
18
+ var userAgent = navigator.userAgent
19
+ var platform = navigator.platform
20
+
21
+ var gecko = /gecko\/\d/i.test(userAgent)
22
+ var ie_upto10 = /MSIE \d/.test(userAgent)
23
+ var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent)
24
+ var ie = ie_upto10 || ie_11up
25
+ var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1])
26
+ var webkit = /WebKit\//.test(userAgent)
27
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent)
28
+ var chrome = /Chrome\//.test(userAgent)
29
+ var presto = /Opera\//.test(userAgent)
30
+ var safari = /Apple Computer/.test(navigator.vendor)
31
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent)
32
+ var phantom = /PhantomJS/.test(userAgent)
33
+
34
+ var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent)
35
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
36
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent)
37
+ var mac = ios || /Mac/.test(platform)
38
+ var chromeOS = /\bCrOS\b/.test(userAgent)
39
+ var windows = /win/i.test(platform)
40
+
41
+ var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/)
42
+ if (presto_version) { presto_version = Number(presto_version[1]) }
43
+ if (presto_version && presto_version >= 15) { presto = false; webkit = true }
44
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
45
+ var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11))
46
+ var captureRightClick = gecko || (ie && ie_version >= 9)
47
+
48
+ function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
49
+
50
+ var rmClass = function(node, cls) {
51
+ var current = node.className
52
+ var match = classTest(cls).exec(current)
53
+ if (match) {
54
+ var after = current.slice(match.index + match[0].length)
55
+ node.className = current.slice(0, match.index) + (after ? match[1] + after : "")
56
+ }
57
+ }
58
+
59
+ function removeChildren(e) {
60
+ for (var count = e.childNodes.length; count > 0; --count)
61
+ { e.removeChild(e.firstChild) }
62
+ return e
63
+ }
64
+
65
+ function removeChildrenAndAdd(parent, e) {
66
+ return removeChildren(parent).appendChild(e)
67
+ }
68
+
69
+ function elt(tag, content, className, style) {
70
+ var e = document.createElement(tag)
71
+ if (className) { e.className = className }
72
+ if (style) { e.style.cssText = style }
73
+ if (typeof content == "string") { e.appendChild(document.createTextNode(content)) }
74
+ else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]) } }
75
+ return e
76
+ }
77
+
78
+ var range
79
+ if (document.createRange) { range = function(node, start, end, endNode) {
80
+ var r = document.createRange()
81
+ r.setEnd(endNode || node, end)
82
+ r.setStart(node, start)
83
+ return r
84
+ } }
85
+ else { range = function(node, start, end) {
86
+ var r = document.body.createTextRange()
87
+ try { r.moveToElementText(node.parentNode) }
88
+ catch(e) { return r }
89
+ r.collapse(true)
90
+ r.moveEnd("character", end)
91
+ r.moveStart("character", start)
92
+ return r
93
+ } }
94
+
95
+ function contains(parent, child) {
96
+ if (child.nodeType == 3) // Android browser always returns false when child is a textnode
97
+ { child = child.parentNode }
98
+ if (parent.contains)
99
+ { return parent.contains(child) }
100
+ do {
101
+ if (child.nodeType == 11) { child = child.host }
102
+ if (child == parent) { return true }
103
+ } while (child = child.parentNode)
104
+ }
105
+
106
+ function activeElt() {
107
+ // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
108
+ // IE < 10 will throw when accessed while the page is loading or in an iframe.
109
+ // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
110
+ var activeElement
111
+ try {
112
+ activeElement = document.activeElement
113
+ } catch(e) {
114
+ activeElement = document.body || null
115
+ }
116
+ while (activeElement && activeElement.root && activeElement.root.activeElement)
117
+ { activeElement = activeElement.root.activeElement }
118
+ return activeElement
119
+ }
120
+
121
+ function addClass(node, cls) {
122
+ var current = node.className
123
+ if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls }
124
+ }
125
+ function joinClasses(a, b) {
126
+ var as = a.split(" ")
127
+ for (var i = 0; i < as.length; i++)
128
+ { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i] } }
129
+ return b
130
+ }
131
+
132
+ var selectInput = function(node) { node.select() }
133
+ if (ios) // Mobile Safari apparently has a bug where select() is broken.
134
+ { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length } }
135
+ else if (ie) // Suppress mysterious IE10 errors
136
+ { selectInput = function(node) { try { node.select() } catch(_e) {} } }
137
+
138
+ function bind(f) {
139
+ var args = Array.prototype.slice.call(arguments, 1)
140
+ return function(){return f.apply(null, args)}
141
+ }
142
+
143
+ function copyObj(obj, target, overwrite) {
144
+ if (!target) { target = {} }
145
+ for (var prop in obj)
146
+ { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
147
+ { target[prop] = obj[prop] } }
148
+ return target
149
+ }
150
+
151
+ // Counts the column offset in a string, taking tabs into account.
152
+ // Used mostly to find indentation.
153
+ function countColumn(string, end, tabSize, startIndex, startValue) {
154
+ if (end == null) {
155
+ end = string.search(/[^\s\u00a0]/)
156
+ if (end == -1) { end = string.length }
157
+ }
158
+ for (var i = startIndex || 0, n = startValue || 0;;) {
159
+ var nextTab = string.indexOf("\t", i)
160
+ if (nextTab < 0 || nextTab >= end)
161
+ { return n + (end - i) }
162
+ n += nextTab - i
163
+ n += tabSize - (n % tabSize)
164
+ i = nextTab + 1
165
+ }
166
+ }
167
+
168
+ function Delayed() {this.id = null}
169
+ Delayed.prototype.set = function(ms, f) {
170
+ clearTimeout(this.id)
171
+ this.id = setTimeout(f, ms)
172
+ }
173
+
174
+ function indexOf(array, elt) {
175
+ for (var i = 0; i < array.length; ++i)
176
+ { if (array[i] == elt) { return i } }
177
+ return -1
178
+ }
179
+
180
+ // Number of pixels added to scroller and sizer to hide scrollbar
181
+ var scrollerGap = 30
182
+
183
+ // Returned or thrown by various protocols to signal 'I'm not
184
+ // handling this'.
185
+ var Pass = {toString: function(){return "CodeMirror.Pass"}}
186
+
187
+ // Reused option objects for setSelection & friends
188
+ var sel_dontScroll = {scroll: false};
189
+ var sel_mouse = {origin: "*mouse"};
190
+ var sel_move = {origin: "+move"};
191
+ // The inverse of countColumn -- find the offset that corresponds to
192
+ // a particular column.
193
+ function findColumn(string, goal, tabSize) {
194
+ for (var pos = 0, col = 0;;) {
195
+ var nextTab = string.indexOf("\t", pos)
196
+ if (nextTab == -1) { nextTab = string.length }
197
+ var skipped = nextTab - pos
198
+ if (nextTab == string.length || col + skipped >= goal)
199
+ { return pos + Math.min(skipped, goal - col) }
200
+ col += nextTab - pos
201
+ col += tabSize - (col % tabSize)
202
+ pos = nextTab + 1
203
+ if (col >= goal) { return pos }
204
+ }
205
+ }
206
+
207
+ var spaceStrs = [""]
208
+ function spaceStr(n) {
209
+ while (spaceStrs.length <= n)
210
+ { spaceStrs.push(lst(spaceStrs) + " ") }
211
+ return spaceStrs[n]
212
+ }
213
+
214
+ function lst(arr) { return arr[arr.length-1] }
215
+
216
+ function map(array, f) {
217
+ var out = []
218
+ for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i) }
219
+ return out
220
+ }
221
+
222
+ function insertSorted(array, value, score) {
223
+ var pos = 0, priority = score(value)
224
+ while (pos < array.length && score(array[pos]) <= priority) { pos++ }
225
+ array.splice(pos, 0, value)
226
+ }
227
+
228
+ function nothing() {}
229
+
230
+ function createObj(base, props) {
231
+ var inst
232
+ if (Object.create) {
233
+ inst = Object.create(base)
234
+ } else {
235
+ nothing.prototype = base
236
+ inst = new nothing()
237
+ }
238
+ if (props) { copyObj(props, inst) }
239
+ return inst
240
+ }
241
+
242
+ var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/
243
+ function isWordCharBasic(ch) {
244
+ return /\w/.test(ch) || ch > "\x80" &&
245
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
246
+ }
247
+ function isWordChar(ch, helper) {
248
+ if (!helper) { return isWordCharBasic(ch) }
249
+ if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true }
250
+ return helper.test(ch)
251
+ }
252
+
253
+ function isEmpty(obj) {
254
+ for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }
255
+ return true
256
+ }
257
+
258
+ // Extending unicode characters. A series of a non-extending char +
259
+ // any number of extending chars is treated as a single unit as far
260
+ // as editing and measuring is concerned. This is not fully correct,
261
+ // since some scripts/fonts/browsers also treat other configurations
262
+ // of code points as a group.
263
+ var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/
264
+ function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }
265
+
266
+ // The display handles the DOM integration, both for input reading
267
+ // and content drawing. It holds references to DOM nodes and
268
+ // display-related state.
269
+
270
+ function Display(place, doc, input) {
271
+ var d = this
272
+ this.input = input
273
+
274
+ // Covers bottom-right square when both scrollbars are present.
275
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler")
276
+ d.scrollbarFiller.setAttribute("cm-not-content", "true")
277
+ // Covers bottom of gutter when coverGutterNextToScrollbar is on
278
+ // and h scrollbar is present.
279
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler")
280
+ d.gutterFiller.setAttribute("cm-not-content", "true")
281
+ // Will contain the actual code, positioned to cover the viewport.
282
+ d.lineDiv = elt("div", null, "CodeMirror-code")
283
+ // Elements are added to these to represent selection and cursors.
284
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1")
285
+ d.cursorDiv = elt("div", null, "CodeMirror-cursors")
286
+ // A visibility: hidden element used to find the size of things.
287
+ d.measure = elt("div", null, "CodeMirror-measure")
288
+ // When lines outside of the viewport are measured, they are drawn in this.
289
+ d.lineMeasure = elt("div", null, "CodeMirror-measure")
290
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
291
+ d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
292
+ null, "position: relative; outline: none")
293
+ // Moved around its parent to cover visible view.
294
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative")
295
+ // Set to the height of the document, allowing scrolling.
296
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer")
297
+ d.sizerWidth = null
298
+ // Behavior of elts with overflow: auto and padding is
299
+ // inconsistent across browsers. This is used to ensure the
300
+ // scrollable area is big enough.
301
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;")
302
+ // Will contain the gutters, if any.
303
+ d.gutters = elt("div", null, "CodeMirror-gutters")
304
+ d.lineGutter = null
305
+ // Actual scrollable element.
306
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll")
307
+ d.scroller.setAttribute("tabIndex", "-1")
308
+ // The element in which the editor lives.
309
+ d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror")
310
+
311
+ // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
312
+ if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0 }
313
+ if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true }
314
+
315
+ if (place) {
316
+ if (place.appendChild) { place.appendChild(d.wrapper) }
317
+ else { place(d.wrapper) }
318
+ }
319
+
320
+ // Current rendered range (may be bigger than the view window).
321
+ d.viewFrom = d.viewTo = doc.first
322
+ d.reportedViewFrom = d.reportedViewTo = doc.first
323
+ // Information about the rendered lines.
324
+ d.view = []
325
+ d.renderedView = null
326
+ // Holds info about a single rendered line when it was rendered
327
+ // for measurement, while not in view.
328
+ d.externalMeasured = null
329
+ // Empty space (in pixels) above the view
330
+ d.viewOffset = 0
331
+ d.lastWrapHeight = d.lastWrapWidth = 0
332
+ d.updateLineNumbers = null
333
+
334
+ d.nativeBarWidth = d.barHeight = d.barWidth = 0
335
+ d.scrollbarsClipped = false
336
+
337
+ // Used to only resize the line number gutter when necessary (when
338
+ // the amount of lines crosses a boundary that makes its width change)
339
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null
340
+ // Set to true when a non-horizontal-scrolling line widget is
341
+ // added. As an optimization, line widget aligning is skipped when
342
+ // this is false.
343
+ d.alignWidgets = false
344
+
345
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null
346
+
347
+ // Tracks the maximum line length so that the horizontal scrollbar
348
+ // can be kept static when scrolling.
349
+ d.maxLine = null
350
+ d.maxLineLength = 0
351
+ d.maxLineChanged = false
352
+
353
+ // Used for measuring wheel scrolling granularity
354
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null
355
+
356
+ // True when shift is held down.
357
+ d.shift = false
358
+
359
+ // Used to track whether anything happened since the context menu
360
+ // was opened.
361
+ d.selForContextMenu = null
362
+
363
+ d.activeTouch = null
364
+
365
+ input.init(d)
366
+ }
367
+
368
+ // Find the line object corresponding to the given line number.
369
+ function getLine(doc, n) {
370
+ n -= doc.first
371
+ if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") }
372
+ var chunk = doc
373
+ while (!chunk.lines) {
374
+ for (var i = 0;; ++i) {
375
+ var child = chunk.children[i], sz = child.chunkSize()
376
+ if (n < sz) { chunk = child; break }
377
+ n -= sz
378
+ }
379
+ }
380
+ return chunk.lines[n]
381
+ }
382
+
383
+ // Get the part of a document between two positions, as an array of
384
+ // strings.
385
+ function getBetween(doc, start, end) {
386
+ var out = [], n = start.line
387
+ doc.iter(start.line, end.line + 1, function (line) {
388
+ var text = line.text
389
+ if (n == end.line) { text = text.slice(0, end.ch) }
390
+ if (n == start.line) { text = text.slice(start.ch) }
391
+ out.push(text)
392
+ ++n
393
+ })
394
+ return out
395
+ }
396
+ // Get the lines between from and to, as array of strings.
397
+ function getLines(doc, from, to) {
398
+ var out = []
399
+ doc.iter(from, to, function (line) { out.push(line.text) }) // iter aborts when callback returns truthy value
400
+ return out
401
+ }
402
+
403
+ // Update the height of a line, propagating the height change
404
+ // upwards to parent nodes.
405
+ function updateLineHeight(line, height) {
406
+ var diff = height - line.height
407
+ if (diff) { for (var n = line; n; n = n.parent) { n.height += diff } }
408
+ }
409
+
410
+ // Given a line object, find its line number by walking up through
411
+ // its parent links.
412
+ function lineNo(line) {
413
+ if (line.parent == null) { return null }
414
+ var cur = line.parent, no = indexOf(cur.lines, line)
415
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
416
+ for (var i = 0;; ++i) {
417
+ if (chunk.children[i] == cur) { break }
418
+ no += chunk.children[i].chunkSize()
419
+ }
420
+ }
421
+ return no + cur.first
422
+ }
423
+
424
+ // Find the line at the given vertical position, using the height
425
+ // information in the document tree.
426
+ function lineAtHeight(chunk, h) {
427
+ var n = chunk.first
428
+ outer: do {
429
+ for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {
430
+ var child = chunk.children[i$1], ch = child.height
431
+ if (h < ch) { chunk = child; continue outer }
432
+ h -= ch
433
+ n += child.chunkSize()
434
+ }
435
+ return n
436
+ } while (!chunk.lines)
437
+ var i = 0
438
+ for (; i < chunk.lines.length; ++i) {
439
+ var line = chunk.lines[i], lh = line.height
440
+ if (h < lh) { break }
441
+ h -= lh
442
+ }
443
+ return n + i
444
+ }
445
+
446
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}
447
+
448
+ function lineNumberFor(options, i) {
449
+ return String(options.lineNumberFormatter(i + options.firstLineNumber))
450
+ }
451
+
452
+ // A Pos instance represents a position within the text.
453
+ function Pos (line, ch) {
454
+ if (!(this instanceof Pos)) { return new Pos(line, ch) }
455
+ this.line = line; this.ch = ch
456
+ }
457
+
458
+ // Compare two positions, return 0 if they are the same, a negative
459
+ // number when a is less, and a positive number otherwise.
460
+ function cmp(a, b) { return a.line - b.line || a.ch - b.ch }
461
+
462
+ function copyPos(x) {return Pos(x.line, x.ch)}
463
+ function maxPos(a, b) { return cmp(a, b) < 0 ? b : a }
464
+ function minPos(a, b) { return cmp(a, b) < 0 ? a : b }
465
+
466
+ // Most of the external API clips given positions to make sure they
467
+ // actually exist within the document.
468
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}
469
+ function clipPos(doc, pos) {
470
+ if (pos.line < doc.first) { return Pos(doc.first, 0) }
471
+ var last = doc.first + doc.size - 1
472
+ if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }
473
+ return clipToLen(pos, getLine(doc, pos.line).text.length)
474
+ }
475
+ function clipToLen(pos, linelen) {
476
+ var ch = pos.ch
477
+ if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }
478
+ else if (ch < 0) { return Pos(pos.line, 0) }
479
+ else { return pos }
480
+ }
481
+ function clipPosArray(doc, array) {
482
+ var out = []
483
+ for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]) }
484
+ return out
485
+ }
486
+
487
+ // Optimize some code when these features are not used.
488
+ var sawReadOnlySpans = false;
489
+ var sawCollapsedSpans = false;
490
+ function seeReadOnlySpans() {
491
+ sawReadOnlySpans = true
492
+ }
493
+
494
+ function seeCollapsedSpans() {
495
+ sawCollapsedSpans = true
496
+ }
497
+
498
+ // TEXTMARKER SPANS
499
+
500
+ function MarkedSpan(marker, from, to) {
501
+ this.marker = marker
502
+ this.from = from; this.to = to
503
+ }
504
+
505
+ // Search an array of spans for a span matching the given marker.
506
+ function getMarkedSpanFor(spans, marker) {
507
+ if (spans) { for (var i = 0; i < spans.length; ++i) {
508
+ var span = spans[i]
509
+ if (span.marker == marker) { return span }
510
+ } }
511
+ }
512
+ // Remove a span from an array, returning undefined if no spans are
513
+ // left (we don't store arrays for lines without spans).
514
+ function removeMarkedSpan(spans, span) {
515
+ var r
516
+ for (var i = 0; i < spans.length; ++i)
517
+ { if (spans[i] != span) { (r || (r = [])).push(spans[i]) } }
518
+ return r
519
+ }
520
+ // Add a span to a line.
521
+ function addMarkedSpan(line, span) {
522
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]
523
+ span.marker.attachLine(line)
524
+ }
525
+
526
+ // Used for the algorithm that adjusts markers for a change in the
527
+ // document. These functions cut an array of spans at a given
528
+ // character position, returning an array of remaining chunks (or
529
+ // undefined if nothing remains).
530
+ function markedSpansBefore(old, startCh, isInsert) {
531
+ var nw
532
+ if (old) { for (var i = 0; i < old.length; ++i) {
533
+ var span = old[i], marker = span.marker
534
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh)
535
+ if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
536
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh)
537
+ ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to))
538
+ }
539
+ } }
540
+ return nw
541
+ }
542
+ function markedSpansAfter(old, endCh, isInsert) {
543
+ var nw
544
+ if (old) { for (var i = 0; i < old.length; ++i) {
545
+ var span = old[i], marker = span.marker
546
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh)
547
+ if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
548
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh)
549
+ ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
550
+ span.to == null ? null : span.to - endCh))
551
+ }
552
+ } }
553
+ return nw
554
+ }
555
+
556
+ // Given a change object, compute the new set of marker spans that
557
+ // cover the line in which the change took place. Removes spans
558
+ // entirely within the change, reconnects spans belonging to the
559
+ // same marker that appear on both sides of the change, and cuts off
560
+ // spans partially within the change. Returns an array of span
561
+ // arrays with one element for each line in (after) the change.
562
+ function stretchSpansOverChange(doc, change) {
563
+ if (change.full) { return null }
564
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans
565
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans
566
+ if (!oldFirst && !oldLast) { return null }
567
+
568
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0
569
+ // Get the spans that 'stick out' on both sides
570
+ var first = markedSpansBefore(oldFirst, startCh, isInsert)
571
+ var last = markedSpansAfter(oldLast, endCh, isInsert)
572
+
573
+ // Next, merge those two ends
574
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0)
575
+ if (first) {
576
+ // Fix up .to properties of first
577
+ for (var i = 0; i < first.length; ++i) {
578
+ var span = first[i]
579
+ if (span.to == null) {
580
+ var found = getMarkedSpanFor(last, span.marker)
581
+ if (!found) { span.to = startCh }
582
+ else if (sameLine) { span.to = found.to == null ? null : found.to + offset }
583
+ }
584
+ }
585
+ }
586
+ if (last) {
587
+ // Fix up .from in last (or move them into first in case of sameLine)
588
+ for (var i$1 = 0; i$1 < last.length; ++i$1) {
589
+ var span$1 = last[i$1]
590
+ if (span$1.to != null) { span$1.to += offset }
591
+ if (span$1.from == null) {
592
+ var found$1 = getMarkedSpanFor(first, span$1.marker)
593
+ if (!found$1) {
594
+ span$1.from = offset
595
+ if (sameLine) { (first || (first = [])).push(span$1) }
596
+ }
597
+ } else {
598
+ span$1.from += offset
599
+ if (sameLine) { (first || (first = [])).push(span$1) }
600
+ }
601
+ }
602
+ }
603
+ // Make sure we didn't create any zero-length spans
604
+ if (first) { first = clearEmptySpans(first) }
605
+ if (last && last != first) { last = clearEmptySpans(last) }
606
+
607
+ var newMarkers = [first]
608
+ if (!sameLine) {
609
+ // Fill gap with whole-line-spans
610
+ var gap = change.text.length - 2, gapMarkers
611
+ if (gap > 0 && first)
612
+ { for (var i$2 = 0; i$2 < first.length; ++i$2)
613
+ { if (first[i$2].to == null)
614
+ { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)) } } }
615
+ for (var i$3 = 0; i$3 < gap; ++i$3)
616
+ { newMarkers.push(gapMarkers) }
617
+ newMarkers.push(last)
618
+ }
619
+ return newMarkers
620
+ }
621
+
622
+ // Remove spans that are empty and don't have a clearWhenEmpty
623
+ // option of false.
624
+ function clearEmptySpans(spans) {
625
+ for (var i = 0; i < spans.length; ++i) {
626
+ var span = spans[i]
627
+ if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
628
+ { spans.splice(i--, 1) }
629
+ }
630
+ if (!spans.length) { return null }
631
+ return spans
632
+ }
633
+
634
+ // Used to 'clip' out readOnly ranges when making a change.
635
+ function removeReadOnlyRanges(doc, from, to) {
636
+ var markers = null
637
+ doc.iter(from.line, to.line + 1, function (line) {
638
+ if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
639
+ var mark = line.markedSpans[i].marker
640
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
641
+ { (markers || (markers = [])).push(mark) }
642
+ } }
643
+ })
644
+ if (!markers) { return null }
645
+ var parts = [{from: from, to: to}]
646
+ for (var i = 0; i < markers.length; ++i) {
647
+ var mk = markers[i], m = mk.find(0)
648
+ for (var j = 0; j < parts.length; ++j) {
649
+ var p = parts[j]
650
+ if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }
651
+ var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to)
652
+ if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
653
+ { newParts.push({from: p.from, to: m.from}) }
654
+ if (dto > 0 || !mk.inclusiveRight && !dto)
655
+ { newParts.push({from: m.to, to: p.to}) }
656
+ parts.splice.apply(parts, newParts)
657
+ j += newParts.length - 1
658
+ }
659
+ }
660
+ return parts
661
+ }
662
+
663
+ // Connect or disconnect spans from a line.
664
+ function detachMarkedSpans(line) {
665
+ var spans = line.markedSpans
666
+ if (!spans) { return }
667
+ for (var i = 0; i < spans.length; ++i)
668
+ { spans[i].marker.detachLine(line) }
669
+ line.markedSpans = null
670
+ }
671
+ function attachMarkedSpans(line, spans) {
672
+ if (!spans) { return }
673
+ for (var i = 0; i < spans.length; ++i)
674
+ { spans[i].marker.attachLine(line) }
675
+ line.markedSpans = spans
676
+ }
677
+
678
+ // Helpers used when computing which overlapping collapsed span
679
+ // counts as the larger one.
680
+ function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }
681
+ function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }
682
+
683
+ // Returns a number indicating which of two overlapping collapsed
684
+ // spans is larger (and thus includes the other). Falls back to
685
+ // comparing ids when the spans cover exactly the same range.
686
+ function compareCollapsedMarkers(a, b) {
687
+ var lenDiff = a.lines.length - b.lines.length
688
+ if (lenDiff != 0) { return lenDiff }
689
+ var aPos = a.find(), bPos = b.find()
690
+ var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b)
691
+ if (fromCmp) { return -fromCmp }
692
+ var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b)
693
+ if (toCmp) { return toCmp }
694
+ return b.id - a.id
695
+ }
696
+
697
+ // Find out whether a line ends or starts in a collapsed span. If
698
+ // so, return the marker for that span.
699
+ function collapsedSpanAtSide(line, start) {
700
+ var sps = sawCollapsedSpans && line.markedSpans, found
701
+ if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
702
+ sp = sps[i]
703
+ if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
704
+ (!found || compareCollapsedMarkers(found, sp.marker) < 0))
705
+ { found = sp.marker }
706
+ } }
707
+ return found
708
+ }
709
+ function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
710
+ function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }
711
+
712
+ // Test whether there exists a collapsed span that partially
713
+ // overlaps (covers the start or end, but not both) of a new span.
714
+ // Such overlap is not allowed.
715
+ function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
716
+ var line = getLine(doc, lineNo)
717
+ var sps = sawCollapsedSpans && line.markedSpans
718
+ if (sps) { for (var i = 0; i < sps.length; ++i) {
719
+ var sp = sps[i]
720
+ if (!sp.marker.collapsed) { continue }
721
+ var found = sp.marker.find(0)
722
+ var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker)
723
+ var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker)
724
+ if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }
725
+ if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
726
+ fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
727
+ { return true }
728
+ } }
729
+ }
730
+
731
+ // A visual line is a line as drawn on the screen. Folding, for
732
+ // example, can cause multiple logical lines to appear on the same
733
+ // visual line. This finds the start of the visual line that the
734
+ // given line is part of (usually that is the line itself).
735
+ function visualLine(line) {
736
+ var merged
737
+ while (merged = collapsedSpanAtStart(line))
738
+ { line = merged.find(-1, true).line }
739
+ return line
740
+ }
741
+
742
+ // Returns an array of logical lines that continue the visual line
743
+ // started by the argument, or undefined if there are no such lines.
744
+ function visualLineContinued(line) {
745
+ var merged, lines
746
+ while (merged = collapsedSpanAtEnd(line)) {
747
+ line = merged.find(1, true).line
748
+ ;(lines || (lines = [])).push(line)
749
+ }
750
+ return lines
751
+ }
752
+
753
+ // Get the line number of the start of the visual line that the
754
+ // given line number is part of.
755
+ function visualLineNo(doc, lineN) {
756
+ var line = getLine(doc, lineN), vis = visualLine(line)
757
+ if (line == vis) { return lineN }
758
+ return lineNo(vis)
759
+ }
760
+
761
+ // Get the line number of the start of the next visual line after
762
+ // the given line.
763
+ function visualLineEndNo(doc, lineN) {
764
+ if (lineN > doc.lastLine()) { return lineN }
765
+ var line = getLine(doc, lineN), merged
766
+ if (!lineIsHidden(doc, line)) { return lineN }
767
+ while (merged = collapsedSpanAtEnd(line))
768
+ { line = merged.find(1, true).line }
769
+ return lineNo(line) + 1
770
+ }
771
+
772
+ // Compute whether a line is hidden. Lines count as hidden when they
773
+ // are part of a visual line that starts with another line, or when
774
+ // they are entirely covered by collapsed, non-widget span.
775
+ function lineIsHidden(doc, line) {
776
+ var sps = sawCollapsedSpans && line.markedSpans
777
+ if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
778
+ sp = sps[i]
779
+ if (!sp.marker.collapsed) { continue }
780
+ if (sp.from == null) { return true }
781
+ if (sp.marker.widgetNode) { continue }
782
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
783
+ { return true }
784
+ } }
785
+ }
786
+ function lineIsHiddenInner(doc, line, span) {
787
+ if (span.to == null) {
788
+ var end = span.marker.find(1, true)
789
+ return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))
790
+ }
791
+ if (span.marker.inclusiveRight && span.to == line.text.length)
792
+ { return true }
793
+ for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {
794
+ sp = line.markedSpans[i]
795
+ if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
796
+ (sp.to == null || sp.to != span.from) &&
797
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
798
+ lineIsHiddenInner(doc, line, sp)) { return true }
799
+ }
800
+ }
801
+
802
+ // Find the height above the given line.
803
+ function heightAtLine(lineObj) {
804
+ lineObj = visualLine(lineObj)
805
+
806
+ var h = 0, chunk = lineObj.parent
807
+ for (var i = 0; i < chunk.lines.length; ++i) {
808
+ var line = chunk.lines[i]
809
+ if (line == lineObj) { break }
810
+ else { h += line.height }
811
+ }
812
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
813
+ for (var i$1 = 0; i$1 < p.children.length; ++i$1) {
814
+ var cur = p.children[i$1]
815
+ if (cur == chunk) { break }
816
+ else { h += cur.height }
817
+ }
818
+ }
819
+ return h
820
+ }
821
+
822
+ // Compute the character length of a line, taking into account
823
+ // collapsed ranges (see markText) that might hide parts, and join
824
+ // other lines onto it.
825
+ function lineLength(line) {
826
+ if (line.height == 0) { return 0 }
827
+ var len = line.text.length, merged, cur = line
828
+ while (merged = collapsedSpanAtStart(cur)) {
829
+ var found = merged.find(0, true)
830
+ cur = found.from.line
831
+ len += found.from.ch - found.to.ch
832
+ }
833
+ cur = line
834
+ while (merged = collapsedSpanAtEnd(cur)) {
835
+ var found$1 = merged.find(0, true)
836
+ len -= cur.text.length - found$1.from.ch
837
+ cur = found$1.to.line
838
+ len += cur.text.length - found$1.to.ch
839
+ }
840
+ return len
841
+ }
842
+
843
+ // Find the longest line in the document.
844
+ function findMaxLine(cm) {
845
+ var d = cm.display, doc = cm.doc
846
+ d.maxLine = getLine(doc, doc.first)
847
+ d.maxLineLength = lineLength(d.maxLine)
848
+ d.maxLineChanged = true
849
+ doc.iter(function (line) {
850
+ var len = lineLength(line)
851
+ if (len > d.maxLineLength) {
852
+ d.maxLineLength = len
853
+ d.maxLine = line
854
+ }
855
+ })
856
+ }
857
+
858
+ // BIDI HELPERS
859
+
860
+ function iterateBidiSections(order, from, to, f) {
861
+ if (!order) { return f(from, to, "ltr") }
862
+ var found = false
863
+ for (var i = 0; i < order.length; ++i) {
864
+ var part = order[i]
865
+ if (part.from < to && part.to > from || from == to && part.to == from) {
866
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr")
867
+ found = true
868
+ }
869
+ }
870
+ if (!found) { f(from, to, "ltr") }
871
+ }
872
+
873
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from }
874
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to }
875
+
876
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0 }
877
+ function lineRight(line) {
878
+ var order = getOrder(line)
879
+ if (!order) { return line.text.length }
880
+ return bidiRight(lst(order))
881
+ }
882
+
883
+ function compareBidiLevel(order, a, b) {
884
+ var linedir = order[0].level
885
+ if (a == linedir) { return true }
886
+ if (b == linedir) { return false }
887
+ return a < b
888
+ }
889
+
890
+ var bidiOther = null
891
+ function getBidiPartAt(order, pos) {
892
+ var found
893
+ bidiOther = null
894
+ for (var i = 0; i < order.length; ++i) {
895
+ var cur = order[i]
896
+ if (cur.from < pos && cur.to > pos) { return i }
897
+ if ((cur.from == pos || cur.to == pos)) {
898
+ if (found == null) {
899
+ found = i
900
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) {
901
+ if (cur.from != cur.to) { bidiOther = found }
902
+ return i
903
+ } else {
904
+ if (cur.from != cur.to) { bidiOther = i }
905
+ return found
906
+ }
907
+ }
908
+ }
909
+ return found
910
+ }
911
+
912
+ function moveInLine(line, pos, dir, byUnit) {
913
+ if (!byUnit) { return pos + dir }
914
+ do { pos += dir }
915
+ while (pos > 0 && isExtendingChar(line.text.charAt(pos)))
916
+ return pos
917
+ }
918
+
919
+ // This is needed in order to move 'visually' through bi-directional
920
+ // text -- i.e., pressing left should make the cursor go left, even
921
+ // when in RTL text. The tricky part is the 'jumps', where RTL and
922
+ // LTR text touch each other. This often requires the cursor offset
923
+ // to move more than one unit, in order to visually move one unit.
924
+ function moveVisually(line, start, dir, byUnit) {
925
+ var bidi = getOrder(line)
926
+ if (!bidi) { return moveLogically(line, start, dir, byUnit) }
927
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos]
928
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit)
929
+
930
+ for (;;) {
931
+ if (target > part.from && target < part.to) { return target }
932
+ if (target == part.from || target == part.to) {
933
+ if (getBidiPartAt(bidi, target) == pos) { return target }
934
+ part = bidi[pos += dir]
935
+ return (dir > 0) == part.level % 2 ? part.to : part.from
936
  } else {
937
+ part = bidi[pos += dir]
938
+ if (!part) { return null }
939
+ if ((dir > 0) == part.level % 2)
940
+ { target = moveInLine(line, part.to, -1, byUnit) }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
941
  else
942
+ { target = moveInLine(line, part.from, 1, byUnit) }
943
+ }
944
+ }
945
+ }
946
+
947
+ function moveLogically(line, start, dir, byUnit) {
948
+ var target = start + dir
949
+ if (byUnit) { while (target > 0 && isExtendingChar(line.text.charAt(target))) { target += dir } }
950
+ return target < 0 || target > line.text.length ? null : target
951
+ }
952
+
953
+ // Bidirectional ordering algorithm
954
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
955
+ // that this (partially) implements.
956
+
957
+ // One-char codes used for character types:
958
+ // L (L): Left-to-Right
959
+ // R (R): Right-to-Left
960
+ // r (AL): Right-to-Left Arabic
961
+ // 1 (EN): European Number
962
+ // + (ES): European Number Separator
963
+ // % (ET): European Number Terminator
964
+ // n (AN): Arabic Number
965
+ // , (CS): Common Number Separator
966
+ // m (NSM): Non-Spacing Mark
967
+ // b (BN): Boundary Neutral
968
+ // s (B): Paragraph Separator
969
+ // t (S): Segment Separator
970
+ // w (WS): Whitespace
971
+ // N (ON): Other Neutrals
972
+
973
+ // Returns null if characters are ordered as they appear
974
+ // (left-to-right), or an array of sections ({from, to, level}
975
+ // objects) in the order in which they occur visually.
976
+ var bidiOrdering = (function() {
977
+ // Character types for codepoints 0 to 0xff
978
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"
979
+ // Character types for codepoints 0x600 to 0x6f9
980
+ var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"
981
+ function charType(code) {
982
+ if (code <= 0xf7) { return lowTypes.charAt(code) }
983
+ else if (0x590 <= code && code <= 0x5f4) { return "R" }
984
+ else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }
985
+ else if (0x6ee <= code && code <= 0x8ac) { return "r" }
986
+ else if (0x2000 <= code && code <= 0x200b) { return "w" }
987
+ else if (code == 0x200c) { return "b" }
988
+ else { return "L" }
989
+ }
990
+
991
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/
992
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/
993
+ // Browsers seem to always treat the boundaries of block elements as being L.
994
+ var outerType = "L"
995
+
996
+ function BidiSpan(level, from, to) {
997
+ this.level = level
998
+ this.from = from; this.to = to
999
+ }
1000
+
1001
+ return function(str) {
1002
+ if (!bidiRE.test(str)) { return false }
1003
+ var len = str.length, types = []
1004
+ for (var i = 0; i < len; ++i)
1005
+ { types.push(charType(str.charCodeAt(i))) }
1006
+
1007
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
1008
+ // change the type of the NSM to the type of the previous
1009
+ // character. If the NSM is at the start of the level run, it will
1010
+ // get the type of sor.
1011
+ for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {
1012
+ var type = types[i$1]
1013
+ if (type == "m") { types[i$1] = prev }
1014
+ else { prev = type }
1015
+ }
1016
+
1017
+ // W2. Search backwards from each instance of a European number
1018
+ // until the first strong type (R, L, AL, or sor) is found. If an
1019
+ // AL is found, change the type of the European number to Arabic
1020
+ // number.
1021
+ // W3. Change all ALs to R.
1022
+ for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {
1023
+ var type$1 = types[i$2]
1024
+ if (type$1 == "1" && cur == "r") { types[i$2] = "n" }
1025
+ else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R" } }
1026
+ }
1027
+
1028
+ // W4. A single European separator between two European numbers
1029
+ // changes to a European number. A single common separator between
1030
+ // two numbers of the same type changes to that type.
1031
+ for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {
1032
+ var type$2 = types[i$3]
1033
+ if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1" }
1034
+ else if (type$2 == "," && prev$1 == types[i$3+1] &&
1035
+ (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1 }
1036
+ prev$1 = type$2
1037
+ }
1038
+
1039
+ // W5. A sequence of European terminators adjacent to European
1040
+ // numbers changes to all European numbers.
1041
+ // W6. Otherwise, separators and terminators change to Other
1042
+ // Neutral.
1043
+ for (var i$4 = 0; i$4 < len; ++i$4) {
1044
+ var type$3 = types[i$4]
1045
+ if (type$3 == ",") { types[i$4] = "N" }
1046
+ else if (type$3 == "%") {
1047
+ var end = (void 0)
1048
+ for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {}
1049
+ var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"
1050
+ for (var j = i$4; j < end; ++j) { types[j] = replace }
1051
+ i$4 = end - 1
1052
+ }
1053
+ }
1054
+
1055
+ // W7. Search backwards from each instance of a European number
1056
+ // until the first strong type (R, L, or sor) is found. If an L is
1057
+ // found, then change the type of the European number to L.
1058
+ for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {
1059
+ var type$4 = types[i$5]
1060
+ if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L" }
1061
+ else if (isStrong.test(type$4)) { cur$1 = type$4 }
1062
+ }
1063
+
1064
+ // N1. A sequence of neutrals takes the direction of the
1065
+ // surrounding strong text if the text on both sides has the same
1066
+ // direction. European and Arabic numbers act as if they were R in
1067
+ // terms of their influence on neutrals. Start-of-level-run (sor)
1068
+ // and end-of-level-run (eor) are used at level run boundaries.
1069
+ // N2. Any remaining neutrals take the embedding direction.
1070
+ for (var i$6 = 0; i$6 < len; ++i$6) {
1071
+ if (isNeutral.test(types[i$6])) {
1072
+ var end$1 = (void 0)
1073
+ for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}
1074
+ var before = (i$6 ? types[i$6-1] : outerType) == "L"
1075
+ var after = (end$1 < len ? types[end$1] : outerType) == "L"
1076
+ var replace$1 = before || after ? "L" : "R"
1077
+ for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1 }
1078
+ i$6 = end$1 - 1
1079
+ }
1080
+ }
1081
+
1082
+ // Here we depart from the documented algorithm, in order to avoid
1083
+ // building up an actual levels array. Since there are only three
1084
+ // levels (0, 1, 2) in an implementation that doesn't take
1085
+ // explicit embedding into account, we can build up the order on
1086
+ // the fly, without following the level-based algorithm.
1087
+ var order = [], m
1088
+ for (var i$7 = 0; i$7 < len;) {
1089
+ if (countsAsLeft.test(types[i$7])) {
1090
+ var start = i$7
1091
+ for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}
1092
+ order.push(new BidiSpan(0, start, i$7))
1093
  } else {
1094
+ var pos = i$7, at = order.length
1095
+ for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {}
1096
+ for (var j$2 = pos; j$2 < i$7;) {
1097
+ if (countsAsNum.test(types[j$2])) {
1098
+ if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)) }
1099
+ var nstart = j$2
1100
+ for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}
1101
+ order.splice(at, 0, new BidiSpan(2, nstart, j$2))
1102
+ pos = j$2
1103
+ } else { ++j$2 }
1104
+ }
1105
+ if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)) }
1106
+ }
1107
+ }
1108
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
1109
+ order[0].from = m[0].length
1110
+ order.unshift(new BidiSpan(0, 0, m[0].length))
1111
+ }
1112
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
1113
+ lst(order).to -= m[0].length
1114
+ order.push(new BidiSpan(0, len - m[0].length, len))
1115
+ }
1116
+ if (order[0].level == 2)
1117
+ { order.unshift(new BidiSpan(1, order[0].to, order[0].to)) }
1118
+ if (order[0].level != lst(order).level)
1119
+ { order.push(new BidiSpan(order[0].level, len, len)) }
1120
+
1121
+ return order
1122
+ }
1123
+ })()
1124
+
1125
+ // Get the bidi ordering for the given line (and cache it). Returns
1126
+ // false for lines that are fully left-to-right, and an array of
1127
+ // BidiSpan objects otherwise.
1128
+ function getOrder(line) {
1129
+ var order = line.order
1130
+ if (order == null) { order = line.order = bidiOrdering(line.text) }
1131
+ return order
1132
+ }
1133
+
1134
+ // EVENT HANDLING
1135
+
1136
+ // Lightweight event framework. on/off also work on DOM nodes,
1137
+ // registering native DOM handlers.
1138
+
1139
+ var noHandlers = []
1140
+
1141
+ var on = function(emitter, type, f) {
1142
+ if (emitter.addEventListener) {
1143
+ emitter.addEventListener(type, f, false)
1144
+ } else if (emitter.attachEvent) {
1145
+ emitter.attachEvent("on" + type, f)
1146
+ } else {
1147
+ var map = emitter._handlers || (emitter._handlers = {})
1148
+ map[type] = (map[type] || noHandlers).concat(f)
1149
+ }
1150
+ }
1151
+
1152
+ function getHandlers(emitter, type) {
1153
+ return emitter._handlers && emitter._handlers[type] || noHandlers
1154
+ }
1155
+
1156
+ function off(emitter, type, f) {
1157
+ if (emitter.removeEventListener) {
1158
+ emitter.removeEventListener(type, f, false)
1159
+ } else if (emitter.detachEvent) {
1160
+ emitter.detachEvent("on" + type, f)
1161
+ } else {
1162
+ var map = emitter._handlers, arr = map && map[type]
1163
+ if (arr) {
1164
+ var index = indexOf(arr, f)
1165
+ if (index > -1)
1166
+ { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)) }
1167
+ }
1168
+ }
1169
+ }
1170
+
1171
+ function signal(emitter, type /*, values...*/) {
1172
+ var handlers = getHandlers(emitter, type)
1173
+ if (!handlers.length) { return }
1174
+ var args = Array.prototype.slice.call(arguments, 2)
1175
+ for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args) }
1176
+ }
1177
+
1178
+ // The DOM events that CodeMirror handles can be overridden by
1179
+ // registering a (non-DOM) handler on the editor for the event name,
1180
+ // and preventDefault-ing the event in that handler.
1181
+ function signalDOMEvent(cm, e, override) {
1182
+ if (typeof e == "string")
1183
+ { e = {type: e, preventDefault: function() { this.defaultPrevented = true }} }
1184
+ signal(cm, override || e.type, cm, e)
1185
+ return e_defaultPrevented(e) || e.codemirrorIgnore
1186
+ }
1187
+
1188
+ function signalCursorActivity(cm) {
1189
+ var arr = cm._handlers && cm._handlers.cursorActivity
1190
+ if (!arr) { return }
1191
+ var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = [])
1192
+ for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)
1193
+ { set.push(arr[i]) } }
1194
+ }
1195
+
1196
+ function hasHandler(emitter, type) {
1197
+ return getHandlers(emitter, type).length > 0
1198
+ }
1199
+
1200
+ // Add on and off methods to a constructor's prototype, to make
1201
+ // registering events on such objects more convenient.
1202
+ function eventMixin(ctor) {
1203
+ ctor.prototype.on = function(type, f) {on(this, type, f)}
1204
+ ctor.prototype.off = function(type, f) {off(this, type, f)}
1205
+ }
1206
+
1207
+ // Due to the fact that we still support jurassic IE versions, some
1208
+ // compatibility wrappers are needed.
1209
+
1210
+ function e_preventDefault(e) {
1211
+ if (e.preventDefault) { e.preventDefault() }
1212
+ else { e.returnValue = false }
1213
+ }
1214
+ function e_stopPropagation(e) {
1215
+ if (e.stopPropagation) { e.stopPropagation() }
1216
+ else { e.cancelBubble = true }
1217
+ }
1218
+ function e_defaultPrevented(e) {
1219
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
1220
+ }
1221
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)}
1222
+
1223
+ function e_target(e) {return e.target || e.srcElement}
1224
+ function e_button(e) {
1225
+ var b = e.which
1226
+ if (b == null) {
1227
+ if (e.button & 1) { b = 1 }
1228
+ else if (e.button & 2) { b = 3 }
1229
+ else if (e.button & 4) { b = 2 }
1230
+ }
1231
+ if (mac && e.ctrlKey && b == 1) { b = 3 }
1232
+ return b
1233
+ }
1234
+
1235
+ // Detect drag-and-drop
1236
+ var dragAndDrop = function() {
1237
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
1238
+ // couldn't get it to work yet.
1239
+ if (ie && ie_version < 9) { return false }
1240
+ var div = elt('div')
1241
+ return "draggable" in div || "dragDrop" in div
1242
+ }()
1243
+
1244
+ var zwspSupported
1245
+ function zeroWidthElement(measure) {
1246
+ if (zwspSupported == null) {
1247
+ var test = elt("span", "\u200b")
1248
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]))
1249
+ if (measure.firstChild.offsetHeight != 0)
1250
+ { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8) }
1251
+ }
1252
+ var node = zwspSupported ? elt("span", "\u200b") :
1253
+ elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px")
1254
+ node.setAttribute("cm-text", "")
1255
+ return node
1256
+ }
1257
+
1258
+ // Feature-detect IE's crummy client rect reporting for bidi text
1259
+ var badBidiRects
1260
+ function hasBadBidiRects(measure) {
1261
+ if (badBidiRects != null) { return badBidiRects }
1262
+ var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"))
1263
+ var r0 = range(txt, 0, 1).getBoundingClientRect()
1264
+ var r1 = range(txt, 1, 2).getBoundingClientRect()
1265
+ removeChildren(measure)
1266
+ if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)
1267
+ return badBidiRects = (r1.right - r0.right < 3)
1268
+ }
1269
+
1270
+ // See if "".split is the broken IE version, if so, provide an
1271
+ // alternative way to split lines.
1272
+ var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) {
1273
+ var pos = 0, result = [], l = string.length
1274
+ while (pos <= l) {
1275
+ var nl = string.indexOf("\n", pos)
1276
+ if (nl == -1) { nl = string.length }
1277
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl)
1278
+ var rt = line.indexOf("\r")
1279
+ if (rt != -1) {
1280
+ result.push(line.slice(0, rt))
1281
+ pos += rt + 1
1282
+ } else {
1283
+ result.push(line)
1284
+ pos = nl + 1
1285
+ }
1286
+ }
1287
+ return result
1288
+ } : function (string) { return string.split(/\r\n?|\n/); }
1289
+
1290
+ var hasSelection = window.getSelection ? function (te) {
1291
+ try { return te.selectionStart != te.selectionEnd }
1292
+ catch(e) { return false }
1293
+ } : function (te) {
1294
+ var range
1295
+ try {range = te.ownerDocument.selection.createRange()}
1296
+ catch(e) {}
1297
+ if (!range || range.parentElement() != te) { return false }
1298
+ return range.compareEndPoints("StartToEnd", range) != 0
1299
+ }
1300
+
1301
+ var hasCopyEvent = (function () {
1302
+ var e = elt("div")
1303
+ if ("oncopy" in e) { return true }
1304
+ e.setAttribute("oncopy", "return;")
1305
+ return typeof e.oncopy == "function"
1306
+ })()
1307
+
1308
+ var badZoomedRects = null
1309
+ function hasBadZoomedRects(measure) {
1310
+ if (badZoomedRects != null) { return badZoomedRects }
1311
+ var node = removeChildrenAndAdd(measure, elt("span", "x"))
1312
+ var normal = node.getBoundingClientRect()
1313
+ var fromRange = range(node, 0, 1).getBoundingClientRect()
1314
+ return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
1315
+ }
1316
+
1317
+ var modes = {};
1318
+ var mimeModes = {};
1319
+ // Extra arguments are stored as the mode's dependencies, which is
1320
+ // used by (legacy) mechanisms like loadmode.js to automatically
1321
+ // load a mode. (Preferred mechanism is the require/define calls.)
1322
+ function defineMode(name, mode) {
1323
+ if (arguments.length > 2)
1324
+ { mode.dependencies = Array.prototype.slice.call(arguments, 2) }
1325
+ modes[name] = mode
1326
+ }
1327
+
1328
+ function defineMIME(mime, spec) {
1329
+ mimeModes[mime] = spec
1330
+ }
1331
+
1332
+ // Given a MIME type, a {name, ...options} config object, or a name
1333
+ // string, return a mode config object.
1334
+ function resolveMode(spec) {
1335
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
1336
+ spec = mimeModes[spec]
1337
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
1338
+ var found = mimeModes[spec.name]
1339
+ if (typeof found == "string") { found = {name: found} }
1340
+ spec = createObj(found, spec)
1341
+ spec.name = found.name
1342
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
1343
+ return resolveMode("application/xml")
1344
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
1345
+ return resolveMode("application/json")
1346
+ }
1347
+ if (typeof spec == "string") { return {name: spec} }
1348
+ else { return spec || {name: "null"} }
1349
+ }
1350
+
1351
+ // Given a mode spec (anything that resolveMode accepts), find and
1352
+ // initialize an actual mode object.
1353
+ function getMode(options, spec) {
1354
+ spec = resolveMode(spec)
1355
+ var mfactory = modes[spec.name]
1356
+ if (!mfactory) { return getMode(options, "text/plain") }
1357
+ var modeObj = mfactory(options, spec)
1358
+ if (modeExtensions.hasOwnProperty(spec.name)) {
1359
+ var exts = modeExtensions[spec.name]
1360
+ for (var prop in exts) {
1361
+ if (!exts.hasOwnProperty(prop)) { continue }
1362
+ if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop] }
1363
+ modeObj[prop] = exts[prop]
1364
+ }
1365
+ }
1366
+ modeObj.name = spec.name
1367
+ if (spec.helperType) { modeObj.helperType = spec.helperType }
1368
+ if (spec.modeProps) { for (var prop$1 in spec.modeProps)
1369
+ { modeObj[prop$1] = spec.modeProps[prop$1] } }
1370
+
1371
+ return modeObj
1372
+ }
1373
+
1374
+ // This can be used to attach properties to mode objects from
1375
+ // outside the actual mode definition.
1376
+ var modeExtensions = {}
1377
+ function extendMode(mode, properties) {
1378
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {})
1379
+ copyObj(properties, exts)
1380
+ }
1381
+
1382
+ function copyState(mode, state) {
1383
+ if (state === true) { return state }
1384
+ if (mode.copyState) { return mode.copyState(state) }
1385
+ var nstate = {}
1386
+ for (var n in state) {
1387
+ var val = state[n]
1388
+ if (val instanceof Array) { val = val.concat([]) }
1389
+ nstate[n] = val
1390
+ }
1391
+ return nstate
1392
+ }
1393
+
1394
+ // Given a mode and a state (for that mode), find the inner mode and
1395
+ // state at the position that the state refers to.
1396
+ function innerMode(mode, state) {
1397
+ var info
1398
+ while (mode.innerMode) {
1399
+ info = mode.innerMode(state)
1400
+ if (!info || info.mode == mode) { break }
1401
+ state = info.state
1402
+ mode = info.mode
1403
+ }
1404
+ return info || {mode: mode, state: state}
1405
+ }
1406
+
1407
+ function startState(mode, a1, a2) {
1408
+ return mode.startState ? mode.startState(a1, a2) : true
1409
+ }
1410
+
1411
+ // STRING STREAM
1412
+
1413
+ // Fed to the mode parsers, provides helper functions to make
1414
+ // parsers more succinct.
1415
+
1416
+ var StringStream = function(string, tabSize) {
1417
+ this.pos = this.start = 0
1418
+ this.string = string
1419
+ this.tabSize = tabSize || 8
1420
+ this.lastColumnPos = this.lastColumnValue = 0
1421
+ this.lineStart = 0
1422
+ }
1423
+
1424
+ StringStream.prototype = {
1425
+ eol: function() {return this.pos >= this.string.length},
1426
+ sol: function() {return this.pos == this.lineStart},
1427
+ peek: function() {return this.string.charAt(this.pos) || undefined},
1428
+ next: function() {
1429
+ if (this.pos < this.string.length)
1430
+ { return this.string.charAt(this.pos++) }
1431
+ },
1432
+ eat: function(match) {
1433
+ var ch = this.string.charAt(this.pos)
1434
+ var ok
1435
+ if (typeof match == "string") { ok = ch == match }
1436
+ else { ok = ch && (match.test ? match.test(ch) : match(ch)) }
1437
+ if (ok) {++this.pos; return ch}
1438
+ },
1439
+ eatWhile: function(match) {
1440
+ var start = this.pos
1441
+ while (this.eat(match)){}
1442
+ return this.pos > start
1443
+ },
1444
+ eatSpace: function() {
1445
+ var this$1 = this;
1446
+
1447
+ var start = this.pos
1448
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos }
1449
+ return this.pos > start
1450
+ },
1451
+ skipToEnd: function() {this.pos = this.string.length},
1452
+ skipTo: function(ch) {
1453
+ var found = this.string.indexOf(ch, this.pos)
1454
+ if (found > -1) {this.pos = found; return true}
1455
+ },
1456
+ backUp: function(n) {this.pos -= n},
1457
+ column: function() {
1458
+ if (this.lastColumnPos < this.start) {
1459
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue)
1460
+ this.lastColumnPos = this.start
1461
+ }
1462
+ return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
1463
+ },
1464
+ indentation: function() {
1465
+ return countColumn(this.string, null, this.tabSize) -
1466
+ (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
1467
+ },
1468
+ match: function(pattern, consume, caseInsensitive) {
1469
+ if (typeof pattern == "string") {
1470
+ var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }
1471
+ var substr = this.string.substr(this.pos, pattern.length)
1472
+ if (cased(substr) == cased(pattern)) {
1473
+ if (consume !== false) { this.pos += pattern.length }
1474
+ return true
1475
  }
1476
+ } else {
1477
+ var match = this.string.slice(this.pos).match(pattern)
1478
+ if (match && match.index > 0) { return null }
1479
+ if (match && consume !== false) { this.pos += match[0].length }
1480
+ return match
1481
+ }
1482
+ },
1483
+ current: function(){return this.string.slice(this.start, this.pos)},
1484
+ hideFirstChars: function(n, inner) {
1485
+ this.lineStart += n
1486
+ try { return inner() }
1487
+ finally { this.lineStart -= n }
1488
+ }
1489
+ }
1490
+
1491
+ // Compute a style array (an array starting with a mode generation
1492
+ // -- for invalidation -- followed by pairs of end positions and
1493
+ // style strings), which is used to highlight the tokens on the
1494
+ // line.
1495
+ function highlightLine(cm, line, state, forceToEnd) {
1496
+ // A styles array always starts with a number identifying the
1497
+ // mode/overlays that it is based on (for easy invalidation).
1498
+ var st = [cm.state.modeGen], lineClasses = {}
1499
+ // Compute the base array of styles
1500
+ runMode(cm, line.text, cm.doc.mode, state, function (end, style) { return st.push(end, style); },
1501
+ lineClasses, forceToEnd)
1502
+
1503
+ // Run overlays, adjust style array.
1504
+ var loop = function ( o ) {
1505
+ var overlay = cm.state.overlays[o], i = 1, at = 0
1506
+ runMode(cm, line.text, overlay.mode, true, function (end, style) {
1507
+ var start = i
1508
+ // Ensure there's a token end at the current position, and that i points at it
1509
+ while (at < end) {
1510
+ var i_end = st[i]
1511
+ if (i_end > end)
1512
+ { st.splice(i, 1, end, st[i+1], i_end) }
1513
+ i += 2
1514
+ at = Math.min(end, i_end)
1515
+ }
1516
+ if (!style) { return }
1517
+ if (overlay.opaque) {
1518
+ st.splice(start, i - start, end, "overlay " + style)
1519
+ i = start + 2
1520
  } else {
1521
+ for (; start < i; start += 2) {
1522
+ var cur = st[start+1]
1523
+ st[start+1] = (cur ? cur + " " : "") + "overlay " + style
1524
+ }
1525
  }
1526
+ }, lineClasses)
1527
+ };
1528
 
1529
+ for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );
1530
+
1531
+ return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}
1532
+ }
1533
+
1534
+ function getLineStyles(cm, line, updateFrontier) {
1535
+ if (!line.styles || line.styles[0] != cm.state.modeGen) {
1536
+ var state = getStateBefore(cm, lineNo(line))
1537
+ var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state)
1538
+ line.stateAfter = state
1539
+ line.styles = result.styles
1540
+ if (result.classes) { line.styleClasses = result.classes }
1541
+ else if (line.styleClasses) { line.styleClasses = null }
1542
+ if (updateFrontier === cm.doc.frontier) { cm.doc.frontier++ }
1543
+ }
1544
+ return line.styles
1545
+ }
1546
+
1547
+ function getStateBefore(cm, n, precise) {
1548
+ var doc = cm.doc, display = cm.display
1549
+ if (!doc.mode.startState) { return true }
1550
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter
1551
+ if (!state) { state = startState(doc.mode) }
1552
+ else { state = copyState(doc.mode, state) }
1553
+ doc.iter(pos, n, function (line) {
1554
+ processLine(cm, line.text, state)
1555
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo
1556
+ line.stateAfter = save ? copyState(doc.mode, state) : null
1557
+ ++pos
1558
+ })
1559
+ if (precise) { doc.frontier = pos }
1560
+ return state
1561
+ }
1562
+
1563
+ // Lightweight form of highlight -- proceed over this line and
1564
+ // update state, but don't save a style array. Used for lines that
1565
+ // aren't currently visible.
1566
+ function processLine(cm, text, state, startAt) {
1567
+ var mode = cm.doc.mode
1568
+ var stream = new StringStream(text, cm.options.tabSize)
1569
+ stream.start = stream.pos = startAt || 0
1570
+ if (text == "") { callBlankLine(mode, state) }
1571
+ while (!stream.eol()) {
1572
+ readToken(mode, stream, state)
1573
+ stream.start = stream.pos
1574
+ }
1575
+ }
1576
+
1577
+ function callBlankLine(mode, state) {
1578
+ if (mode.blankLine) { return mode.blankLine(state) }
1579
+ if (!mode.innerMode) { return }
1580
+ var inner = innerMode(mode, state)
1581
+ if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }
1582
+ }
1583
+
1584
+ function readToken(mode, stream, state, inner) {
1585
+ for (var i = 0; i < 10; i++) {
1586
+ if (inner) { inner[0] = innerMode(mode, state).mode }
1587
+ var style = mode.token(stream, state)
1588
+ if (stream.pos > stream.start) { return style }
1589
+ }
1590
+ throw new Error("Mode " + mode.name + " failed to advance stream.")
1591
+ }
1592
+
1593
+ // Utility for getTokenAt and getLineTokens
1594
+ function takeToken(cm, pos, precise, asArray) {
1595
+ var getObj = function (copy) { return ({
1596
+ start: stream.start, end: stream.pos,
1597
+ string: stream.current(),
1598
+ type: style || null,
1599
+ state: copy ? copyState(doc.mode, state) : state
1600
+ }); }
1601
+
1602
+ var doc = cm.doc, mode = doc.mode, style
1603
+ pos = clipPos(doc, pos)
1604
+ var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise)
1605
+ var stream = new StringStream(line.text, cm.options.tabSize), tokens
1606
+ if (asArray) { tokens = [] }
1607
+ while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
1608
+ stream.start = stream.pos
1609
+ style = readToken(mode, stream, state)
1610
+ if (asArray) { tokens.push(getObj(true)) }
1611
+ }
1612
+ return asArray ? tokens : getObj()
1613
+ }
1614
+
1615
+ function extractLineClasses(type, output) {
1616
+ if (type) { for (;;) {
1617
+ var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/)
1618
+ if (!lineClass) { break }
1619
+ type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length)
1620
+ var prop = lineClass[1] ? "bgClass" : "textClass"
1621
+ if (output[prop] == null)
1622
+ { output[prop] = lineClass[2] }
1623
+ else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
1624
+ { output[prop] += " " + lineClass[2] }
1625
+ } }
1626
+ return type
1627
+ }
1628
+
1629
+ // Run the given mode's parser over a line, calling f for each token.
1630
+ function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
1631
+ var flattenSpans = mode.flattenSpans
1632
+ if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans }
1633
+ var curStart = 0, curStyle = null
1634
+ var stream = new StringStream(text, cm.options.tabSize), style
1635
+ var inner = cm.options.addModeClass && [null]
1636
+ if (text == "") { extractLineClasses(callBlankLine(mode, state), lineClasses) }
1637
+ while (!stream.eol()) {
1638
+ if (stream.pos > cm.options.maxHighlightLength) {
1639
+ flattenSpans = false
1640
+ if (forceToEnd) { processLine(cm, text, state, stream.pos) }
1641
+ stream.pos = text.length
1642
+ style = null
1643
+ } else {
1644
+ style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses)
1645
+ }
1646
+ if (inner) {
1647
+ var mName = inner[0].name
1648
+ if (mName) { style = "m-" + (style ? mName + " " + style : mName) }
1649
+ }
1650
+ if (!flattenSpans || curStyle != style) {
1651
+ while (curStart < stream.start) {
1652
+ curStart = Math.min(stream.start, curStart + 5000)
1653
+ f(curStart, curStyle)
1654
+ }
1655
+ curStyle = style
1656
+ }
1657
+ stream.start = stream.pos
1658
+ }
1659
+ while (curStart < stream.pos) {
1660
+ // Webkit seems to refuse to render text nodes longer than 57444
1661
+ // characters, and returns inaccurate measurements in nodes
1662
+ // starting around 5000 chars.
1663
+ var pos = Math.min(stream.pos, curStart + 5000)
1664
+ f(pos, curStyle)
1665
+ curStart = pos
1666
+ }
1667
+ }
1668
+
1669
+ // Finds the line to start with when starting a parse. Tries to
1670
+ // find a line with a stateAfter, so that it can start with a
1671
+ // valid state. If that fails, it returns the line with the
1672
+ // smallest indentation, which tends to need the least context to
1673
+ // parse correctly.
1674
+ function findStartLine(cm, n, precise) {
1675
+ var minindent, minline, doc = cm.doc
1676
+ var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100)
1677
+ for (var search = n; search > lim; --search) {
1678
+ if (search <= doc.first) { return doc.first }
1679
+ var line = getLine(doc, search - 1)
1680
+ if (line.stateAfter && (!precise || search <= doc.frontier)) { return search }
1681
+ var indented = countColumn(line.text, null, cm.options.tabSize)
1682
+ if (minline == null || minindent > indented) {
1683
+ minline = search - 1
1684
+ minindent = indented
1685
+ }
1686
+ }
1687
+ return minline
1688
+ }
1689
+
1690
+ // LINE DATA STRUCTURE
1691
+
1692
+ // Line objects. These hold state related to a line, including
1693
+ // highlighting info (the styles array).
1694
+ function Line(text, markedSpans, estimateHeight) {
1695
+ this.text = text
1696
+ attachMarkedSpans(this, markedSpans)
1697
+ this.height = estimateHeight ? estimateHeight(this) : 1
1698
+ }
1699
+ eventMixin(Line)
1700
+ Line.prototype.lineNo = function() { return lineNo(this) }
1701
+
1702
+ // Change the content (text, markers) of a line. Automatically
1703
+ // invalidates cached information and tries to re-estimate the
1704
+ // line's height.
1705
+ function updateLine(line, text, markedSpans, estimateHeight) {
1706
+ line.text = text
1707
+ if (line.stateAfter) { line.stateAfter = null }
1708
+ if (line.styles) { line.styles = null }
1709
+ if (line.order != null) { line.order = null }
1710
+ detachMarkedSpans(line)
1711
+ attachMarkedSpans(line, markedSpans)
1712
+ var estHeight = estimateHeight ? estimateHeight(line) : 1
1713
+ if (estHeight != line.height) { updateLineHeight(line, estHeight) }
1714
+ }
1715
+
1716
+ // Detach a line from the document tree and its markers.
1717
+ function cleanUpLine(line) {
1718
+ line.parent = null
1719
+ detachMarkedSpans(line)
1720
+ }
1721
+
1722
+ // Convert a style as returned by a mode (either null, or a string
1723
+ // containing one or more styles) to a CSS style. This is cached,
1724
+ // and also looks for line-wide styles.
1725
+ var styleToClassCache = {};
1726
+ var styleToClassCacheWithMode = {};
1727
+ function interpretTokenStyle(style, options) {
1728
+ if (!style || /^\s*$/.test(style)) { return null }
1729
+ var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache
1730
+ return cache[style] ||
1731
+ (cache[style] = style.replace(/\S+/g, "cm-$&"))
1732
+ }
1733
+
1734
+ // Render the DOM representation of the text of a line. Also builds
1735
+ // up a 'line map', which points at the DOM nodes that represent
1736
+ // specific stretches of text, and is used by the measuring code.
1737
+ // The returned object contains the DOM node, this map, and
1738
+ // information about line-wide styles that were set by the mode.
1739
+ function buildLineContent(cm, lineView) {
1740
+ // The padding-right forces the element to have a 'border', which
1741
+ // is needed on Webkit to be able to get line-level bounding
1742
+ // rectangles for it (in measureChar).
1743
+ var content = elt("span", null, null, webkit ? "padding-right: .1px" : null)
1744
+ var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
1745
+ col: 0, pos: 0, cm: cm,
1746
+ trailingSpace: false,
1747
+ splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")}
1748
+ // hide from accessibility tree
1749
+ content.setAttribute("role", "presentation")
1750
+ builder.pre.setAttribute("role", "presentation")
1751
+ lineView.measure = {}
1752
+
1753
+ // Iterate over the logical lines that make up this visual line.
1754
+ for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
1755
+ var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0)
1756
+ builder.pos = 0
1757
+ builder.addToken = buildToken
1758
+ // Optionally wire in some hacks into the token-rendering
1759
+ // algorithm, to deal with browser quirks.
1760
+ if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
1761
+ { builder.addToken = buildTokenBadBidi(builder.addToken, order) }
1762
+ builder.map = []
1763
+ var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line)
1764
+ insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate))
1765
+ if (line.styleClasses) {
1766
+ if (line.styleClasses.bgClass)
1767
+ { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "") }
1768
+ if (line.styleClasses.textClass)
1769
+ { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "") }
1770
+ }
1771
+
1772
+ // Ensure at least a single node is present, for measuring.
1773
+ if (builder.map.length == 0)
1774
+ { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))) }
1775
+
1776
+ // Store the map and a cache object for the current logical line
1777
+ if (i == 0) {
1778
+ lineView.measure.map = builder.map
1779
+ lineView.measure.cache = {}
1780
+ } else {
1781
+ ;(lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)
1782
+ ;(lineView.measure.caches || (lineView.measure.caches = [])).push({})
1783
+ }
1784
+ }
1785
+
1786
+ // See issue #2901
1787
+ if (webkit) {
1788
+ var last = builder.content.lastChild
1789
+ if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
1790
+ { builder.content.className = "cm-tab-wrap-hack" }
1791
+ }
1792
+
1793
+ signal(cm, "renderLine", cm, lineView.line, builder.pre)
1794
+ if (builder.pre.className)
1795
+ { builder.textClass = joinClasses(builder.pre.className, builder.textClass || "") }
1796
+
1797
+ return builder
1798
+ }
1799
+
1800
+ function defaultSpecialCharPlaceholder(ch) {
1801
+ var token = elt("span", "\u2022", "cm-invalidchar")
1802
+ token.title = "\\u" + ch.charCodeAt(0).toString(16)
1803
+ token.setAttribute("aria-label", token.title)
1804
+ return token
1805
+ }
1806
+
1807
+ // Build up the DOM representation for a single token, and add it to
1808
+ // the line map. Takes care to render special characters separately.
1809
+ function buildToken(builder, text, style, startStyle, endStyle, title, css) {
1810
+ if (!text) { return }
1811
+ var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text
1812
+ var special = builder.cm.state.specialChars, mustWrap = false
1813
+ var content
1814
+ if (!special.test(text)) {
1815
+ builder.col += text.length
1816
+ content = document.createTextNode(displayText)
1817
+ builder.map.push(builder.pos, builder.pos + text.length, content)
1818
+ if (ie && ie_version < 9) { mustWrap = true }
1819
+ builder.pos += text.length
1820
+ } else {
1821
+ content = document.createDocumentFragment()
1822
+ var pos = 0
1823
+ while (true) {
1824
+ special.lastIndex = pos
1825
+ var m = special.exec(text)
1826
+ var skipped = m ? m.index - pos : text.length - pos
1827
+ if (skipped) {
1828
+ var txt = document.createTextNode(displayText.slice(pos, pos + skipped))
1829
+ if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])) }
1830
+ else { content.appendChild(txt) }
1831
+ builder.map.push(builder.pos, builder.pos + skipped, txt)
1832
+ builder.col += skipped
1833
+ builder.pos += skipped
1834
+ }
1835
+ if (!m) { break }
1836
+ pos += skipped + 1
1837
+ var txt$1 = (void 0)
1838
+ if (m[0] == "\t") {
1839
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize
1840
+ txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"))
1841
+ txt$1.setAttribute("role", "presentation")
1842
+ txt$1.setAttribute("cm-text", "\t")
1843
+ builder.col += tabWidth
1844
+ } else if (m[0] == "\r" || m[0] == "\n") {
1845
+ txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"))
1846
+ txt$1.setAttribute("cm-text", m[0])
1847
+ builder.col += 1
1848
+ } else {
1849
+ txt$1 = builder.cm.options.specialCharPlaceholder(m[0])
1850
+ txt$1.setAttribute("cm-text", m[0])
1851
+ if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])) }
1852
+ else { content.appendChild(txt$1) }
1853
+ builder.col += 1
1854
+ }
1855
+ builder.map.push(builder.pos, builder.pos + 1, txt$1)
1856
+ builder.pos++
1857
+ }
1858
+ }
1859
+ builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32
1860
+ if (style || startStyle || endStyle || mustWrap || css) {
1861
+ var fullStyle = style || ""
1862
+ if (startStyle) { fullStyle += startStyle }
1863
+ if (endStyle) { fullStyle += endStyle }
1864
+ var token = elt("span", [content], fullStyle, css)
1865
+ if (title) { token.title = title }
1866
+ return builder.content.appendChild(token)
1867
+ }
1868
+ builder.content.appendChild(content)
1869
+ }
1870
+
1871
+ function splitSpaces(text, trailingBefore) {
1872
+ if (text.length > 1 && !/ /.test(text)) { return text }
1873
+ var spaceBefore = trailingBefore, result = ""
1874
+ for (var i = 0; i < text.length; i++) {
1875
+ var ch = text.charAt(i)
1876
+ if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
1877
+ { ch = "\u00a0" }
1878
+ result += ch
1879
+ spaceBefore = ch == " "
1880
+ }
1881
+ return result
1882
+ }
1883
+
1884
+ // Work around nonsense dimensions being reported for stretches of
1885
+ // right-to-left text.
1886
+ function buildTokenBadBidi(inner, order) {
1887
+ return function (builder, text, style, startStyle, endStyle, title, css) {
1888
+ style = style ? style + " cm-force-border" : "cm-force-border"
1889
+ var start = builder.pos, end = start + text.length
1890
+ for (;;) {
1891
+ // Find the part that overlaps with the start of this text
1892
+ var part = (void 0)
1893
+ for (var i = 0; i < order.length; i++) {
1894
+ part = order[i]
1895
+ if (part.to > start && part.from <= start) { break }
1896
+ }
1897
+ if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, title, css) }
1898
+ inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css)
1899
+ startStyle = null
1900
+ text = text.slice(part.to - start)
1901
+ start = part.to
1902
+ }
1903
+ }
1904
+ }
1905
+
1906
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
1907
+ var widget = !ignoreWidget && marker.widgetNode
1908
+ if (widget) { builder.map.push(builder.pos, builder.pos + size, widget) }
1909
+ if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
1910
+ if (!widget)
1911
+ { widget = builder.content.appendChild(document.createElement("span")) }
1912
+ widget.setAttribute("cm-marker", marker.id)
1913
+ }
1914
+ if (widget) {
1915
+ builder.cm.display.input.setUneditable(widget)
1916
+ builder.content.appendChild(widget)
1917
+ }
1918
+ builder.pos += size
1919
+ builder.trailingSpace = false
1920
+ }
1921
+
1922
+ // Outputs a number of spans to make up a line, taking highlighting
1923
+ // and marked text into account.
1924
+ function insertLineContent(line, builder, styles) {
1925
+ var spans = line.markedSpans, allText = line.text, at = 0
1926
+ if (!spans) {
1927
+ for (var i$1 = 1; i$1 < styles.length; i$1+=2)
1928
+ { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)) }
1929
+ return
1930
+ }
1931
+
1932
+ var len = allText.length, pos = 0, i = 1, text = "", style, css
1933
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed
1934
+ for (;;) {
1935
+ if (nextChange == pos) { // Update current marker set
1936
+ spanStyle = spanEndStyle = spanStartStyle = title = css = ""
1937
+ collapsed = null; nextChange = Infinity
1938
+ var foundBookmarks = [], endStyles = (void 0)
1939
+ for (var j = 0; j < spans.length; ++j) {
1940
+ var sp = spans[j], m = sp.marker
1941
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
1942
+ foundBookmarks.push(m)
1943
+ } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
1944
+ if (sp.to != null && sp.to != pos && nextChange > sp.to) {
1945
+ nextChange = sp.to
1946
+ spanEndStyle = ""
1947
+ }
1948
+ if (m.className) { spanStyle += " " + m.className }
1949
+ if (m.css) { css = (css ? css + ";" : "") + m.css }
1950
+ if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle }
1951
+ if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to) }
1952
+ if (m.title && !title) { title = m.title }
1953
+ if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
1954
+ { collapsed = sp }
1955
+ } else if (sp.from > pos && nextChange > sp.from) {
1956
+ nextChange = sp.from
1957
+ }
1958
  }
1959
+ if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)
1960
+ { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1] } } }
1961
 
1962
+ if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)
1963
+ { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]) } }
1964
+ if (collapsed && (collapsed.from || 0) == pos) {
1965
+ buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
1966
+ collapsed.marker, collapsed.from == null)
1967
+ if (collapsed.to == null) { return }
1968
+ if (collapsed.to == pos) { collapsed = false }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1969
  }
1970
  }
1971
+ if (pos >= len) { break }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1972
 
1973
+ var upto = Math.min(len, nextChange)
1974
+ while (true) {
1975
+ if (text) {
1976
+ var end = pos + text.length
1977
+ if (!collapsed) {
1978
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text
1979
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
1980
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css)
1981
+ }
1982
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
1983
+ pos = end
1984
+ spanStartStyle = ""
1985
+ }
1986
+ text = allText.slice(at, at = styles[i++])
1987
+ style = interpretTokenStyle(styles[i++], builder.cm.options)
1988
+ }
1989
+ }
1990
+ }
1991
+
1992
+
1993
+ // These objects are used to represent the visible (currently drawn)
1994
+ // part of the document. A LineView may correspond to multiple
1995
+ // logical lines, if those are connected by collapsed ranges.
1996
+ function LineView(doc, line, lineN) {
1997
+ // The starting line
1998
+ this.line = line
1999
+ // Continuing lines, if any
2000
+ this.rest = visualLineContinued(line)
2001
+ // Number of logical lines in this visual line
2002
+ this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1
2003
+ this.node = this.text = null
2004
+ this.hidden = lineIsHidden(doc, line)
2005
+ }
2006
+
2007
+ // Create a range of LineView objects for the given lines.
2008
+ function buildViewArray(cm, from, to) {
2009
+ var array = [], nextPos
2010
+ for (var pos = from; pos < to; pos = nextPos) {
2011
+ var view = new LineView(cm.doc, getLine(cm.doc, pos), pos)
2012
+ nextPos = pos + view.size
2013
+ array.push(view)
2014
+ }
2015
+ return array
2016
+ }
2017
+
2018
+ var operationGroup = null
2019
+
2020
+ function pushOperation(op) {
2021
+ if (operationGroup) {
2022
+ operationGroup.ops.push(op)
2023
+ } else {
2024
+ op.ownsGroup = operationGroup = {
2025
+ ops: [op],
2026
+ delayedCallbacks: []
2027
+ }
2028
+ }
2029
+ }
2030
+
2031
+ function fireCallbacksForOps(group) {
2032
+ // Calls delayed callbacks and cursorActivity handlers until no
2033
+ // new ones appear
2034
+ var callbacks = group.delayedCallbacks, i = 0
2035
+ do {
2036
+ for (; i < callbacks.length; i++)
2037
+ { callbacks[i].call(null) }
2038
+ for (var j = 0; j < group.ops.length; j++) {
2039
+ var op = group.ops[j]
2040
+ if (op.cursorActivityHandlers)
2041
+ { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
2042
+ { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm) } }
2043
+ }
2044
+ } while (i < callbacks.length)
2045
+ }
2046
+
2047
+ function finishOperation(op, endCb) {
2048
+ var group = op.ownsGroup
2049
+ if (!group) { return }
2050
+
2051
+ try { fireCallbacksForOps(group) }
2052
+ finally {
2053
+ operationGroup = null
2054
+ endCb(group)
2055
+ }
2056
+ }
2057
+
2058
+ var orphanDelayedCallbacks = null
2059
+
2060
+ // Often, we want to signal events at a point where we are in the
2061
+ // middle of some work, but don't want the handler to start calling
2062
+ // other methods on the editor, which might be in an inconsistent
2063
+ // state or simply not expect any other events to happen.
2064
+ // signalLater looks whether there are any handlers, and schedules
2065
+ // them to be executed when the last operation ends, or, if no
2066
+ // operation is active, when a timeout fires.
2067
+ function signalLater(emitter, type /*, values...*/) {
2068
+ var arr = getHandlers(emitter, type)
2069
+ if (!arr.length) { return }
2070
+ var args = Array.prototype.slice.call(arguments, 2), list
2071
+ if (operationGroup) {
2072
+ list = operationGroup.delayedCallbacks
2073
+ } else if (orphanDelayedCallbacks) {
2074
+ list = orphanDelayedCallbacks
2075
+ } else {
2076
+ list = orphanDelayedCallbacks = []
2077
+ setTimeout(fireOrphanDelayed, 0)
2078
+ }
2079
+ var loop = function ( i ) {
2080
+ list.push(function () { return arr[i].apply(null, args); })
2081
+ };
2082
 
2083
+ for (var i = 0; i < arr.length; ++i)
2084
+ loop( i );
2085
+ }
2086
+
2087
+ function fireOrphanDelayed() {
2088
+ var delayed = orphanDelayedCallbacks
2089
+ orphanDelayedCallbacks = null
2090
+ for (var i = 0; i < delayed.length; ++i) { delayed[i]() }
2091
+ }
2092
+
2093
+ // When an aspect of a line changes, a string is added to
2094
+ // lineView.changes. This updates the relevant part of the line's
2095
+ // DOM structure.
2096
+ function updateLineForChanges(cm, lineView, lineN, dims) {
2097
+ for (var j = 0; j < lineView.changes.length; j++) {
2098
+ var type = lineView.changes[j]
2099
+ if (type == "text") { updateLineText(cm, lineView) }
2100
+ else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims) }
2101
+ else if (type == "class") { updateLineClasses(lineView) }
2102
+ else if (type == "widget") { updateLineWidgets(cm, lineView, dims) }
2103
+ }
2104
+ lineView.changes = null
2105
+ }
2106
+
2107
+ // Lines with gutter elements, widgets or a background class need to
2108
+ // be wrapped, and have the extra elements added to the wrapper div
2109
+ function ensureLineWrapped(lineView) {
2110
+ if (lineView.node == lineView.text) {
2111
+ lineView.node = elt("div", null, null, "position: relative")
2112
+ if (lineView.text.parentNode)
2113
+ { lineView.text.parentNode.replaceChild(lineView.node, lineView.text) }
2114
+ lineView.node.appendChild(lineView.text)
2115
+ if (ie && ie_version < 8) { lineView.node.style.zIndex = 2 }
2116
+ }
2117
+ return lineView.node
2118
+ }
2119
+
2120
+ function updateLineBackground(lineView) {
2121
+ var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass
2122
+ if (cls) { cls += " CodeMirror-linebackground" }
2123
+ if (lineView.background) {
2124
+ if (cls) { lineView.background.className = cls }
2125
+ else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null }
2126
+ } else if (cls) {
2127
+ var wrap = ensureLineWrapped(lineView)
2128
+ lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild)
2129
+ }
2130
+ }
2131
+
2132
+ // Wrapper around buildLineContent which will reuse the structure
2133
+ // in display.externalMeasured when possible.
2134
+ function getLineContent(cm, lineView) {
2135
+ var ext = cm.display.externalMeasured
2136
+ if (ext && ext.line == lineView.line) {
2137
+ cm.display.externalMeasured = null
2138
+ lineView.measure = ext.measure
2139
+ return ext.built
2140
+ }
2141
+ return buildLineContent(cm, lineView)
2142
+ }
2143
+
2144
+ // Redraw the line's text. Interacts with the background and text
2145
+ // classes because the mode may output tokens that influence these
2146
+ // classes.
2147
+ function updateLineText(cm, lineView) {
2148
+ var cls = lineView.text.className
2149
+ var built = getLineContent(cm, lineView)
2150
+ if (lineView.text == lineView.node) { lineView.node = built.pre }
2151
+ lineView.text.parentNode.replaceChild(built.pre, lineView.text)
2152
+ lineView.text = built.pre
2153
+ if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
2154
+ lineView.bgClass = built.bgClass
2155
+ lineView.textClass = built.textClass
2156
+ updateLineClasses(lineView)
2157
+ } else if (cls) {
2158
+ lineView.text.className = cls
2159
+ }
2160
+ }
2161
+
2162
+ function updateLineClasses(lineView) {
2163
+ updateLineBackground(lineView)
2164
+ if (lineView.line.wrapClass)
2165
+ { ensureLineWrapped(lineView).className = lineView.line.wrapClass }
2166
+ else if (lineView.node != lineView.text)
2167
+ { lineView.node.className = "" }
2168
+ var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass
2169
+ lineView.text.className = textClass || ""
2170
+ }
2171
+
2172
+ function updateLineGutter(cm, lineView, lineN, dims) {
2173
+ if (lineView.gutter) {
2174
+ lineView.node.removeChild(lineView.gutter)
2175
+ lineView.gutter = null
2176
+ }
2177
+ if (lineView.gutterBackground) {
2178
+ lineView.node.removeChild(lineView.gutterBackground)
2179
+ lineView.gutterBackground = null
2180
+ }
2181
+ if (lineView.line.gutterClass) {
2182
+ var wrap = ensureLineWrapped(lineView)
2183
+ lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
2184
+ ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px"))
2185
+ wrap.insertBefore(lineView.gutterBackground, lineView.text)
2186
+ }
2187
+ var markers = lineView.line.gutterMarkers
2188
+ if (cm.options.lineNumbers || markers) {
2189
+ var wrap$1 = ensureLineWrapped(lineView)
2190
+ var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"))
2191
+ cm.display.input.setUneditable(gutterWrap)
2192
+ wrap$1.insertBefore(gutterWrap, lineView.text)
2193
+ if (lineView.line.gutterClass)
2194
+ { gutterWrap.className += " " + lineView.line.gutterClass }
2195
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
2196
+ { lineView.lineNumber = gutterWrap.appendChild(
2197
+ elt("div", lineNumberFor(cm.options, lineN),
2198
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
2199
+ ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))) }
2200
+ if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) {
2201
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]
2202
+ if (found)
2203
+ { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt",
2204
+ ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))) }
2205
+ } }
2206
+ }
2207
+ }
2208
+
2209
+ function updateLineWidgets(cm, lineView, dims) {
2210
+ if (lineView.alignable) { lineView.alignable = null }
2211
+ for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {
2212
+ next = node.nextSibling
2213
+ if (node.className == "CodeMirror-linewidget")
2214
+ { lineView.node.removeChild(node) }
2215
+ }
2216
+ insertLineWidgets(cm, lineView, dims)
2217
+ }
2218
+
2219
+ // Build a line's DOM representation from scratch
2220
+ function buildLineElement(cm, lineView, lineN, dims) {
2221
+ var built = getLineContent(cm, lineView)
2222
+ lineView.text = lineView.node = built.pre
2223
+ if (built.bgClass) { lineView.bgClass = built.bgClass }
2224
+ if (built.textClass) { lineView.textClass = built.textClass }
2225
+
2226
+ updateLineClasses(lineView)
2227
+ updateLineGutter(cm, lineView, lineN, dims)
2228
+ insertLineWidgets(cm, lineView, dims)
2229
+ return lineView.node
2230
+ }
2231
+
2232
+ // A lineView may contain multiple logical lines (when merged by
2233
+ // collapsed spans). The widgets for all of them need to be drawn.
2234
+ function insertLineWidgets(cm, lineView, dims) {
2235
+ insertLineWidgetsFor(cm, lineView.line, lineView, dims, true)
2236
+ if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
2237
+ { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false) } }
2238
+ }
2239
+
2240
+ function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
2241
+ if (!line.widgets) { return }
2242
+ var wrap = ensureLineWrapped(lineView)
2243
+ for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
2244
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget")
2245
+ if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true") }
2246
+ positionLineWidget(widget, node, lineView, dims)
2247
+ cm.display.input.setUneditable(node)
2248
+ if (allowAbove && widget.above)
2249
+ { wrap.insertBefore(node, lineView.gutter || lineView.text) }
2250
+ else
2251
+ { wrap.appendChild(node) }
2252
+ signalLater(widget, "redraw")
2253
+ }
2254
+ }
2255
+
2256
+ function positionLineWidget(widget, node, lineView, dims) {
2257
+ if (widget.noHScroll) {
2258
+ ;(lineView.alignable || (lineView.alignable = [])).push(node)
2259
+ var width = dims.wrapperWidth
2260
+ node.style.left = dims.fixedPos + "px"
2261
+ if (!widget.coverGutter) {
2262
+ width -= dims.gutterTotalWidth
2263
+ node.style.paddingLeft = dims.gutterTotalWidth + "px"
2264
+ }
2265
+ node.style.width = width + "px"
2266
+ }
2267
+ if (widget.coverGutter) {
2268
+ node.style.zIndex = 5
2269
+ node.style.position = "relative"
2270
+ if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px" }
2271
+ }
2272
+ }
2273
+
2274
+ function widgetHeight(widget) {
2275
+ if (widget.height != null) { return widget.height }
2276
+ var cm = widget.doc.cm
2277
+ if (!cm) { return 0 }
2278
+ if (!contains(document.body, widget.node)) {
2279
+ var parentStyle = "position: relative;"
2280
+ if (widget.coverGutter)
2281
+ { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;" }
2282
+ if (widget.noHScroll)
2283
+ { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;" }
2284
+ removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle))
2285
+ }
2286
+ return widget.height = widget.node.parentNode.offsetHeight
2287
+ }
2288
+
2289
+ // Return true when the given mouse event happened in a widget
2290
+ function eventInWidget(display, e) {
2291
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
2292
+ if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
2293
+ (n.parentNode == display.sizer && n != display.mover))
2294
+ { return true }
2295
+ }
2296
+ }
2297
+
2298
+ // POSITION MEASUREMENT
2299
+
2300
+ function paddingTop(display) {return display.lineSpace.offsetTop}
2301
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}
2302
+ function paddingH(display) {
2303
+ if (display.cachedPaddingH) { return display.cachedPaddingH }
2304
+ var e = removeChildrenAndAdd(display.measure, elt("pre", "x"))
2305
+ var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle
2306
+ var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}
2307
+ if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data }
2308
+ return data
2309
+ }
2310
+
2311
+ function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }
2312
+ function displayWidth(cm) {
2313
+ return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth
2314
+ }
2315
+ function displayHeight(cm) {
2316
+ return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight
2317
+ }
2318
+
2319
+ // Ensure the lineView.wrapping.heights array is populated. This is
2320
+ // an array of bottom offsets for the lines that make up a drawn
2321
+ // line. When lineWrapping is on, there might be more than one
2322
+ // height.
2323
+ function ensureLineHeights(cm, lineView, rect) {
2324
+ var wrapping = cm.options.lineWrapping
2325
+ var curWidth = wrapping && displayWidth(cm)
2326
+ if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
2327
+ var heights = lineView.measure.heights = []
2328
+ if (wrapping) {
2329
+ lineView.measure.width = curWidth
2330
+ var rects = lineView.text.firstChild.getClientRects()
2331
+ for (var i = 0; i < rects.length - 1; i++) {
2332
+ var cur = rects[i], next = rects[i + 1]
2333
+ if (Math.abs(cur.bottom - next.bottom) > 2)
2334
+ { heights.push((cur.bottom + next.top) / 2 - rect.top) }
2335
+ }
2336
+ }
2337
+ heights.push(rect.bottom - rect.top)
2338
+ }
2339
+ }
2340
+
2341
+ // Find a line map (mapping character offsets to text nodes) and a
2342
+ // measurement cache for the given line number. (A line view might
2343
+ // contain multiple lines when collapsed ranges are present.)
2344
+ function mapFromLineView(lineView, line, lineN) {
2345
+ if (lineView.line == line)
2346
+ { return {map: lineView.measure.map, cache: lineView.measure.cache} }
2347
+ for (var i = 0; i < lineView.rest.length; i++)
2348
+ { if (lineView.rest[i] == line)
2349
+ { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
2350
+ for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
2351
+ { if (lineNo(lineView.rest[i$1]) > lineN)
2352
+ { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
2353
+ }
2354
+
2355
+ // Render a line into the hidden node display.externalMeasured. Used
2356
+ // when measurement is needed for a line that's not in the viewport.
2357
+ function updateExternalMeasurement(cm, line) {
2358
+ line = visualLine(line)
2359
+ var lineN = lineNo(line)
2360
+ var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN)
2361
+ view.lineN = lineN
2362
+ var built = view.built = buildLineContent(cm, view)
2363
+ view.text = built.pre
2364
+ removeChildrenAndAdd(cm.display.lineMeasure, built.pre)
2365
+ return view
2366
+ }
2367
+
2368
+ // Get a {top, bottom, left, right} box (in line-local coordinates)
2369
+ // for a given character.
2370
+ function measureChar(cm, line, ch, bias) {
2371
+ return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)
2372
+ }
2373
+
2374
+ // Find a line view that corresponds to the given line number.
2375
+ function findViewForLine(cm, lineN) {
2376
+ if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
2377
+ { return cm.display.view[findViewIndex(cm, lineN)] }
2378
+ var ext = cm.display.externalMeasured
2379
+ if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
2380
+ { return ext }
2381
+ }
2382
+
2383
+ // Measurement can be split in two steps, the set-up work that
2384
+ // applies to the whole line, and the measurement of the actual
2385
+ // character. Functions like coordsChar, that need to do a lot of
2386
+ // measurements in a row, can thus ensure that the set-up work is
2387
+ // only done once.
2388
+ function prepareMeasureForLine(cm, line) {
2389
+ var lineN = lineNo(line)
2390
+ var view = findViewForLine(cm, lineN)
2391
+ if (view && !view.text) {
2392
+ view = null
2393
+ } else if (view && view.changes) {
2394
+ updateLineForChanges(cm, view, lineN, getDimensions(cm))
2395
+ cm.curOp.forceUpdate = true
2396
+ }
2397
+ if (!view)
2398
+ { view = updateExternalMeasurement(cm, line) }
2399
+
2400
+ var info = mapFromLineView(view, line, lineN)
2401
+ return {
2402
+ line: line, view: view, rect: null,
2403
+ map: info.map, cache: info.cache, before: info.before,
2404
+ hasHeights: false
2405
+ }
2406
+ }
2407
+
2408
+ // Given a prepared measurement object, measures the position of an
2409
+ // actual character (or fetches it from the cache).
2410
+ function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
2411
+ if (prepared.before) { ch = -1 }
2412
+ var key = ch + (bias || ""), found
2413
+ if (prepared.cache.hasOwnProperty(key)) {
2414
+ found = prepared.cache[key]
2415
+ } else {
2416
+ if (!prepared.rect)
2417
+ { prepared.rect = prepared.view.text.getBoundingClientRect() }
2418
+ if (!prepared.hasHeights) {
2419
+ ensureLineHeights(cm, prepared.view, prepared.rect)
2420
+ prepared.hasHeights = true
2421
+ }
2422
+ found = measureCharInner(cm, prepared, ch, bias)
2423
+ if (!found.bogus) { prepared.cache[key] = found }
2424
+ }
2425
+ return {left: found.left, right: found.right,
2426
+ top: varHeight ? found.rtop : found.top,
2427
+ bottom: varHeight ? found.rbottom : found.bottom}
2428
+ }
2429
+
2430
+ var nullRect = {left: 0, right: 0, top: 0, bottom: 0}
2431
+
2432
+ function nodeAndOffsetInLineMap(map, ch, bias) {
2433
+ var node, start, end, collapse, mStart, mEnd
2434
+ // First, search the line map for the text node corresponding to,
2435
+ // or closest to, the target character.
2436
+ for (var i = 0; i < map.length; i += 3) {
2437
+ mStart = map[i]
2438
+ mEnd = map[i + 1]
2439
+ if (ch < mStart) {
2440
+ start = 0; end = 1
2441
+ collapse = "left"
2442
+ } else if (ch < mEnd) {
2443
+ start = ch - mStart
2444
+ end = start + 1
2445
+ } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
2446
+ end = mEnd - mStart
2447
+ start = end - 1
2448
+ if (ch >= mEnd) { collapse = "right" }
2449
+ }
2450
+ if (start != null) {
2451
+ node = map[i + 2]
2452
+ if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
2453
+ { collapse = bias }
2454
+ if (bias == "left" && start == 0)
2455
+ { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
2456
+ node = map[(i -= 3) + 2]
2457
+ collapse = "left"
2458
+ } }
2459
+ if (bias == "right" && start == mEnd - mStart)
2460
+ { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
2461
+ node = map[(i += 3) + 2]
2462
+ collapse = "right"
2463
+ } }
2464
+ break
2465
+ }
2466
+ }
2467
+ return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}
2468
+ }
2469
+
2470
+ function getUsefulRect(rects, bias) {
2471
+ var rect = nullRect
2472
+ if (bias == "left") { for (var i = 0; i < rects.length; i++) {
2473
+ if ((rect = rects[i]).left != rect.right) { break }
2474
+ } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {
2475
+ if ((rect = rects[i$1]).left != rect.right) { break }
2476
+ } }
2477
+ return rect
2478
+ }
2479
+
2480
+ function measureCharInner(cm, prepared, ch, bias) {
2481
+ var place = nodeAndOffsetInLineMap(prepared.map, ch, bias)
2482
+ var node = place.node, start = place.start, end = place.end, collapse = place.collapse
2483
+
2484
+ var rect
2485
+ if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
2486
+ for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned
2487
+ while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start }
2488
+ while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end }
2489
+ if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
2490
+ { rect = node.parentNode.getBoundingClientRect() }
2491
+ else
2492
+ { rect = getUsefulRect(range(node, start, end).getClientRects(), bias) }
2493
+ if (rect.left || rect.right || start == 0) { break }
2494
+ end = start
2495
+ start = start - 1
2496
+ collapse = "right"
2497
+ }
2498
+ if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect) }
2499
+ } else { // If it is a widget, simply get the box for the whole widget.
2500
+ if (start > 0) { collapse = bias = "right" }
2501
+ var rects
2502
+ if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
2503
+ { rect = rects[bias == "right" ? rects.length - 1 : 0] }
2504
+ else
2505
+ { rect = node.getBoundingClientRect() }
2506
  }
2507
+ if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
2508
+ var rSpan = node.parentNode.getClientRects()[0]
2509
+ if (rSpan)
2510
+ { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom} }
2511
+ else
2512
+ { rect = nullRect }
2513
+ }
2514
+
2515
+ var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top
2516
+ var mid = (rtop + rbot) / 2
2517
+ var heights = prepared.view.measure.heights
2518
+ var i = 0
2519
+ for (; i < heights.length - 1; i++)
2520
+ { if (mid < heights[i]) { break } }
2521
+ var top = i ? heights[i - 1] : 0, bot = heights[i]
2522
+ var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
2523
+ right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
2524
+ top: top, bottom: bot}
2525
+ if (!rect.left && !rect.right) { result.bogus = true }
2526
+ if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot }
2527
+
2528
+ return result
2529
+ }
2530
+
2531
+ // Work around problem with bounding client rects on ranges being
2532
+ // returned incorrectly when zoomed on IE10 and below.
2533
+ function maybeUpdateRectForZooming(measure, rect) {
2534
+ if (!window.screen || screen.logicalXDPI == null ||
2535
+ screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
2536
+ { return rect }
2537
+ var scaleX = screen.logicalXDPI / screen.deviceXDPI
2538
+ var scaleY = screen.logicalYDPI / screen.deviceYDPI
2539
+ return {left: rect.left * scaleX, right: rect.right * scaleX,
2540
+ top: rect.top * scaleY, bottom: rect.bottom * scaleY}
2541
+ }
2542
+
2543
+ function clearLineMeasurementCacheFor(lineView) {
2544
+ if (lineView.measure) {
2545
+ lineView.measure.cache = {}
2546
+ lineView.measure.heights = null
2547
+ if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
2548
+ { lineView.measure.caches[i] = {} } }
2549
+ }
2550
+ }
2551
+
2552
+ function clearLineMeasurementCache(cm) {
2553
+ cm.display.externalMeasure = null
2554
+ removeChildren(cm.display.lineMeasure)
2555
+ for (var i = 0; i < cm.display.view.length; i++)
2556
+ { clearLineMeasurementCacheFor(cm.display.view[i]) }
2557
+ }
2558
+
2559
+ function clearCaches(cm) {
2560
+ clearLineMeasurementCache(cm)
2561
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null
2562
+ if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true }
2563
+ cm.display.lineNumChars = null
2564
+ }
2565
+
2566
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft }
2567
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop }
2568
+
2569
+ // Converts a {top, bottom, left, right} box from line-local
2570
+ // coordinates into another coordinate system. Context may be one of
2571
+ // "line", "div" (display.lineDiv), "local"./null (editor), "window",
2572
+ // or "page".
2573
+ function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
2574
+ if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) {
2575
+ var size = widgetHeight(lineObj.widgets[i])
2576
+ rect.top += size; rect.bottom += size
2577
+ } } }
2578
+ if (context == "line") { return rect }
2579
+ if (!context) { context = "local" }
2580
+ var yOff = heightAtLine(lineObj)
2581
+ if (context == "local") { yOff += paddingTop(cm.display) }
2582
+ else { yOff -= cm.display.viewOffset }
2583
+ if (context == "page" || context == "window") {
2584
+ var lOff = cm.display.lineSpace.getBoundingClientRect()
2585
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY())
2586
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX())
2587
+ rect.left += xOff; rect.right += xOff
2588
+ }
2589
+ rect.top += yOff; rect.bottom += yOff
2590
+ return rect
2591
+ }
2592
+
2593
+ // Coverts a box from "div" coords to another coordinate system.
2594
+ // Context may be "window", "page", "div", or "local"./null.
2595
+ function fromCoordSystem(cm, coords, context) {
2596
+ if (context == "div") { return coords }
2597
+ var left = coords.left, top = coords.top
2598
+ // First move into "page" coordinate system
2599
+ if (context == "page") {
2600
+ left -= pageScrollX()
2601
+ top -= pageScrollY()
2602
+ } else if (context == "local" || !context) {
2603
+ var localBox = cm.display.sizer.getBoundingClientRect()
2604
+ left += localBox.left
2605
+ top += localBox.top
2606
+ }
2607
+
2608
+ var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect()
2609
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}
2610
+ }
2611
+
2612
+ function charCoords(cm, pos, context, lineObj, bias) {
2613
+ if (!lineObj) { lineObj = getLine(cm.doc, pos.line) }
2614
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)
2615
+ }
2616
+
2617
+ // Returns a box for a given cursor position, which may have an
2618
+ // 'other' property containing the position of the secondary cursor
2619
+ // on a bidi boundary.
2620
+ function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
2621
+ lineObj = lineObj || getLine(cm.doc, pos.line)
2622
+ if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) }
2623
+ function get(ch, right) {
2624
+ var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight)
2625
+ if (right) { m.left = m.right; } else { m.right = m.left }
2626
+ return intoCoordSystem(cm, lineObj, m, context)
2627
+ }
2628
+ function getBidi(ch, partPos) {
2629
+ var part = order[partPos], right = part.level % 2
2630
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
2631
+ part = order[--partPos]
2632
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1)
2633
+ right = true
2634
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
2635
+ part = order[++partPos]
2636
+ ch = bidiLeft(part) - part.level % 2
2637
+ right = false
2638
+ }
2639
+ if (right && ch == part.to && ch > part.from) { return get(ch - 1) }
2640
+ return get(ch, right)
2641
+ }
2642
+ var order = getOrder(lineObj), ch = pos.ch
2643
+ if (!order) { return get(ch) }
2644
+ var partPos = getBidiPartAt(order, ch)
2645
+ var val = getBidi(ch, partPos)
2646
+ if (bidiOther != null) { val.other = getBidi(ch, bidiOther) }
2647
+ return val
2648
+ }
2649
+
2650
+ // Used to cheaply estimate the coordinates for a position. Used for
2651
+ // intermediate scroll updates.
2652
+ function estimateCoords(cm, pos) {
2653
+ var left = 0
2654
+ pos = clipPos(cm.doc, pos)
2655
+ if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch }
2656
+ var lineObj = getLine(cm.doc, pos.line)
2657
+ var top = heightAtLine(lineObj) + paddingTop(cm.display)
2658
+ return {left: left, right: left, top: top, bottom: top + lineObj.height}
2659
+ }
2660
+
2661
+ // Positions returned by coordsChar contain some extra information.
2662
+ // xRel is the relative x position of the input coordinates compared
2663
+ // to the found position (so xRel > 0 means the coordinates are to
2664
+ // the right of the character position, for example). When outside
2665
+ // is true, that means the coordinates lie outside the line's
2666
+ // vertical range.
2667
+ function PosWithInfo(line, ch, outside, xRel) {
2668
+ var pos = Pos(line, ch)
2669
+ pos.xRel = xRel
2670
+ if (outside) { pos.outside = true }
2671
+ return pos
2672
+ }
2673
+
2674
+ // Compute the character position closest to the given coordinates.
2675
+ // Input must be lineSpace-local ("div" coordinate system).
2676
+ function coordsChar(cm, x, y) {
2677
+ var doc = cm.doc
2678
+ y += cm.display.viewOffset
2679
+ if (y < 0) { return PosWithInfo(doc.first, 0, true, -1) }
2680
+ var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1
2681
+ if (lineN > last)
2682
+ { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1) }
2683
+ if (x < 0) { x = 0 }
2684
+
2685
+ var lineObj = getLine(doc, lineN)
2686
+ for (;;) {
2687
+ var found = coordsCharInner(cm, lineObj, lineN, x, y)
2688
+ var merged = collapsedSpanAtEnd(lineObj)
2689
+ var mergedPos = merged && merged.find(0, true)
2690
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
2691
+ { lineN = lineNo(lineObj = mergedPos.to.line) }
2692
+ else
2693
+ { return found }
2694
+ }
2695
+ }
2696
+
2697
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
2698
+ var innerOff = y - heightAtLine(lineObj)
2699
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth
2700
+ var preparedMeasure = prepareMeasureForLine(cm, lineObj)
2701
+
2702
+ function getX(ch) {
2703
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure)
2704
+ wrongLine = true
2705
+ if (innerOff > sp.bottom) { return sp.left - adjust }
2706
+ else if (innerOff < sp.top) { return sp.left + adjust }
2707
+ else { wrongLine = false }
2708
+ return sp.left
2709
+ }
2710
+
2711
+ var bidi = getOrder(lineObj), dist = lineObj.text.length
2712
+ var from = lineLeft(lineObj), to = lineRight(lineObj)
2713
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine
2714
+
2715
+ if (x > toX) { return PosWithInfo(lineNo, to, toOutside, 1) }
2716
+ // Do a binary search between these bounds.
2717
+ for (;;) {
2718
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
2719
+ var ch = x < fromX || x - fromX <= toX - x ? from : to
2720
+ var outside = ch == from ? fromOutside : toOutside
2721
+ var xDiff = x - (ch == from ? fromX : toX)
2722
+ // This is a kludge to handle the case where the coordinates
2723
+ // are after a line-wrapped line. We should replace it with a
2724
+ // more general handling of cursor positions around line
2725
+ // breaks. (Issue #4078)
2726
+ if (toOutside && !bidi && !/\s/.test(lineObj.text.charAt(ch)) && xDiff > 0 &&
2727
+ ch < lineObj.text.length && preparedMeasure.view.measure.heights.length > 1) {
2728
+ var charSize = measureCharPrepared(cm, preparedMeasure, ch, "right")
2729
+ if (innerOff <= charSize.bottom && innerOff >= charSize.top && Math.abs(x - charSize.right) < xDiff) {
2730
+ outside = false
2731
+ ch++
2732
+ xDiff = x - charSize.right
2733
+ }
2734
  }
2735
+ while (isExtendingChar(lineObj.text.charAt(ch))) { ++ch }
2736
+ var pos = PosWithInfo(lineNo, ch, outside, xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0)
2737
+ return pos
2738
+ }
2739
+ var step = Math.ceil(dist / 2), middle = from + step
2740
+ if (bidi) {
2741
+ middle = from
2742
+ for (var i = 0; i < step; ++i) { middle = moveVisually(lineObj, middle, 1) }
2743
+ }
2744
+ var middleX = getX(middle)
2745
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) { toX += 1000; } dist = step}
2746
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step}
2747
+ }
2748
+ }
2749
+
2750
+ var measureText
2751
+ // Compute the default text height.
2752
+ function textHeight(display) {
2753
+ if (display.cachedTextHeight != null) { return display.cachedTextHeight }
2754
+ if (measureText == null) {
2755
+ measureText = elt("pre")
2756
+ // Measure a bunch of lines, for browsers that compute
2757
+ // fractional heights.
2758
+ for (var i = 0; i < 49; ++i) {
2759
+ measureText.appendChild(document.createTextNode("x"))
2760
+ measureText.appendChild(elt("br"))
2761
+ }
2762
+ measureText.appendChild(document.createTextNode("x"))
2763
+ }
2764
+ removeChildrenAndAdd(display.measure, measureText)
2765
+ var height = measureText.offsetHeight / 50
2766
+ if (height > 3) { display.cachedTextHeight = height }
2767
+ removeChildren(display.measure)
2768
+ return height || 1
2769
+ }
2770
+
2771
+ // Compute the default character width.
2772
+ function charWidth(display) {
2773
+ if (display.cachedCharWidth != null) { return display.cachedCharWidth }
2774
+ var anchor = elt("span", "xxxxxxxxxx")
2775
+ var pre = elt("pre", [anchor])
2776
+ removeChildrenAndAdd(display.measure, pre)
2777
+ var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10
2778
+ if (width > 2) { display.cachedCharWidth = width }
2779
+ return width || 10
2780
+ }
2781
+
2782
+ // Do a bulk-read of the DOM positions and sizes needed to draw the
2783
+ // view, so that we don't interleave reading and writing to the DOM.
2784
+ function getDimensions(cm) {
2785
+ var d = cm.display, left = {}, width = {}
2786
+ var gutterLeft = d.gutters.clientLeft
2787
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
2788
+ left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft
2789
+ width[cm.options.gutters[i]] = n.clientWidth
2790
+ }
2791
+ return {fixedPos: compensateForHScroll(d),
2792
+ gutterTotalWidth: d.gutters.offsetWidth,
2793
+ gutterLeft: left,
2794
+ gutterWidth: width,
2795
+ wrapperWidth: d.wrapper.clientWidth}
2796
+ }
2797
+
2798
+ // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
2799
+ // but using getBoundingClientRect to get a sub-pixel-accurate
2800
+ // result.
2801
+ function compensateForHScroll(display) {
2802
+ return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left
2803
+ }
2804
+
2805
+ // Returns a function that estimates the height of a line, to use as
2806
+ // first approximation until the line becomes visible (and is thus
2807
+ // properly measurable).
2808
+ function estimateHeight(cm) {
2809
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping
2810
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3)
2811
+ return function (line) {
2812
+ if (lineIsHidden(cm.doc, line)) { return 0 }
2813
+
2814
+ var widgetsHeight = 0
2815
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {
2816
+ if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height }
2817
+ } }
2818
+
2819
+ if (wrapping)
2820
+ { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }
2821
+ else
2822
+ { return widgetsHeight + th }
2823
+ }
2824
+ }
2825
+
2826
+ function estimateLineHeights(cm) {
2827
+ var doc = cm.doc, est = estimateHeight(cm)
2828
+ doc.iter(function (line) {
2829
+ var estHeight = est(line)
2830
+ if (estHeight != line.height) { updateLineHeight(line, estHeight) }
2831
+ })
2832
+ }
2833
+
2834
+ // Given a mouse event, find the corresponding position. If liberal
2835
+ // is false, it checks whether a gutter or scrollbar was clicked,
2836
+ // and returns null if it was. forRect is used by rectangular
2837
+ // selections, and tries to estimate a character position even for
2838
+ // coordinates beyond the right of the text.
2839
+ function posFromMouse(cm, e, liberal, forRect) {
2840
+ var display = cm.display
2841
+ if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null }
2842
+
2843
+ var x, y, space = display.lineSpace.getBoundingClientRect()
2844
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
2845
+ try { x = e.clientX - space.left; y = e.clientY - space.top }
2846
+ catch (e) { return null }
2847
+ var coords = coordsChar(cm, x, y), line
2848
+ if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
2849
+ var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length
2850
+ coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff))
2851
+ }
2852
+ return coords
2853
+ }
2854
+
2855
+ // Find the view element corresponding to a given line. Return null
2856
+ // when the line isn't visible.
2857
+ function findViewIndex(cm, n) {
2858
+ if (n >= cm.display.viewTo) { return null }
2859
+ n -= cm.display.viewFrom
2860
+ if (n < 0) { return null }
2861
+ var view = cm.display.view
2862
+ for (var i = 0; i < view.length; i++) {
2863
+ n -= view[i].size
2864
+ if (n < 0) { return i }
2865
+ }
2866
+ }
2867
+
2868
+ function updateSelection(cm) {
2869
+ cm.display.input.showSelection(cm.display.input.prepareSelection())
2870
+ }
2871
+
2872
+ function prepareSelection(cm, primary) {
2873
+ var doc = cm.doc, result = {}
2874
+ var curFragment = result.cursors = document.createDocumentFragment()
2875
+ var selFragment = result.selection = document.createDocumentFragment()
2876
+
2877
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
2878
+ if (primary === false && i == doc.sel.primIndex) { continue }
2879
+ var range = doc.sel.ranges[i]
2880
+ if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
2881
+ var collapsed = range.empty()
2882
+ if (collapsed || cm.options.showCursorWhenSelecting)
2883
+ { drawSelectionCursor(cm, range.head, curFragment) }
2884
+ if (!collapsed)
2885
+ { drawSelectionRange(cm, range, selFragment) }
2886
+ }
2887
+ return result
2888
+ }
2889
+
2890
+ // Draws a cursor for the given range
2891
+ function drawSelectionCursor(cm, head, output) {
2892
+ var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine)
2893
+
2894
+ var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"))
2895
+ cursor.style.left = pos.left + "px"
2896
+ cursor.style.top = pos.top + "px"
2897
+ cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"
2898
+
2899
+ if (pos.other) {
2900
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
2901
+ var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"))
2902
+ otherCursor.style.display = ""
2903
+ otherCursor.style.left = pos.other.left + "px"
2904
+ otherCursor.style.top = pos.other.top + "px"
2905
+ otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"
2906
+ }
2907
+ }
2908
+
2909
+ // Draws the given range as a highlighted selection
2910
+ function drawSelectionRange(cm, range, output) {
2911
+ var display = cm.display, doc = cm.doc
2912
+ var fragment = document.createDocumentFragment()
2913
+ var padding = paddingH(cm.display), leftSide = padding.left
2914
+ var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right
2915
+
2916
+ function add(left, top, width, bottom) {
2917
+ if (top < 0) { top = 0 }
2918
+ top = Math.round(top)
2919
+ bottom = Math.round(bottom)
2920
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px")))
2921
+ }
2922
+
2923
+ function drawForLine(line, fromArg, toArg) {
2924
+ var lineObj = getLine(doc, line)
2925
+ var lineLen = lineObj.text.length
2926
+ var start, end
2927
+ function coords(ch, bias) {
2928
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
2929
+ }
2930
+
2931
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) {
2932
+ var leftPos = coords(from, "left"), rightPos, left, right
2933
+ if (from == to) {
2934
+ rightPos = leftPos
2935
+ left = right = leftPos.left
2936
  } else {
2937
+ rightPos = coords(to - 1, "right")
2938
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp }
2939
+ left = leftPos.left
2940
+ right = rightPos.right
2941
+ }
2942
+ if (fromArg == null && from == 0) { left = leftSide }
2943
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
2944
+ add(left, leftPos.top, null, leftPos.bottom)
2945
+ left = leftSide
2946
+ if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top) }
2947
+ }
2948
+ if (toArg == null && to == lineLen) { right = rightSide }
2949
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
2950
+ { start = leftPos }
2951
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
2952
+ { end = rightPos }
2953
+ if (left < leftSide + 1) { left = leftSide }
2954
+ add(left, rightPos.top, right - left, rightPos.bottom)
2955
+ })
2956
+ return {start: start, end: end}
2957
+ }
2958
+
2959
+ var sFrom = range.from(), sTo = range.to()
2960
+ if (sFrom.line == sTo.line) {
2961
+ drawForLine(sFrom.line, sFrom.ch, sTo.ch)
2962
+ } else {
2963
+ var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line)
2964
+ var singleVLine = visualLine(fromLine) == visualLine(toLine)
2965
+ var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end
2966
+ var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start
2967
+ if (singleVLine) {
2968
+ if (leftEnd.top < rightStart.top - 2) {
2969
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom)
2970
+ add(leftSide, rightStart.top, rightStart.left, rightStart.bottom)
2971
+ } else {
2972
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom)
2973
+ }
2974
+ }
2975
+ if (leftEnd.bottom < rightStart.top)
2976
+ { add(leftSide, leftEnd.bottom, null, rightStart.top) }
2977
+ }
2978
+
2979
+ output.appendChild(fragment)
2980
+ }
2981
+
2982
+ // Cursor-blinking
2983
+ function restartBlink(cm) {
2984
+ if (!cm.state.focused) { return }
2985
+ var display = cm.display
2986
+ clearInterval(display.blinker)
2987
+ var on = true
2988
+ display.cursorDiv.style.visibility = ""
2989
+ if (cm.options.cursorBlinkRate > 0)
2990
+ { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; },
2991
+ cm.options.cursorBlinkRate) }
2992
+ else if (cm.options.cursorBlinkRate < 0)
2993
+ { display.cursorDiv.style.visibility = "hidden" }
2994
+ }
2995
+
2996
+ function ensureFocus(cm) {
2997
+ if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm) }
2998
+ }
2999
+
3000
+ function delayBlurEvent(cm) {
3001
+ cm.state.delayingBlurEvent = true
3002
+ setTimeout(function () { if (cm.state.delayingBlurEvent) {
3003
+ cm.state.delayingBlurEvent = false
3004
+ onBlur(cm)
3005
+ } }, 100)
3006
+ }
3007
+
3008
+ function onFocus(cm, e) {
3009
+ if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false }
3010
+
3011
+ if (cm.options.readOnly == "nocursor") { return }
3012
+ if (!cm.state.focused) {
3013
+ signal(cm, "focus", cm, e)
3014
+ cm.state.focused = true
3015
+ addClass(cm.display.wrapper, "CodeMirror-focused")
3016
+ // This test prevents this from firing when a context
3017
+ // menu is closed (since the input reset would kill the
3018
+ // select-all detection hack)
3019
+ if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
3020
+ cm.display.input.reset()
3021
+ if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20) } // Issue #1730
3022
+ }
3023
+ cm.display.input.receivedFocus()
3024
+ }
3025
+ restartBlink(cm)
3026
+ }
3027
+ function onBlur(cm, e) {
3028
+ if (cm.state.delayingBlurEvent) { return }
3029
+
3030
+ if (cm.state.focused) {
3031
+ signal(cm, "blur", cm, e)
3032
+ cm.state.focused = false
3033
+ rmClass(cm.display.wrapper, "CodeMirror-focused")
3034
+ }
3035
+ clearInterval(cm.display.blinker)
3036
+ setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false } }, 150)
3037
+ }
3038
+
3039
+ // Re-align line numbers and gutter marks to compensate for
3040
+ // horizontal scrolling.
3041
+ function alignHorizontally(cm) {
3042
+ var display = cm.display, view = display.view
3043
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
3044
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft
3045
+ var gutterW = display.gutters.offsetWidth, left = comp + "px"
3046
+ for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
3047
+ if (cm.options.fixedGutter) {
3048
+ if (view[i].gutter)
3049
+ { view[i].gutter.style.left = left }
3050
+ if (view[i].gutterBackground)
3051
+ { view[i].gutterBackground.style.left = left }
3052
+ }
3053
+ var align = view[i].alignable
3054
+ if (align) { for (var j = 0; j < align.length; j++)
3055
+ { align[j].style.left = left } }
3056
+ } }
3057
+ if (cm.options.fixedGutter)
3058
+ { display.gutters.style.left = (comp + gutterW) + "px" }
3059
+ }
3060
+
3061
+ // Used to ensure that the line number gutter is still the right
3062
+ // size for the current document size. Returns true when an update
3063
+ // is needed.
3064
+ function maybeUpdateLineNumberWidth(cm) {
3065
+ if (!cm.options.lineNumbers) { return false }
3066
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display
3067
+ if (last.length != display.lineNumChars) {
3068
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
3069
+ "CodeMirror-linenumber CodeMirror-gutter-elt"))
3070
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW
3071
+ display.lineGutter.style.width = ""
3072
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1
3073
+ display.lineNumWidth = display.lineNumInnerWidth + padding
3074
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1
3075
+ display.lineGutter.style.width = display.lineNumWidth + "px"
3076
+ updateGutterSpace(cm)
3077
+ return true
3078
+ }
3079
+ return false
3080
+ }
3081
+
3082
+ // Read the actual heights of the rendered lines, and update their
3083
+ // stored heights to match.
3084
+ function updateHeightsInViewport(cm) {
3085
+ var display = cm.display
3086
+ var prevBottom = display.lineDiv.offsetTop
3087
+ for (var i = 0; i < display.view.length; i++) {
3088
+ var cur = display.view[i], height = (void 0)
3089
+ if (cur.hidden) { continue }
3090
+ if (ie && ie_version < 8) {
3091
+ var bot = cur.node.offsetTop + cur.node.offsetHeight
3092
+ height = bot - prevBottom
3093
+ prevBottom = bot
3094
+ } else {
3095
+ var box = cur.node.getBoundingClientRect()
3096
+ height = box.bottom - box.top
3097
+ }
3098
+ var diff = cur.line.height - height
3099
+ if (height < 2) { height = textHeight(display) }
3100
+ if (diff > .001 || diff < -.001) {
3101
+ updateLineHeight(cur.line, height)
3102
+ updateWidgetHeight(cur.line)
3103
+ if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
3104
+ { updateWidgetHeight(cur.rest[j]) } }
3105
+ }
3106
+ }
3107
+ }
3108
+
3109
+ // Read and store the height of line widgets associated with the
3110
+ // given line.
3111
+ function updateWidgetHeight(line) {
3112
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i)
3113
+ { line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight } }
3114
+ }
3115
+
3116
+ // Compute the lines that are visible in a given viewport (defaults
3117
+ // the the current scroll position). viewport may contain top,
3118
+ // height, and ensure (see op.scrollToPos) properties.
3119
+ function visibleLines(display, doc, viewport) {
3120
+ var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop
3121
+ top = Math.floor(top - paddingTop(display))
3122
+ var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight
3123
+
3124
+ var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom)
3125
+ // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
3126
+ // forces those lines into the viewport (if possible).
3127
+ if (viewport && viewport.ensure) {
3128
+ var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line
3129
+ if (ensureFrom < from) {
3130
+ from = ensureFrom
3131
+ to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)
3132
+ } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
3133
+ from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight)
3134
+ to = ensureTo
3135
+ }
3136
+ }
3137
+ return {from: from, to: Math.max(to, from + 1)}
3138
+ }
3139
+
3140
+ // Sync the scrollable area and scrollbars, ensure the viewport
3141
+ // covers the visible area.
3142
+ function setScrollTop(cm, val) {
3143
+ if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
3144
+ cm.doc.scrollTop = val
3145
+ if (!gecko) { updateDisplaySimple(cm, {top: val}) }
3146
+ if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val }
3147
+ cm.display.scrollbars.setScrollTop(val)
3148
+ if (gecko) { updateDisplaySimple(cm) }
3149
+ startWorker(cm, 100)
3150
+ }
3151
+ // Sync scroller and scrollbar, ensure the gutter elements are
3152
+ // aligned.
3153
+ function setScrollLeft(cm, val, isScroller) {
3154
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) { return }
3155
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)
3156
+ cm.doc.scrollLeft = val
3157
+ alignHorizontally(cm)
3158
+ if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val }
3159
+ cm.display.scrollbars.setScrollLeft(val)
3160
+ }
3161
+
3162
+ // Since the delta values reported on mouse wheel events are
3163
+ // unstandardized between browsers and even browser versions, and
3164
+ // generally horribly unpredictable, this code starts by measuring
3165
+ // the scroll effect that the first few mouse wheel events have,
3166
+ // and, from that, detects the way it can convert deltas to pixel
3167
+ // offsets afterwards.
3168
+ //
3169
+ // The reason we want to know the amount a wheel event will scroll
3170
+ // is that it gives us a chance to update the display before the
3171
+ // actual scrolling happens, reducing flickering.
3172
+
3173
+ var wheelSamples = 0;
3174
+ var wheelPixelsPerUnit = null;
3175
+ // Fill in a browser-detected starting value on browsers where we
3176
+ // know one. These don't have to be accurate -- the result of them
3177
+ // being wrong would just be a slight flicker on the first wheel
3178
+ // scroll (if it is large enough).
3179
+ if (ie) { wheelPixelsPerUnit = -.53 }
3180
+ else if (gecko) { wheelPixelsPerUnit = 15 }
3181
+ else if (chrome) { wheelPixelsPerUnit = -.7 }
3182
+ else if (safari) { wheelPixelsPerUnit = -1/3 }
3183
+
3184
+ function wheelEventDelta(e) {
3185
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY
3186
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail }
3187
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail }
3188
+ else if (dy == null) { dy = e.wheelDelta }
3189
+ return {x: dx, y: dy}
3190
+ }
3191
+ function wheelEventPixels(e) {
3192
+ var delta = wheelEventDelta(e)
3193
+ delta.x *= wheelPixelsPerUnit
3194
+ delta.y *= wheelPixelsPerUnit
3195
+ return delta
3196
+ }
3197
+
3198
+ function onScrollWheel(cm, e) {
3199
+ var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y
3200
+
3201
+ var display = cm.display, scroll = display.scroller
3202
+ // Quit if there's nothing to scroll here
3203
+ var canScrollX = scroll.scrollWidth > scroll.clientWidth
3204
+ var canScrollY = scroll.scrollHeight > scroll.clientHeight
3205
+ if (!(dx && canScrollX || dy && canScrollY)) { return }
3206
+
3207
+ // Webkit browsers on OS X abort momentum scrolls when the target
3208
+ // of the scroll event is removed from the scrollable element.
3209
+ // This hack (see related code in patchDisplay) makes sure the
3210
+ // element is kept around.
3211
+ if (dy && mac && webkit) {
3212
+ outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
3213
+ for (var i = 0; i < view.length; i++) {
3214
+ if (view[i].node == cur) {
3215
+ cm.display.currentWheelTarget = cur
3216
+ break outer
3217
+ }
3218
  }
3219
  }
3220
  }
3221
 
3222
+ // On some browsers, horizontal scrolling will cause redraws to
3223
+ // happen before the gutter has been realigned, causing it to
3224
+ // wriggle around in a most unseemly way. When we have an
3225
+ // estimated pixels/delta value, we just handle horizontal
3226
+ // scrolling entirely here. It'll be slightly off from native, but
3227
+ // better than glitching out.
3228
+ if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
3229
+ if (dy && canScrollY)
3230
+ { setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))) }
3231
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)))
3232
+ // Only prevent default scrolling if vertical scrolling is
3233
+ // actually possible. Otherwise, it causes vertical scroll
3234
+ // jitter on OSX trackpads when deltaX is small and deltaY
3235
+ // is large (issue #3579)
3236
+ if (!dy || (dy && canScrollY))
3237
+ { e_preventDefault(e) }
3238
+ display.wheelStartX = null // Abort measurement, if in progress
3239
+ return
3240
+ }
3241
+
3242
+ // 'Project' the visible viewport to cover the area that is being
3243
+ // scrolled into view (if we know enough to estimate it).
3244
+ if (dy && wheelPixelsPerUnit != null) {
3245
+ var pixels = dy * wheelPixelsPerUnit
3246
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight
3247
+ if (pixels < 0) { top = Math.max(0, top + pixels - 50) }
3248
+ else { bot = Math.min(cm.doc.height, bot + pixels + 50) }
3249
+ updateDisplaySimple(cm, {top: top, bottom: bot})
3250
+ }
3251
+
3252
+ if (wheelSamples < 20) {
3253
+ if (display.wheelStartX == null) {
3254
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop
3255
+ display.wheelDX = dx; display.wheelDY = dy
3256
+ setTimeout(function () {
3257
+ if (display.wheelStartX == null) { return }
3258
+ var movedX = scroll.scrollLeft - display.wheelStartX
3259
+ var movedY = scroll.scrollTop - display.wheelStartY
3260
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
3261
+ (movedX && display.wheelDX && movedX / display.wheelDX)
3262
+ display.wheelStartX = display.wheelStartY = null
3263
+ if (!sample) { return }
3264
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1)
3265
+ ++wheelSamples
3266
+ }, 200)
3267
+ } else {
3268
+ display.wheelDX += dx; display.wheelDY += dy
3269
+ }
3270
+ }
3271
+ }
3272
+
3273
+ // SCROLLBARS
3274
+
3275
+ // Prepare DOM reads needed to update the scrollbars. Done in one
3276
+ // shot to minimize update/measure roundtrips.
3277
+ function measureForScrollbars(cm) {
3278
+ var d = cm.display, gutterW = d.gutters.offsetWidth
3279
+ var docH = Math.round(cm.doc.height + paddingVert(cm.display))
3280
+ return {
3281
+ clientHeight: d.scroller.clientHeight,
3282
+ viewHeight: d.wrapper.clientHeight,
3283
+ scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
3284
+ viewWidth: d.wrapper.clientWidth,
3285
+ barLeft: cm.options.fixedGutter ? gutterW : 0,
3286
+ docHeight: docH,
3287
+ scrollHeight: docH + scrollGap(cm) + d.barHeight,
3288
+ nativeBarWidth: d.nativeBarWidth,
3289
+ gutterWidth: gutterW
3290
+ }
3291
+ }
3292
+
3293
+ var NativeScrollbars = function(place, scroll, cm) {
3294
+ this.cm = cm
3295
+ var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar")
3296
+ var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar")
3297
+ place(vert); place(horiz)
3298
+
3299
+ on(vert, "scroll", function () {
3300
+ if (vert.clientHeight) { scroll(vert.scrollTop, "vertical") }
3301
+ })
3302
+ on(horiz, "scroll", function () {
3303
+ if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal") }
3304
+ })
3305
+
3306
+ this.checkedZeroWidth = false
3307
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
3308
+ if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px" }
3309
+ };
3310
+
3311
+ NativeScrollbars.prototype.update = function (measure) {
3312
+ var needsH = measure.scrollWidth > measure.clientWidth + 1
3313
+ var needsV = measure.scrollHeight > measure.clientHeight + 1
3314
+ var sWidth = measure.nativeBarWidth
3315
+
3316
+ if (needsV) {
3317
+ this.vert.style.display = "block"
3318
+ this.vert.style.bottom = needsH ? sWidth + "px" : "0"
3319
+ var totalHeight = measure.viewHeight - (needsH ? sWidth : 0)
3320
+ // A bug in IE8 can cause this value to be negative, so guard it.
3321
+ this.vert.firstChild.style.height =
3322
+ Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"
3323
+ } else {
3324
+ this.vert.style.display = ""
3325
+ this.vert.firstChild.style.height = "0"
3326
+ }
3327
+
3328
+ if (needsH) {
3329
+ this.horiz.style.display = "block"
3330
+ this.horiz.style.right = needsV ? sWidth + "px" : "0"
3331
+ this.horiz.style.left = measure.barLeft + "px"
3332
+ var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0)
3333
+ this.horiz.firstChild.style.width =
3334
+ (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"
3335
+ } else {
3336
+ this.horiz.style.display = ""
3337
+ this.horiz.firstChild.style.width = "0"
3338
+ }
3339
+
3340
+ if (!this.checkedZeroWidth && measure.clientHeight > 0) {
3341
+ if (sWidth == 0) { this.zeroWidthHack() }
3342
+ this.checkedZeroWidth = true
3343
+ }
3344
+
3345
+ return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}
3346
+ };
3347
+
3348
+ NativeScrollbars.prototype.setScrollLeft = function (pos) {
3349
+ if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos }
3350
+ if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz) }
3351
+ };
3352
+
3353
+ NativeScrollbars.prototype.setScrollTop = function (pos) {
3354
+ if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos }
3355
+ if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert) }
3356
+ };
3357
+
3358
+ NativeScrollbars.prototype.zeroWidthHack = function () {
3359
+ var w = mac && !mac_geMountainLion ? "12px" : "18px"
3360
+ this.horiz.style.height = this.vert.style.width = w
3361
+ this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"
3362
+ this.disableHoriz = new Delayed
3363
+ this.disableVert = new Delayed
3364
+ };
3365
+
3366
+ NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay) {
3367
+ bar.style.pointerEvents = "auto"
3368
+ function maybeDisable() {
3369
+ // To find out whether the scrollbar is still visible, we
3370
+ // check whether the element under the pixel in the bottom
3371
+ // left corner of the scrollbar box is the scrollbar box
3372
+ // itself (when the bar is still visible) or its filler child
3373
+ // (when the bar is hidden). If it is still visible, we keep
3374
+ // it enabled, if it's hidden, we disable pointer events.
3375
+ var box = bar.getBoundingClientRect()
3376
+ var elt = document.elementFromPoint(box.left + 1, box.bottom - 1)
3377
+ if (elt != bar) { bar.style.pointerEvents = "none" }
3378
+ else { delay.set(1000, maybeDisable) }
3379
+ }
3380
+ delay.set(1000, maybeDisable)
3381
+ };
3382
+
3383
+ NativeScrollbars.prototype.clear = function () {
3384
+ var parent = this.horiz.parentNode
3385
+ parent.removeChild(this.horiz)
3386
+ parent.removeChild(this.vert)
3387
+ };
3388
+
3389
+ var NullScrollbars = function () {};
3390
+
3391
+ NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };
3392
+ NullScrollbars.prototype.setScrollLeft = function () {};
3393
+ NullScrollbars.prototype.setScrollTop = function () {};
3394
+ NullScrollbars.prototype.clear = function () {};
3395
+
3396
+ function updateScrollbars(cm, measure) {
3397
+ if (!measure) { measure = measureForScrollbars(cm) }
3398
+ var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight
3399
+ updateScrollbarsInner(cm, measure)
3400
+ for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
3401
+ if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
3402
+ { updateHeightsInViewport(cm) }
3403
+ updateScrollbarsInner(cm, measureForScrollbars(cm))
3404
+ startWidth = cm.display.barWidth; startHeight = cm.display.barHeight
3405
+ }
3406
+ }
3407
+
3408
+ // Re-synchronize the fake scrollbars with the actual size of the
3409
+ // content.
3410
+ function updateScrollbarsInner(cm, measure) {
3411
+ var d = cm.display
3412
+ var sizes = d.scrollbars.update(measure)
3413
+
3414
+ d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"
3415
+ d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"
3416
+ d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"
3417
+
3418
+ if (sizes.right && sizes.bottom) {
3419
+ d.scrollbarFiller.style.display = "block"
3420
+ d.scrollbarFiller.style.height = sizes.bottom + "px"
3421
+ d.scrollbarFiller.style.width = sizes.right + "px"
3422
+ } else { d.scrollbarFiller.style.display = "" }
3423
+ if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
3424
+ d.gutterFiller.style.display = "block"
3425
+ d.gutterFiller.style.height = sizes.bottom + "px"
3426
+ d.gutterFiller.style.width = measure.gutterWidth + "px"
3427
+ } else { d.gutterFiller.style.display = "" }
3428
+ }
3429
+
3430
+ var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}
3431
+
3432
+ function initScrollbars(cm) {
3433
+ if (cm.display.scrollbars) {
3434
+ cm.display.scrollbars.clear()
3435
+ if (cm.display.scrollbars.addClass)
3436
+ { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass) }
3437
+ }
3438
+
3439
+ cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {
3440
+ cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller)
3441
+ // Prevent clicks in the scrollbars from killing focus
3442
+ on(node, "mousedown", function () {
3443
+ if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0) }
3444
+ })
3445
+ node.setAttribute("cm-not-content", "true")
3446
+ }, function (pos, axis) {
3447
+ if (axis == "horizontal") { setScrollLeft(cm, pos) }
3448
+ else { setScrollTop(cm, pos) }
3449
+ }, cm)
3450
+ if (cm.display.scrollbars.addClass)
3451
+ { addClass(cm.display.wrapper, cm.display.scrollbars.addClass) }
3452
+ }
3453
+
3454
+ // SCROLLING THINGS INTO VIEW
3455
+
3456
+ // If an editor sits on the top or bottom of the window, partially
3457
+ // scrolled out of view, this ensures that the cursor is visible.
3458
+ function maybeScrollWindow(cm, coords) {
3459
+ if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
3460
+
3461
+ var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null
3462
+ if (coords.top + box.top < 0) { doScroll = true }
3463
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false }
3464
+ if (doScroll != null && !phantom) {
3465
+ var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (coords.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (coords.left) + "px; width: 2px;"))
3466
+ cm.display.lineSpace.appendChild(scrollNode)
3467
+ scrollNode.scrollIntoView(doScroll)
3468
+ cm.display.lineSpace.removeChild(scrollNode)
3469
+ }
3470
+ }
3471
+
3472
+ // Scroll a given position into view (immediately), verifying that
3473
+ // it actually became visible (as line heights are accurately
3474
+ // measured, the position of something may 'drift' during drawing).
3475
+ function scrollPosIntoView(cm, pos, end, margin) {
3476
+ if (margin == null) { margin = 0 }
3477
+ var coords
3478
+ for (var limit = 0; limit < 5; limit++) {
3479
+ var changed = false
3480
+ coords = cursorCoords(cm, pos)
3481
+ var endCoords = !end || end == pos ? coords : cursorCoords(cm, end)
3482
+ var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
3483
+ Math.min(coords.top, endCoords.top) - margin,
3484
+ Math.max(coords.left, endCoords.left),
3485
+ Math.max(coords.bottom, endCoords.bottom) + margin)
3486
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft
3487
+ if (scrollPos.scrollTop != null) {
3488
+ setScrollTop(cm, scrollPos.scrollTop)
3489
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true }
3490
+ }
3491
+ if (scrollPos.scrollLeft != null) {
3492
+ setScrollLeft(cm, scrollPos.scrollLeft)
3493
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true }
3494
+ }
3495
+ if (!changed) { break }
3496
+ }
3497
+ return coords
3498
+ }
3499
+
3500
+ // Scroll a given set of coordinates into view (immediately).
3501
+ function scrollIntoView(cm, x1, y1, x2, y2) {
3502
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2)
3503
+ if (scrollPos.scrollTop != null) { setScrollTop(cm, scrollPos.scrollTop) }
3504
+ if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft) }
3505
+ }
3506
+
3507
+ // Calculate a new scroll position needed to scroll the given
3508
+ // rectangle into view. Returns an object with scrollTop and
3509
+ // scrollLeft properties. When these are undefined, the
3510
+ // vertical/horizontal position does not need to be adjusted.
3511
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
3512
+ var display = cm.display, snapMargin = textHeight(cm.display)
3513
+ if (y1 < 0) { y1 = 0 }
3514
+ var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop
3515
+ var screen = displayHeight(cm), result = {}
3516
+ if (y2 - y1 > screen) { y2 = y1 + screen }
3517
+ var docBottom = cm.doc.height + paddingVert(display)
3518
+ var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin
3519
+ if (y1 < screentop) {
3520
+ result.scrollTop = atTop ? 0 : y1
3521
+ } else if (y2 > screentop + screen) {
3522
+ var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen)
3523
+ if (newTop != screentop) { result.scrollTop = newTop }
3524
+ }
3525
+
3526
+ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft
3527
+ var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0)
3528
+ var tooWide = x2 - x1 > screenw
3529
+ if (tooWide) { x2 = x1 + screenw }
3530
+ if (x1 < 10)
3531
+ { result.scrollLeft = 0 }
3532
+ else if (x1 < screenleft)
3533
+ { result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)) }
3534
+ else if (x2 > screenw + screenleft - 3)
3535
+ { result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw }
3536
+ return result
3537
+ }
3538
+
3539
+ // Store a relative adjustment to the scroll position in the current
3540
+ // operation (to be applied when the operation finishes).
3541
+ function addToScrollPos(cm, left, top) {
3542
+ if (left != null || top != null) { resolveScrollToPos(cm) }
3543
+ if (left != null)
3544
+ { cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left }
3545
+ if (top != null)
3546
+ { cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top }
3547
+ }
3548
+
3549
+ // Make sure that at the end of the operation the current cursor is
3550
+ // shown.
3551
+ function ensureCursorVisible(cm) {
3552
+ resolveScrollToPos(cm)
3553
+ var cur = cm.getCursor(), from = cur, to = cur
3554
+ if (!cm.options.lineWrapping) {
3555
+ from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur
3556
+ to = Pos(cur.line, cur.ch + 1)
3557
+ }
3558
+ cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}
3559
+ }
3560
+
3561
+ // When an operation has its scrollToPos property set, and another
3562
+ // scroll action is applied before the end of the operation, this
3563
+ // 'simulates' scrolling that position into view in a cheap way, so
3564
+ // that the effect of intermediate scroll commands is not ignored.
3565
+ function resolveScrollToPos(cm) {
3566
+ var range = cm.curOp.scrollToPos
3567
+ if (range) {
3568
+ cm.curOp.scrollToPos = null
3569
+ var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to)
3570
+ var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
3571
+ Math.min(from.top, to.top) - range.margin,
3572
+ Math.max(from.right, to.right),
3573
+ Math.max(from.bottom, to.bottom) + range.margin)
3574
+ cm.scrollTo(sPos.scrollLeft, sPos.scrollTop)
3575
+ }
3576
+ }
3577
+
3578
+ // Operations are used to wrap a series of changes to the editor
3579
+ // state in such a way that each change won't have to update the
3580
+ // cursor and display (which would be awkward, slow, and
3581
+ // error-prone). Instead, display updates are batched and then all
3582
+ // combined and executed at once.
3583
+
3584
+ var nextOpId = 0
3585
+ // Start a new operation.
3586
+ function startOperation(cm) {
3587
+ cm.curOp = {
3588
+ cm: cm,
3589
+ viewChanged: false, // Flag that indicates that lines might need to be redrawn
3590
+ startHeight: cm.doc.height, // Used to detect need to update scrollbar
3591
+ forceUpdate: false, // Used to force a redraw
3592
+ updateInput: null, // Whether to reset the input textarea
3593
+ typing: false, // Whether this reset should be careful to leave existing text (for compositing)
3594
+ changeObjs: null, // Accumulated changes, for firing change events
3595
+ cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
3596
+ cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
3597
+ selectionChanged: false, // Whether the selection needs to be redrawn
3598
+ updateMaxLine: false, // Set when the widest line needs to be determined anew
3599
+ scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
3600
+ scrollToPos: null, // Used to scroll to a specific position
3601
+ focus: false,
3602
+ id: ++nextOpId // Unique ID
3603
+ }
3604
+ pushOperation(cm.curOp)
3605
+ }
3606
+
3607
+ // Finish an operation, updating the display and signalling delayed events
3608
+ function endOperation(cm) {
3609
+ var op = cm.curOp
3610
+ finishOperation(op, function (group) {
3611
+ for (var i = 0; i < group.ops.length; i++)
3612
+ { group.ops[i].cm.curOp = null }
3613
+ endOperations(group)
3614
+ })
3615
+ }
3616
+
3617
+ // The DOM updates done when an operation finishes are batched so
3618
+ // that the minimum number of relayouts are required.
3619
+ function endOperations(group) {
3620
+ var ops = group.ops
3621
+ for (var i = 0; i < ops.length; i++) // Read DOM
3622
+ { endOperation_R1(ops[i]) }
3623
+ for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)
3624
+ { endOperation_W1(ops[i$1]) }
3625
+ for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM
3626
+ { endOperation_R2(ops[i$2]) }
3627
+ for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)
3628
+ { endOperation_W2(ops[i$3]) }
3629
+ for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM
3630
+ { endOperation_finish(ops[i$4]) }
3631
+ }
3632
+
3633
+ function endOperation_R1(op) {
3634
+ var cm = op.cm, display = cm.display
3635
+ maybeClipScrollbars(cm)
3636
+ if (op.updateMaxLine) { findMaxLine(cm) }
3637
+
3638
+ op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
3639
+ op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
3640
+ op.scrollToPos.to.line >= display.viewTo) ||
3641
+ display.maxLineChanged && cm.options.lineWrapping
3642
+ op.update = op.mustUpdate &&
3643
+ new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate)
3644
+ }
3645
+
3646
+ function endOperation_W1(op) {
3647
+ op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update)
3648
+ }
3649
+
3650
+ function endOperation_R2(op) {
3651
+ var cm = op.cm, display = cm.display
3652
+ if (op.updatedDisplay) { updateHeightsInViewport(cm) }
3653
+
3654
+ op.barMeasure = measureForScrollbars(cm)
3655
+
3656
+ // If the max line changed since it was last measured, measure it,
3657
+ // and ensure the document's width matches it.
3658
+ // updateDisplay_W2 will use these properties to do the actual resizing
3659
+ if (display.maxLineChanged && !cm.options.lineWrapping) {
3660
+ op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3
3661
+ cm.display.sizerWidth = op.adjustWidthTo
3662
+ op.barMeasure.scrollWidth =
3663
+ Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth)
3664
+ op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm))
3665
+ }
3666
+
3667
+ if (op.updatedDisplay || op.selectionChanged)
3668
+ { op.preparedSelection = display.input.prepareSelection(op.focus) }
3669
+ }
3670
+
3671
+ function endOperation_W2(op) {
3672
+ var cm = op.cm
3673
+
3674
+ if (op.adjustWidthTo != null) {
3675
+ cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"
3676
+ if (op.maxScrollLeft < cm.doc.scrollLeft)
3677
+ { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) }
3678
+ cm.display.maxLineChanged = false
3679
+ }
3680
+
3681
+ var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus())
3682
+ if (op.preparedSelection)
3683
+ { cm.display.input.showSelection(op.preparedSelection, takeFocus) }
3684
+ if (op.updatedDisplay || op.startHeight != cm.doc.height)
3685
+ { updateScrollbars(cm, op.barMeasure) }
3686
+ if (op.updatedDisplay)
3687
+ { setDocumentHeight(cm, op.barMeasure) }
3688
+
3689
+ if (op.selectionChanged) { restartBlink(cm) }
3690
+
3691
+ if (cm.state.focused && op.updateInput)
3692
+ { cm.display.input.reset(op.typing) }
3693
+ if (takeFocus) { ensureFocus(op.cm) }
3694
+ }
3695
+
3696
+ function endOperation_finish(op) {
3697
+ var cm = op.cm, display = cm.display, doc = cm.doc
3698
+
3699
+ if (op.updatedDisplay) { postUpdateDisplay(cm, op.update) }
3700
+
3701
+ // Abort mouse wheel delta measurement, when scrolling explicitly
3702
+ if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
3703
+ { display.wheelStartX = display.wheelStartY = null }
3704
+
3705
+ // Propagate the scroll position to the actual DOM scroller
3706
+ if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
3707
+ doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop))
3708
+ display.scrollbars.setScrollTop(doc.scrollTop)
3709
+ display.scroller.scrollTop = doc.scrollTop
3710
+ }
3711
+ if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
3712
+ doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft))
3713
+ display.scrollbars.setScrollLeft(doc.scrollLeft)
3714
+ display.scroller.scrollLeft = doc.scrollLeft
3715
+ alignHorizontally(cm)
3716
+ }
3717
+ // If we need to scroll a specific position into view, do so.
3718
+ if (op.scrollToPos) {
3719
+ var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
3720
+ clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin)
3721
+ if (op.scrollToPos.isCursor && cm.state.focused) { maybeScrollWindow(cm, coords) }
3722
+ }
3723
+
3724
+ // Fire events for markers that are hidden/unidden by editing or
3725
+ // undoing
3726
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers
3727
+ if (hidden) { for (var i = 0; i < hidden.length; ++i)
3728
+ { if (!hidden[i].lines.length) { signal(hidden[i], "hide") } } }
3729
+ if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)
3730
+ { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide") } } }
3731
+
3732
+ if (display.wrapper.offsetHeight)
3733
+ { doc.scrollTop = cm.display.scroller.scrollTop }
3734
+
3735
+ // Fire change events, and delayed event handlers
3736
+ if (op.changeObjs)
3737
+ { signal(cm, "changes", cm, op.changeObjs) }
3738
+ if (op.update)
3739
+ { op.update.finish() }
3740
+ }
3741
+
3742
+ // Run the given function in an operation
3743
+ function runInOp(cm, f) {
3744
+ if (cm.curOp) { return f() }
3745
+ startOperation(cm)
3746
+ try { return f() }
3747
+ finally { endOperation(cm) }
3748
+ }
3749
+ // Wraps a function in an operation. Returns the wrapped function.
3750
+ function operation(cm, f) {
3751
+ return function() {
3752
+ if (cm.curOp) { return f.apply(cm, arguments) }
3753
+ startOperation(cm)
3754
+ try { return f.apply(cm, arguments) }
3755
+ finally { endOperation(cm) }
3756
+ }
3757
+ }
3758
+ // Used to add methods to editor and doc instances, wrapping them in
3759
+ // operations.
3760
+ function methodOp(f) {
3761
+ return function() {
3762
+ if (this.curOp) { return f.apply(this, arguments) }
3763
+ startOperation(this)
3764
+ try { return f.apply(this, arguments) }
3765
+ finally { endOperation(this) }
3766
+ }
3767
+ }
3768
+ function docMethodOp(f) {
3769
+ return function() {
3770
+ var cm = this.cm
3771
+ if (!cm || cm.curOp) { return f.apply(this, arguments) }
3772
+ startOperation(cm)
3773
+ try { return f.apply(this, arguments) }
3774
+ finally { endOperation(cm) }
3775
+ }
3776
+ }
3777
+
3778
+ // Updates the display.view data structure for a given change to the
3779
+ // document. From and to are in pre-change coordinates. Lendiff is
3780
+ // the amount of lines added or subtracted by the change. This is
3781
+ // used for changes that span multiple lines, or change the way
3782
+ // lines are divided into visual lines. regLineChange (below)
3783
+ // registers single-line changes.
3784
+ function regChange(cm, from, to, lendiff) {
3785
+ if (from == null) { from = cm.doc.first }
3786
+ if (to == null) { to = cm.doc.first + cm.doc.size }
3787
+ if (!lendiff) { lendiff = 0 }
3788
+
3789
+ var display = cm.display
3790
+ if (lendiff && to < display.viewTo &&
3791
+ (display.updateLineNumbers == null || display.updateLineNumbers > from))
3792
+ { display.updateLineNumbers = from }
3793
+
3794
+ cm.curOp.viewChanged = true
3795
+
3796
+ if (from >= display.viewTo) { // Change after
3797
+ if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
3798
+ { resetView(cm) }
3799
+ } else if (to <= display.viewFrom) { // Change before
3800
+ if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
3801
+ resetView(cm)
3802
+ } else {
3803
+ display.viewFrom += lendiff
3804
+ display.viewTo += lendiff
3805
+ }
3806
+ } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
3807
+ resetView(cm)
3808
+ } else if (from <= display.viewFrom) { // Top overlap
3809
+ var cut = viewCuttingPoint(cm, to, to + lendiff, 1)
3810
+ if (cut) {
3811
+ display.view = display.view.slice(cut.index)
3812
+ display.viewFrom = cut.lineN
3813
+ display.viewTo += lendiff
3814
+ } else {
3815
+ resetView(cm)
3816
  }
3817
+ } else if (to >= display.viewTo) { // Bottom overlap
3818
+ var cut$1 = viewCuttingPoint(cm, from, from, -1)
3819
+ if (cut$1) {
3820
+ display.view = display.view.slice(0, cut$1.index)
3821
+ display.viewTo = cut$1.lineN
3822
+ } else {
3823
+ resetView(cm)
3824
+ }
3825
+ } else { // Gap in the middle
3826
+ var cutTop = viewCuttingPoint(cm, from, from, -1)
3827
+ var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1)
3828
+ if (cutTop && cutBot) {
3829
+ display.view = display.view.slice(0, cutTop.index)
3830
+ .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
3831
+ .concat(display.view.slice(cutBot.index))
3832
+ display.viewTo += lendiff
3833
+ } else {
3834
+ resetView(cm)
3835
+ }
3836
+ }
3837
+
3838
+ var ext = display.externalMeasured
3839
+ if (ext) {
3840
+ if (to < ext.lineN)
3841
+ { ext.lineN += lendiff }
3842
+ else if (from < ext.lineN + ext.size)
3843
+ { display.externalMeasured = null }
3844
+ }
3845
+ }
3846
+
3847
+ // Register a change to a single line. Type must be one of "text",
3848
+ // "gutter", "class", "widget"
3849
+ function regLineChange(cm, line, type) {
3850
+ cm.curOp.viewChanged = true
3851
+ var display = cm.display, ext = cm.display.externalMeasured
3852
+ if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
3853
+ { display.externalMeasured = null }
3854
+
3855
+ if (line < display.viewFrom || line >= display.viewTo) { return }
3856
+ var lineView = display.view[findViewIndex(cm, line)]
3857
+ if (lineView.node == null) { return }
3858
+ var arr = lineView.changes || (lineView.changes = [])
3859
+ if (indexOf(arr, type) == -1) { arr.push(type) }
3860
+ }
3861
+
3862
+ // Clear the view.
3863
+ function resetView(cm) {
3864
+ cm.display.viewFrom = cm.display.viewTo = cm.doc.first
3865
+ cm.display.view = []
3866
+ cm.display.viewOffset = 0
3867
+ }
3868
+
3869
+ function viewCuttingPoint(cm, oldN, newN, dir) {
3870
+ var index = findViewIndex(cm, oldN), diff, view = cm.display.view
3871
+ if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
3872
+ { return {index: index, lineN: newN} }
3873
+ var n = cm.display.viewFrom
3874
+ for (var i = 0; i < index; i++)
3875
+ { n += view[i].size }
3876
+ if (n != oldN) {
3877
+ if (dir > 0) {
3878
+ if (index == view.length - 1) { return null }
3879
+ diff = (n + view[index].size) - oldN
3880
+ index++
3881
+ } else {
3882
+ diff = n - oldN
3883
+ }
3884
+ oldN += diff; newN += diff
3885
+ }
3886
+ while (visualLineNo(cm.doc, newN) != newN) {
3887
+ if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
3888
+ newN += dir * view[index - (dir < 0 ? 1 : 0)].size
3889
+ index += dir
3890
+ }
3891
+ return {index: index, lineN: newN}
3892
+ }
3893
+
3894
+ // Force the view to cover a given range, adding empty view element
3895
+ // or clipping off existing ones as needed.
3896
+ function adjustView(cm, from, to) {
3897
+ var display = cm.display, view = display.view
3898
+ if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
3899
+ display.view = buildViewArray(cm, from, to)
3900
+ display.viewFrom = from
3901
+ } else {
3902
+ if (display.viewFrom > from)
3903
+ { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view) }
3904
+ else if (display.viewFrom < from)
3905
+ { display.view = display.view.slice(findViewIndex(cm, from)) }
3906
+ display.viewFrom = from
3907
+ if (display.viewTo < to)
3908
+ { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)) }
3909
+ else if (display.viewTo > to)
3910
+ { display.view = display.view.slice(0, findViewIndex(cm, to)) }
3911
+ }
3912
+ display.viewTo = to
3913
+ }
3914
+
3915
+ // Count the number of lines in the view whose DOM representation is
3916
+ // out of date (or nonexistent).
3917
+ function countDirtyView(cm) {
3918
+ var view = cm.display.view, dirty = 0
3919
+ for (var i = 0; i < view.length; i++) {
3920
+ var lineView = view[i]
3921
+ if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty }
3922
+ }
3923
+ return dirty
3924
+ }
3925
+
3926
+ // HIGHLIGHT WORKER
3927
+
3928
+ function startWorker(cm, time) {
3929
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
3930
+ { cm.state.highlight.set(time, bind(highlightWorker, cm)) }
3931
+ }
3932
+
3933
+ function highlightWorker(cm) {
3934
+ var doc = cm.doc
3935
+ if (doc.frontier < doc.first) { doc.frontier = doc.first }
3936
+ if (doc.frontier >= cm.display.viewTo) { return }
3937
+ var end = +new Date + cm.options.workTime
3938
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier))
3939
+ var changedLines = []
3940
+
3941
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
3942
+ if (doc.frontier >= cm.display.viewFrom) { // Visible
3943
+ var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength
3944
+ var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true)
3945
+ line.styles = highlighted.styles
3946
+ var oldCls = line.styleClasses, newCls = highlighted.classes
3947
+ if (newCls) { line.styleClasses = newCls }
3948
+ else if (oldCls) { line.styleClasses = null }
3949
+ var ischange = !oldStyles || oldStyles.length != line.styles.length ||
3950
+ oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass)
3951
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i] }
3952
+ if (ischange) { changedLines.push(doc.frontier) }
3953
+ line.stateAfter = tooLong ? state : copyState(doc.mode, state)
3954
+ } else {
3955
+ if (line.text.length <= cm.options.maxHighlightLength)
3956
+ { processLine(cm, line.text, state) }
3957
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null
3958
+ }
3959
+ ++doc.frontier
3960
+ if (+new Date > end) {
3961
+ startWorker(cm, cm.options.workDelay)
3962
+ return true
3963
+ }
3964
+ })
3965
+ if (changedLines.length) { runInOp(cm, function () {
3966
+ for (var i = 0; i < changedLines.length; i++)
3967
+ { regLineChange(cm, changedLines[i], "text") }
3968
+ }) }
3969
+ }
3970
+
3971
+ // DISPLAY DRAWING
3972
+
3973
+ var DisplayUpdate = function(cm, viewport, force) {
3974
+ var display = cm.display
3975
+
3976
+ this.viewport = viewport
3977
+ // Store some values that we'll need later (but don't want to force a relayout for)
3978
+ this.visible = visibleLines(display, cm.doc, viewport)
3979
+ this.editorIsHidden = !display.wrapper.offsetWidth
3980
+ this.wrapperHeight = display.wrapper.clientHeight
3981
+ this.wrapperWidth = display.wrapper.clientWidth
3982
+ this.oldDisplayWidth = displayWidth(cm)
3983
+ this.force = force
3984
+ this.dims = getDimensions(cm)
3985
+ this.events = []
3986
+ };
3987
+
3988
+ DisplayUpdate.prototype.signal = function (emitter, type) {
3989
+ if (hasHandler(emitter, type))
3990
+ { this.events.push(arguments) }
3991
+ };
3992
+ DisplayUpdate.prototype.finish = function () {
3993
+ var this$1 = this;
3994
+
3995
+ for (var i = 0; i < this.events.length; i++)
3996
+ { signal.apply(null, this$1.events[i]) }
3997
+ };
3998
+
3999
+ function maybeClipScrollbars(cm) {
4000
+ var display = cm.display
4001
+ if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
4002
+ display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth
4003
+ display.heightForcer.style.height = scrollGap(cm) + "px"
4004
+ display.sizer.style.marginBottom = -display.nativeBarWidth + "px"
4005
+ display.sizer.style.borderRightWidth = scrollGap(cm) + "px"
4006
+ display.scrollbarsClipped = true
4007
+ }
4008
+ }
4009
+
4010
+ // Does the actual updating of the line display. Bails out
4011
+ // (returning false) when there is nothing to be done and forced is
4012
+ // false.
4013
+ function updateDisplayIfNeeded(cm, update) {
4014
+ var display = cm.display, doc = cm.doc
4015
+
4016
+ if (update.editorIsHidden) {
4017
+ resetView(cm)
4018
+ return false
4019
+ }
4020
+
4021
+ // Bail out if the visible area is already rendered and nothing changed.
4022
+ if (!update.force &&
4023
+ update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
4024
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
4025
+ display.renderedView == display.view && countDirtyView(cm) == 0)
4026
+ { return false }
4027
+
4028
+ if (maybeUpdateLineNumberWidth(cm)) {
4029
+ resetView(cm)
4030
+ update.dims = getDimensions(cm)
4031
+ }
4032
+
4033
+ // Compute a suitable new viewport (from & to)
4034
+ var end = doc.first + doc.size
4035
+ var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first)
4036
+ var to = Math.min(end, update.visible.to + cm.options.viewportMargin)
4037
+ if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom) }
4038
+ if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo) }
4039
+ if (sawCollapsedSpans) {
4040
+ from = visualLineNo(cm.doc, from)
4041
+ to = visualLineEndNo(cm.doc, to)
4042
+ }
4043
+
4044
+ var different = from != display.viewFrom || to != display.viewTo ||
4045
+ display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth
4046
+ adjustView(cm, from, to)
4047
+
4048
+ display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom))
4049
+ // Position the mover div to align with the current scroll position
4050
+ cm.display.mover.style.top = display.viewOffset + "px"
4051
+
4052
+ var toUpdate = countDirtyView(cm)
4053
+ if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
4054
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
4055
+ { return false }
4056
+
4057
+ // For big changes, we hide the enclosing element during the
4058
+ // update, since that speeds up the operations on most browsers.
4059
+ var focused = activeElt()
4060
+ if (toUpdate > 4) { display.lineDiv.style.display = "none" }
4061
+ patchDisplay(cm, display.updateLineNumbers, update.dims)
4062
+ if (toUpdate > 4) { display.lineDiv.style.display = "" }
4063
+ display.renderedView = display.view
4064
+ // There might have been a widget with a focused element that got
4065
+ // hidden or updated, if so re-focus it.
4066
+ if (focused && activeElt() != focused && focused.offsetHeight) { focused.focus() }
4067
+
4068
+ // Prevent selection and cursors from interfering with the scroll
4069
+ // width and height.
4070
+ removeChildren(display.cursorDiv)
4071
+ removeChildren(display.selectionDiv)
4072
+ display.gutters.style.height = display.sizer.style.minHeight = 0
4073
+
4074
+ if (different) {
4075
+ display.lastWrapHeight = update.wrapperHeight
4076
+ display.lastWrapWidth = update.wrapperWidth
4077
+ startWorker(cm, 400)
4078
+ }
4079
+
4080
+ display.updateLineNumbers = null
4081
+
4082
+ return true
4083
+ }
4084
+
4085
+ function postUpdateDisplay(cm, update) {
4086
+ var viewport = update.viewport
4087
+
4088
+ for (var first = true;; first = false) {
4089
+ if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
4090
+ // Clip forced viewport to actual scrollable area.
4091
+ if (viewport && viewport.top != null)
4092
+ { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)} }
4093
+ // Updated line heights might result in the drawn area not
4094
+ // actually covering the viewport. Keep looping until it does.
4095
+ update.visible = visibleLines(cm.display, cm.doc, viewport)
4096
+ if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
4097
+ { break }
4098
+ }
4099
+ if (!updateDisplayIfNeeded(cm, update)) { break }
4100
+ updateHeightsInViewport(cm)
4101
+ var barMeasure = measureForScrollbars(cm)
4102
+ updateSelection(cm)
4103
+ updateScrollbars(cm, barMeasure)
4104
+ setDocumentHeight(cm, barMeasure)
4105
+ }
4106
+
4107
+ update.signal(cm, "update", cm)
4108
+ if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
4109
+ update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo)
4110
+ cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo
4111
+ }
4112
+ }
4113
+
4114
+ function updateDisplaySimple(cm, viewport) {
4115
+ var update = new DisplayUpdate(cm, viewport)
4116
+ if (updateDisplayIfNeeded(cm, update)) {
4117
+ updateHeightsInViewport(cm)
4118
+ postUpdateDisplay(cm, update)
4119
+ var barMeasure = measureForScrollbars(cm)
4120
+ updateSelection(cm)
4121
+ updateScrollbars(cm, barMeasure)
4122
+ setDocumentHeight(cm, barMeasure)
4123
+ update.finish()
4124
+ }
4125
+ }
4126
+
4127
+ // Sync the actual display DOM structure with display.view, removing
4128
+ // nodes for lines that are no longer in view, and creating the ones
4129
+ // that are not there yet, and updating the ones that are out of
4130
+ // date.
4131
+ function patchDisplay(cm, updateNumbersFrom, dims) {
4132
+ var display = cm.display, lineNumbers = cm.options.lineNumbers
4133
+ var container = display.lineDiv, cur = container.firstChild
4134
+
4135
+ function rm(node) {
4136
+ var next = node.nextSibling
4137
+ // Works around a throw-scroll bug in OS X Webkit
4138
+ if (webkit && mac && cm.display.currentWheelTarget == node)
4139
+ { node.style.display = "none" }
4140
+ else
4141
+ { node.parentNode.removeChild(node) }
4142
+ return next
4143
+ }
4144
+
4145
+ var view = display.view, lineN = display.viewFrom
4146
+ // Loop over the elements in the view, syncing cur (the DOM nodes
4147
+ // in display.lineDiv) with the view as we go.
4148
+ for (var i = 0; i < view.length; i++) {
4149
+ var lineView = view[i]
4150
+ if (lineView.hidden) {
4151
+ } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
4152
+ var node = buildLineElement(cm, lineView, lineN, dims)
4153
+ container.insertBefore(node, cur)
4154
+ } else { // Already drawn
4155
+ while (cur != lineView.node) { cur = rm(cur) }
4156
+ var updateNumber = lineNumbers && updateNumbersFrom != null &&
4157
+ updateNumbersFrom <= lineN && lineView.lineNumber
4158
+ if (lineView.changes) {
4159
+ if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false }
4160
+ updateLineForChanges(cm, lineView, lineN, dims)
4161
+ }
4162
+ if (updateNumber) {
4163
+ removeChildren(lineView.lineNumber)
4164
+ lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)))
4165
+ }
4166
+ cur = lineView.node.nextSibling
4167
+ }
4168
+ lineN += lineView.size
4169
+ }
4170
+ while (cur) { cur = rm(cur) }
4171
+ }
4172
+
4173
+ function updateGutterSpace(cm) {
4174
+ var width = cm.display.gutters.offsetWidth
4175
+ cm.display.sizer.style.marginLeft = width + "px"
4176
+ }
4177
+
4178
+ function setDocumentHeight(cm, measure) {
4179
+ cm.display.sizer.style.minHeight = measure.docHeight + "px"
4180
+ cm.display.heightForcer.style.top = measure.docHeight + "px"
4181
+ cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"
4182
+ }
4183
+
4184
+ // Rebuild the gutter elements, ensure the margin to the left of the
4185
+ // code matches their width.
4186
+ function updateGutters(cm) {
4187
+ var gutters = cm.display.gutters, specs = cm.options.gutters
4188
+ removeChildren(gutters)
4189
+ var i = 0
4190
+ for (; i < specs.length; ++i) {
4191
+ var gutterClass = specs[i]
4192
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass))
4193
+ if (gutterClass == "CodeMirror-linenumbers") {
4194
+ cm.display.lineGutter = gElt
4195
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px"
4196
+ }
4197
+ }
4198
+ gutters.style.display = i ? "" : "none"
4199
+ updateGutterSpace(cm)
4200
+ }
4201
+
4202
+ // Make sure the gutters options contains the element
4203
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
4204
+ function setGuttersForLineNumbers(options) {
4205
+ var found = indexOf(options.gutters, "CodeMirror-linenumbers")
4206
+ if (found == -1 && options.lineNumbers) {
4207
+ options.gutters = options.gutters.concat(["CodeMirror-linenumbers"])
4208
+ } else if (found > -1 && !options.lineNumbers) {
4209
+ options.gutters = options.gutters.slice(0)
4210
+ options.gutters.splice(found, 1)
4211
+ }
4212
+ }
4213
+
4214
+ // Selection objects are immutable. A new one is created every time
4215
+ // the selection changes. A selection is one or more non-overlapping
4216
+ // (and non-touching) ranges, sorted, and an integer that indicates
4217
+ // which one is the primary selection (the one that's scrolled into
4218
+ // view, that getCursor returns, etc).
4219
+ function Selection(ranges, primIndex) {
4220
+ this.ranges = ranges
4221
+ this.primIndex = primIndex
4222
+ }
4223
+
4224
+ Selection.prototype = {
4225
+ primary: function() { return this.ranges[this.primIndex] },
4226
+ equals: function(other) {
4227
+ var this$1 = this;
4228
+
4229
+ if (other == this) { return true }
4230
+ if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
4231
+ for (var i = 0; i < this.ranges.length; i++) {
4232
+ var here = this$1.ranges[i], there = other.ranges[i]
4233
+ if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) { return false }
4234
+ }
4235
+ return true
4236
+ },
4237
+ deepCopy: function() {
4238
+ var this$1 = this;
4239
+
4240
+ var out = []
4241
+ for (var i = 0; i < this.ranges.length; i++)
4242
+ { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)) }
4243
+ return new Selection(out, this.primIndex)
4244
+ },
4245
+ somethingSelected: function() {
4246
+ var this$1 = this;
4247
+
4248
+ for (var i = 0; i < this.ranges.length; i++)
4249
+ { if (!this$1.ranges[i].empty()) { return true } }
4250
+ return false
4251
+ },
4252
+ contains: function(pos, end) {
4253
+ var this$1 = this;
4254
+
4255
+ if (!end) { end = pos }
4256
+ for (var i = 0; i < this.ranges.length; i++) {
4257
+ var range = this$1.ranges[i]
4258
+ if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
4259
+ { return i }
4260
+ }
4261
+ return -1
4262
+ }
4263
+ }
4264
+
4265
+ function Range(anchor, head) {
4266
+ this.anchor = anchor; this.head = head
4267
+ }
4268
+
4269
+ Range.prototype = {
4270
+ from: function() { return minPos(this.anchor, this.head) },
4271
+ to: function() { return maxPos(this.anchor, this.head) },
4272
+ empty: function() {
4273
+ return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch
4274
+ }
4275
+ }
4276
+
4277
+ // Take an unsorted, potentially overlapping set of ranges, and
4278
+ // build a selection out of it. 'Consumes' ranges array (modifying
4279
+ // it).
4280
+ function normalizeSelection(ranges, primIndex) {
4281
+ var prim = ranges[primIndex]
4282
+ ranges.sort(function (a, b) { return cmp(a.from(), b.from()); })
4283
+ primIndex = indexOf(ranges, prim)
4284
+ for (var i = 1; i < ranges.length; i++) {
4285
+ var cur = ranges[i], prev = ranges[i - 1]
4286
+ if (cmp(prev.to(), cur.from()) >= 0) {
4287
+ var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to())
4288
+ var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head
4289
+ if (i <= primIndex) { --primIndex }
4290
+ ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to))
4291
+ }
4292
+ }
4293
+ return new Selection(ranges, primIndex)
4294
+ }
4295
+
4296
+ function simpleSelection(anchor, head) {
4297
+ return new Selection([new Range(anchor, head || anchor)], 0)
4298
+ }
4299
+
4300
+ // Compute the position of the end of a change (its 'to' property
4301
+ // refers to the pre-change end).
4302
+ function changeEnd(change) {
4303
+ if (!change.text) { return change.to }
4304
+ return Pos(change.from.line + change.text.length - 1,
4305
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))
4306
+ }
4307
+
4308
+ // Adjust a position to refer to the post-change position of the
4309
+ // same text, or the end of the change if the change covers it.
4310
+ function adjustForChange(pos, change) {
4311
+ if (cmp(pos, change.from) < 0) { return pos }
4312
+ if (cmp(pos, change.to) <= 0) { return changeEnd(change) }
4313
+
4314
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch
4315
+ if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch }
4316
+ return Pos(line, ch)
4317
+ }
4318
+
4319
+ function computeSelAfterChange(doc, change) {
4320
+ var out = []
4321
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
4322
+ var range = doc.sel.ranges[i]
4323
+ out.push(new Range(adjustForChange(range.anchor, change),
4324
+ adjustForChange(range.head, change)))
4325
+ }
4326
+ return normalizeSelection(out, doc.sel.primIndex)
4327
+ }
4328
+
4329
+ function offsetPos(pos, old, nw) {
4330
+ if (pos.line == old.line)
4331
+ { return Pos(nw.line, pos.ch - old.ch + nw.ch) }
4332
+ else
4333
+ { return Pos(nw.line + (pos.line - old.line), pos.ch) }
4334
+ }
4335
+
4336
+ // Used by replaceSelections to allow moving the selection to the
4337
+ // start or around the replaced test. Hint may be "start" or "around".
4338
+ function computeReplacedSel(doc, changes, hint) {
4339
+ var out = []
4340
+ var oldPrev = Pos(doc.first, 0), newPrev = oldPrev
4341
+ for (var i = 0; i < changes.length; i++) {
4342
+ var change = changes[i]
4343
+ var from = offsetPos(change.from, oldPrev, newPrev)
4344
+ var to = offsetPos(changeEnd(change), oldPrev, newPrev)
4345
+ oldPrev = change.to
4346
+ newPrev = to
4347
+ if (hint == "around") {
4348
+ var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0
4349
+ out[i] = new Range(inv ? to : from, inv ? from : to)
4350
+ } else {
4351
+ out[i] = new Range(from, from)
4352
+ }
4353
+ }
4354
+ return new Selection(out, doc.sel.primIndex)
4355
+ }
4356
+
4357
+ // Used to get the editor into a consistent state again when options change.
4358
+
4359
+ function loadMode(cm) {
4360
+ cm.doc.mode = getMode(cm.options, cm.doc.modeOption)
4361
+ resetModeState(cm)
4362
+ }
4363
+
4364
+ function resetModeState(cm) {
4365
+ cm.doc.iter(function (line) {
4366
+ if (line.stateAfter) { line.stateAfter = null }
4367
+ if (line.styles) { line.styles = null }
4368
+ })
4369
+ cm.doc.frontier = cm.doc.first
4370
+ startWorker(cm, 100)
4371
+ cm.state.modeGen++
4372
+ if (cm.curOp) { regChange(cm) }
4373
+ }
4374
+
4375
+ // DOCUMENT DATA STRUCTURE
4376
+
4377
+ // By default, updates that start and end at the beginning of a line
4378
+ // are treated specially, in order to make the association of line
4379
+ // widgets and marker elements with the text behave more intuitive.
4380
+ function isWholeLineUpdate(doc, change) {
4381
+ return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
4382
+ (!doc.cm || doc.cm.options.wholeLineUpdateBefore)
4383
+ }
4384
+
4385
+ // Perform a change on the document data structure.
4386
+ function updateDoc(doc, change, markedSpans, estimateHeight) {
4387
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null}
4388
+ function update(line, text, spans) {
4389
+ updateLine(line, text, spans, estimateHeight)
4390
+ signalLater(line, "change", line, change)
4391
+ }
4392
+ function linesFor(start, end) {
4393
+ var result = []
4394
+ for (var i = start; i < end; ++i)
4395
+ { result.push(new Line(text[i], spansFor(i), estimateHeight)) }
4396
+ return result
4397
+ }
4398
+
4399
+ var from = change.from, to = change.to, text = change.text
4400
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line)
4401
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line
4402
+
4403
+ // Adjust the line structure
4404
+ if (change.full) {
4405
+ doc.insert(0, linesFor(0, text.length))
4406
+ doc.remove(text.length, doc.size - text.length)
4407
+ } else if (isWholeLineUpdate(doc, change)) {
4408
+ // This is a whole-line replace. Treated specially to make
4409
+ // sure line objects move the way they are supposed to.
4410
+ var added = linesFor(0, text.length - 1)
4411
+ update(lastLine, lastLine.text, lastSpans)
4412
+ if (nlines) { doc.remove(from.line, nlines) }
4413
+ if (added.length) { doc.insert(from.line, added) }
4414
+ } else if (firstLine == lastLine) {
4415
+ if (text.length == 1) {
4416
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans)
4417
+ } else {
4418
+ var added$1 = linesFor(1, text.length - 1)
4419
+ added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight))
4420
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0))
4421
+ doc.insert(from.line + 1, added$1)
4422
+ }
4423
+ } else if (text.length == 1) {
4424
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0))
4425
+ doc.remove(from.line + 1, nlines)
4426
+ } else {
4427
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0))
4428
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans)
4429
+ var added$2 = linesFor(1, text.length - 1)
4430
+ if (nlines > 1) { doc.remove(from.line + 1, nlines - 1) }
4431
+ doc.insert(from.line + 1, added$2)
4432
+ }
4433
+
4434
+ signalLater(doc, "change", doc, change)
4435
+ }
4436
+
4437
+ // Call f for all linked documents.
4438
+ function linkedDocs(doc, f, sharedHistOnly) {
4439
+ function propagate(doc, skip, sharedHist) {
4440
+ if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {
4441
+ var rel = doc.linked[i]
4442
+ if (rel.doc == skip) { continue }
4443
+ var shared = sharedHist && rel.sharedHist
4444
+ if (sharedHistOnly && !shared) { continue }
4445
+ f(rel.doc, shared)
4446
+ propagate(rel.doc, doc, shared)
4447
+ } }
4448
+ }
4449
+ propagate(doc, null, true)
4450
+ }
4451
+
4452
+ // Attach a document to an editor.
4453
+ function attachDoc(cm, doc) {
4454
+ if (doc.cm) { throw new Error("This document is already in use.") }
4455
+ cm.doc = doc
4456
+ doc.cm = cm
4457
+ estimateLineHeights(cm)
4458
+ loadMode(cm)
4459
+ if (!cm.options.lineWrapping) { findMaxLine(cm) }
4460
+ cm.options.mode = doc.modeOption
4461
+ regChange(cm)
4462
+ }
4463
+
4464
+ function History(startGen) {
4465
+ // Arrays of change events and selections. Doing something adds an
4466
+ // event to done and clears undo. Undoing moves events from done
4467
+ // to undone, redoing moves them in the other direction.
4468
+ this.done = []; this.undone = []
4469
+ this.undoDepth = Infinity
4470
+ // Used to track when changes can be merged into a single undo
4471
+ // event
4472
+ this.lastModTime = this.lastSelTime = 0
4473
+ this.lastOp = this.lastSelOp = null
4474
+ this.lastOrigin = this.lastSelOrigin = null
4475
+ // Used by the isClean() method
4476
+ this.generation = this.maxGeneration = startGen || 1
4477
+ }
4478
+
4479
+ // Create a history change event from an updateDoc-style change
4480
+ // object.
4481
+ function historyChangeFromChange(doc, change) {
4482
+ var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}
4483
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1)
4484
+ linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true)
4485
+ return histChange
4486
+ }
4487
+
4488
+ // Pop all selection events off the end of a history array. Stop at
4489
+ // a change event.
4490
+ function clearSelectionEvents(array) {
4491
+ while (array.length) {
4492
+ var last = lst(array)
4493
+ if (last.ranges) { array.pop() }
4494
+ else { break }
4495
+ }
4496
+ }
4497
+
4498
+ // Find the top change event in the history. Pop off selection
4499
+ // events that are in the way.
4500
+ function lastChangeEvent(hist, force) {
4501
+ if (force) {
4502
+ clearSelectionEvents(hist.done)
4503
+ return lst(hist.done)
4504
+ } else if (hist.done.length && !lst(hist.done).ranges) {
4505
+ return lst(hist.done)
4506
+ } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
4507
+ hist.done.pop()
4508
+ return lst(hist.done)
4509
+ }
4510
+ }
4511
+
4512
+ // Register a change in the history. Merges changes that are within
4513
+ // a single operation, or are close together with an origin that
4514
+ // allows merging (starting with "+") into a single event.
4515
+ function addChangeToHistory(doc, change, selAfter, opId) {
4516
+ var hist = doc.history
4517
+ hist.undone.length = 0
4518
+ var time = +new Date, cur
4519
+ var last
4520
+
4521
+ if ((hist.lastOp == opId ||
4522
+ hist.lastOrigin == change.origin && change.origin &&
4523
+ ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
4524
+ change.origin.charAt(0) == "*")) &&
4525
+ (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
4526
+ // Merge this change into the last event
4527
+ last = lst(cur.changes)
4528
+ if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
4529
+ // Optimized case for simple insertion -- don't want to add
4530
+ // new changesets for every character typed
4531
+ last.to = changeEnd(change)
4532
+ } else {
4533
+ // Add new sub-event
4534
+ cur.changes.push(historyChangeFromChange(doc, change))
4535
+ }
4536
+ } else {
4537
+ // Can not be merged, start a new event.
4538
+ var before = lst(hist.done)
4539
+ if (!before || !before.ranges)
4540
+ { pushSelectionToHistory(doc.sel, hist.done) }
4541
+ cur = {changes: [historyChangeFromChange(doc, change)],
4542
+ generation: hist.generation}
4543
+ hist.done.push(cur)
4544
+ while (hist.done.length > hist.undoDepth) {
4545
+ hist.done.shift()
4546
+ if (!hist.done[0].ranges) { hist.done.shift() }
4547
+ }
4548
+ }
4549
+ hist.done.push(selAfter)
4550
+ hist.generation = ++hist.maxGeneration
4551
+ hist.lastModTime = hist.lastSelTime = time
4552
+ hist.lastOp = hist.lastSelOp = opId
4553
+ hist.lastOrigin = hist.lastSelOrigin = change.origin
4554
+
4555
+ if (!last) { signal(doc, "historyAdded") }
4556
+ }
4557
+
4558
+ function selectionEventCanBeMerged(doc, origin, prev, sel) {
4559
+ var ch = origin.charAt(0)
4560
+ return ch == "*" ||
4561
+ ch == "+" &&
4562
+ prev.ranges.length == sel.ranges.length &&
4563
+ prev.somethingSelected() == sel.somethingSelected() &&
4564
+ new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
4565
+ }
4566
+
4567
+ // Called whenever the selection changes, sets the new selection as
4568
+ // the pending selection in the history, and pushes the old pending
4569
+ // selection into the 'done' array when it was significantly
4570
+ // different (in number of selected ranges, emptiness, or time).
4571
+ function addSelectionToHistory(doc, sel, opId, options) {
4572
+ var hist = doc.history, origin = options && options.origin
4573
+
4574
+ // A new event is started when the previous origin does not match
4575
+ // the current, or the origins don't allow matching. Origins
4576
+ // starting with * are always merged, those starting with + are
4577
+ // merged when similar and close together in time.
4578
+ if (opId == hist.lastSelOp ||
4579
+ (origin && hist.lastSelOrigin == origin &&
4580
+ (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
4581
+ selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
4582
+ { hist.done[hist.done.length - 1] = sel }
4583
+ else
4584
+ { pushSelectionToHistory(sel, hist.done) }
4585
+
4586
+ hist.lastSelTime = +new Date
4587
+ hist.lastSelOrigin = origin
4588
+ hist.lastSelOp = opId
4589
+ if (options && options.clearRedo !== false)
4590
+ { clearSelectionEvents(hist.undone) }
4591
+ }
4592
+
4593
+ function pushSelectionToHistory(sel, dest) {
4594
+ var top = lst(dest)
4595
+ if (!(top && top.ranges && top.equals(sel)))
4596
+ { dest.push(sel) }
4597
+ }
4598
+
4599
+ // Used to store marked span information in the history.
4600
+ function attachLocalSpans(doc, change, from, to) {
4601
+ var existing = change["spans_" + doc.id], n = 0
4602
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {
4603
+ if (line.markedSpans)
4604
+ { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans }
4605
+ ++n
4606
+ })
4607
+ }
4608
+
4609
+ // When un/re-doing restores text containing marked spans, those
4610
+ // that have been explicitly cleared should not be restored.
4611
+ function removeClearedSpans(spans) {
4612
+ if (!spans) { return null }
4613
+ var out
4614
+ for (var i = 0; i < spans.length; ++i) {
4615
+ if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i) } }
4616
+ else if (out) { out.push(spans[i]) }
4617
+ }
4618
+ return !out ? spans : out.length ? out : null
4619
+ }
4620
+
4621
+ // Retrieve and filter the old marked spans stored in a change event.
4622
+ function getOldSpans(doc, change) {
4623
+ var found = change["spans_" + doc.id]
4624
+ if (!found) { return null }
4625
+ var nw = []
4626
+ for (var i = 0; i < change.text.length; ++i)
4627
+ { nw.push(removeClearedSpans(found[i])) }
4628
+ return nw
4629
+ }
4630
+
4631
+ // Used for un/re-doing changes from the history. Combines the
4632
+ // result of computing the existing spans with the set of spans that
4633
+ // existed in the history (so that deleting around a span and then
4634
+ // undoing brings back the span).
4635
+ function mergeOldSpans(doc, change) {
4636
+ var old = getOldSpans(doc, change)
4637
+ var stretched = stretchSpansOverChange(doc, change)
4638
+ if (!old) { return stretched }
4639
+ if (!stretched) { return old }
4640
+
4641
+ for (var i = 0; i < old.length; ++i) {
4642
+ var oldCur = old[i], stretchCur = stretched[i]
4643
+ if (oldCur && stretchCur) {
4644
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
4645
+ var span = stretchCur[j]
4646
+ for (var k = 0; k < oldCur.length; ++k)
4647
+ { if (oldCur[k].marker == span.marker) { continue spans } }
4648
+ oldCur.push(span)
4649
+ }
4650
+ } else if (stretchCur) {
4651
+ old[i] = stretchCur
4652
+ }
4653
+ }
4654
+ return old
4655
+ }
4656
+
4657
+ // Used both to provide a JSON-safe object in .getHistory, and, when
4658
+ // detaching a document, to split the history in two
4659
+ function copyHistoryArray(events, newGroup, instantiateSel) {
4660
+ var copy = []
4661
+ for (var i = 0; i < events.length; ++i) {
4662
+ var event = events[i]
4663
+ if (event.ranges) {
4664
+ copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event)
4665
+ continue
4666
+ }
4667
+ var changes = event.changes, newChanges = []
4668
+ copy.push({changes: newChanges})
4669
+ for (var j = 0; j < changes.length; ++j) {
4670
+ var change = changes[j], m = (void 0)
4671
+ newChanges.push({from: change.from, to: change.to, text: change.text})
4672
+ if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) {
4673
+ if (indexOf(newGroup, Number(m[1])) > -1) {
4674
+ lst(newChanges)[prop] = change[prop]
4675
+ delete change[prop]
4676
  }
4677
+ } } }
4678
+ }
4679
+ }
4680
+ return copy
4681
+ }
4682
+
4683
+ // The 'scroll' parameter given to many of these indicated whether
4684
+ // the new cursor position should be scrolled into view after
4685
+ // modifying the selection.
4686
+
4687
+ // If shift is held or the extend flag is set, extends a range to
4688
+ // include a given position (and optionally a second position).
4689
+ // Otherwise, simply returns the range between the given positions.
4690
+ // Used for cursor motion and such.
4691
+ function extendRange(doc, range, head, other) {
4692
+ if (doc.cm && doc.cm.display.shift || doc.extend) {
4693
+ var anchor = range.anchor
4694
+ if (other) {
4695
+ var posBefore = cmp(head, anchor) < 0
4696
+ if (posBefore != (cmp(other, anchor) < 0)) {
4697
+ anchor = head
4698
+ head = other
4699
+ } else if (posBefore != (cmp(head, other) < 0)) {
4700
+ head = other
4701
+ }
4702
+ }
4703
+ return new Range(anchor, head)
4704
+ } else {
4705
+ return new Range(other || head, head)
4706
+ }
4707
+ }
4708
+
4709
+ // Extend the primary selection range, discard the rest.
4710
+ function extendSelection(doc, head, other, options) {
4711
+ setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options)
4712
+ }
4713
+
4714
+ // Extend all selections (pos is an array of selections with length
4715
+ // equal the number of selections)
4716
+ function extendSelections(doc, heads, options) {
4717
+ var out = []
4718
+ for (var i = 0; i < doc.sel.ranges.length; i++)
4719
+ { out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null) }
4720
+ var newSel = normalizeSelection(out, doc.sel.primIndex)
4721
+ setSelection(doc, newSel, options)
4722
+ }
4723
+
4724
+ // Updates a single range in the selection.
4725
+ function replaceOneSelection(doc, i, range, options) {
4726
+ var ranges = doc.sel.ranges.slice(0)
4727
+ ranges[i] = range
4728
+ setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options)
4729
+ }
4730
+
4731
+ // Reset the selection to a single range.
4732
+ function setSimpleSelection(doc, anchor, head, options) {
4733
+ setSelection(doc, simpleSelection(anchor, head), options)
4734
+ }
4735
+
4736
+ // Give beforeSelectionChange handlers a change to influence a
4737
+ // selection update.
4738
+ function filterSelectionChange(doc, sel, options) {
4739
+ var obj = {
4740
+ ranges: sel.ranges,
4741
+ update: function(ranges) {
4742
+ var this$1 = this;
4743
+
4744
+ this.ranges = []
4745
+ for (var i = 0; i < ranges.length; i++)
4746
+ { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
4747
+ clipPos(doc, ranges[i].head)) }
4748
+ },
4749
+ origin: options && options.origin
4750
+ }
4751
+ signal(doc, "beforeSelectionChange", doc, obj)
4752
+ if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj) }
4753
+ if (obj.ranges != sel.ranges) { return normalizeSelection(obj.ranges, obj.ranges.length - 1) }
4754
+ else { return sel }
4755
+ }
4756
+
4757
+ function setSelectionReplaceHistory(doc, sel, options) {
4758
+ var done = doc.history.done, last = lst(done)
4759
+ if (last && last.ranges) {
4760
+ done[done.length - 1] = sel
4761
+ setSelectionNoUndo(doc, sel, options)
4762
+ } else {
4763
+ setSelection(doc, sel, options)
4764
+ }
4765
+ }
4766
+
4767
+ // Set a new selection.
4768
+ function setSelection(doc, sel, options) {
4769
+ setSelectionNoUndo(doc, sel, options)
4770
+ addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options)
4771
+ }
4772
+
4773
+ function setSelectionNoUndo(doc, sel, options) {
4774
+ if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
4775
+ { sel = filterSelectionChange(doc, sel, options) }
4776
+
4777
+ var bias = options && options.bias ||
4778
+ (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1)
4779
+ setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true))
4780
+
4781
+ if (!(options && options.scroll === false) && doc.cm)
4782
+ { ensureCursorVisible(doc.cm) }
4783
+ }
4784
+
4785
+ function setSelectionInner(doc, sel) {
4786
+ if (sel.equals(doc.sel)) { return }
4787
+
4788
+ doc.sel = sel
4789
+
4790
+ if (doc.cm) {
4791
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true
4792
+ signalCursorActivity(doc.cm)
4793
+ }
4794
+ signalLater(doc, "cursorActivity", doc)
4795
+ }
4796
+
4797
+ // Verify that the selection does not partially select any atomic
4798
+ // marked ranges.
4799
+ function reCheckSelection(doc) {
4800
+ setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll)
4801
+ }
4802
+
4803
+ // Return a selection that does not partially select any atomic
4804
+ // ranges.
4805
+ function skipAtomicInSelection(doc, sel, bias, mayClear) {
4806
+ var out
4807
+ for (var i = 0; i < sel.ranges.length; i++) {
4808
+ var range = sel.ranges[i]
4809
+ var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]
4810
+ var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear)
4811
+ var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear)
4812
+ if (out || newAnchor != range.anchor || newHead != range.head) {
4813
+ if (!out) { out = sel.ranges.slice(0, i) }
4814
+ out[i] = new Range(newAnchor, newHead)
4815
+ }
4816
+ }
4817
+ return out ? normalizeSelection(out, sel.primIndex) : sel
4818
+ }
4819
+
4820
+ function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
4821
+ var line = getLine(doc, pos.line)
4822
+ if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
4823
+ var sp = line.markedSpans[i], m = sp.marker
4824
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
4825
+ (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
4826
+ if (mayClear) {
4827
+ signal(m, "beforeCursorEnter")
4828
+ if (m.explicitlyCleared) {
4829
+ if (!line.markedSpans) { break }
4830
+ else {--i; continue}
4831
  }
 
4832
  }
4833
+ if (!m.atomic) { continue }
4834
+
4835
+ if (oldPos) {
4836
+ var near = m.find(dir < 0 ? 1 : -1), diff = (void 0)
4837
+ if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft)
4838
+ { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null) }
4839
+ if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
4840
+ { return skipAtomicInner(doc, near, pos, dir, mayClear) }
4841
+ }
4842
+
4843
+ var far = m.find(dir < 0 ? -1 : 1)
4844
+ if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight)
4845
+ { far = movePos(doc, far, dir, far.line == pos.line ? line : null) }
4846
+ return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null
4847
+ }
4848
+ } }
4849
+ return pos
4850
+ }
4851
+
4852
+ // Ensure a given position is not inside an atomic range.
4853
+ function skipAtomic(doc, pos, oldPos, bias, mayClear) {
4854
+ var dir = bias || 1
4855
+ var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
4856
+ (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
4857
+ skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
4858
+ (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true))
4859
+ if (!found) {
4860
+ doc.cantEdit = true
4861
+ return Pos(doc.first, 0)
4862
+ }
4863
+ return found
4864
+ }
4865
+
4866
+ function movePos(doc, pos, dir, line) {
4867
+ if (dir < 0 && pos.ch == 0) {
4868
+ if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }
4869
+ else { return null }
4870
+ } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
4871
+ if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }
4872
+ else { return null }
4873
+ } else {
4874
+ return new Pos(pos.line, pos.ch + dir)
4875
+ }
4876
+ }
4877
+
4878
+ function selectAll(cm) {
4879
+ cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll)
4880
+ }
4881
+
4882
+ // UPDATING
4883
+
4884
+ // Allow "beforeChange" event handlers to influence a change
4885
+ function filterChange(doc, change, update) {
4886
+ var obj = {
4887
+ canceled: false,
4888
+ from: change.from,
4889
+ to: change.to,
4890
+ text: change.text,
4891
+ origin: change.origin,
4892
+ cancel: function () { return obj.canceled = true; }
4893
+ }
4894
+ if (update) { obj.update = function (from, to, text, origin) {
4895
+ if (from) { obj.from = clipPos(doc, from) }
4896
+ if (to) { obj.to = clipPos(doc, to) }
4897
+ if (text) { obj.text = text }
4898
+ if (origin !== undefined) { obj.origin = origin }
4899
+ } }
4900
+ signal(doc, "beforeChange", doc, obj)
4901
+ if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj) }
4902
+
4903
+ if (obj.canceled) { return null }
4904
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}
4905
+ }
4906
+
4907
+ // Apply a change to a document, and add it to the document's
4908
+ // history, and propagating it to all linked documents.
4909
+ function makeChange(doc, change, ignoreReadOnly) {
4910
+ if (doc.cm) {
4911
+ if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }
4912
+ if (doc.cm.state.suppressEdits) { return }
4913
+ }
4914
+
4915
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
4916
+ change = filterChange(doc, change, true)
4917
+ if (!change) { return }
4918
+ }
4919
+
4920
+ // Possibly split or suppress the update based on the presence
4921
+ // of read-only spans in its range.
4922
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to)
4923
+ if (split) {
4924
+ for (var i = split.length - 1; i >= 0; --i)
4925
+ { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}) }
4926
+ } else {
4927
+ makeChangeInner(doc, change)
4928
+ }
4929
+ }
4930
+
4931
+ function makeChangeInner(doc, change) {
4932
+ if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return }
4933
+ var selAfter = computeSelAfterChange(doc, change)
4934
+ addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN)
4935
+
4936
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change))
4937
+ var rebased = []
4938
+
4939
+ linkedDocs(doc, function (doc, sharedHist) {
4940
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
4941
+ rebaseHist(doc.history, change)
4942
+ rebased.push(doc.history)
4943
+ }
4944
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change))
4945
+ })
4946
+ }
4947
+
4948
+ // Revert a change stored in a document's history.
4949
+ function makeChangeFromHistory(doc, type, allowSelectionOnly) {
4950
+ if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return }
4951
+
4952
+ var hist = doc.history, event, selAfter = doc.sel
4953
+ var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done
4954
+
4955
+ // Verify that there is a useable event (so that ctrl-z won't
4956
+ // needlessly clear selection events)
4957
+ var i = 0
4958
+ for (; i < source.length; i++) {
4959
+ event = source[i]
4960
+ if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
4961
+ { break }
4962
+ }
4963
+ if (i == source.length) { return }
4964
+ hist.lastOrigin = hist.lastSelOrigin = null
4965
+
4966
+ for (;;) {
4967
+ event = source.pop()
4968
+ if (event.ranges) {
4969
+ pushSelectionToHistory(event, dest)
4970
+ if (allowSelectionOnly && !event.equals(doc.sel)) {
4971
+ setSelection(doc, event, {clearRedo: false})
4972
+ return
4973
+ }
4974
+ selAfter = event
4975
+ }
4976
+ else { break }
4977
+ }
4978
+
4979
+ // Build up a reverse change object to add to the opposite history
4980
+ // stack (redo when undoing, and vice versa).
4981
+ var antiChanges = []
4982
+ pushSelectionToHistory(selAfter, dest)
4983
+ dest.push({changes: antiChanges, generation: hist.generation})
4984
+ hist.generation = event.generation || ++hist.maxGeneration
4985
+
4986
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")
4987
+
4988
+ var loop = function ( i ) {
4989
+ var change = event.changes[i]
4990
+ change.origin = type
4991
+ if (filter && !filterChange(doc, change, false)) {
4992
+ source.length = 0
4993
+ return {}
4994
+ }
4995
+
4996
+ antiChanges.push(historyChangeFromChange(doc, change))
4997
+
4998
+ var after = i ? computeSelAfterChange(doc, change) : lst(source)
4999
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change))
5000
+ if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}) }
5001
+ var rebased = []
 
5002
 
5003
+ // Propagate to the linked documents
5004
+ linkedDocs(doc, function (doc, sharedHist) {
5005
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
5006
+ rebaseHist(doc.history, change)
5007
+ rebased.push(doc.history)
 
 
 
5008
  }
5009
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change))
5010
+ })
 
 
 
 
 
 
 
 
 
 
 
 
 
5011
  };
5012
 
5013
+ for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {
5014
+ var returned = loop( i$1 );
5015
+
5016
+ if ( returned ) return returned.v;
5017
+ }
5018
+ }
5019
+
5020
+ // Sub-views need their line numbers shifted when text is added
5021
+ // above or below them in the parent document.
5022
+ function shiftDoc(doc, distance) {
5023
+ if (distance == 0) { return }
5024
+ doc.first += distance
5025
+ doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(
5026
+ Pos(range.anchor.line + distance, range.anchor.ch),
5027
+ Pos(range.head.line + distance, range.head.ch)
5028
+ ); }), doc.sel.primIndex)
5029
+ if (doc.cm) {
5030
+ regChange(doc.cm, doc.first, doc.first - distance, distance)
5031
+ for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
5032
+ { regLineChange(doc.cm, l, "gutter") }
5033
+ }
5034
+ }
5035
+
5036
+ // More lower-level change function, handling only a single document
5037
+ // (not linked ones).
5038
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
5039
+ if (doc.cm && !doc.cm.curOp)
5040
+ { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }
5041
+
5042
+ if (change.to.line < doc.first) {
5043
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line))
5044
+ return
5045
+ }
5046
+ if (change.from.line > doc.lastLine()) { return }
5047
+
5048
+ // Clip the change to the size of this doc
5049
+ if (change.from.line < doc.first) {
5050
+ var shift = change.text.length - 1 - (doc.first - change.from.line)
5051
+ shiftDoc(doc, shift)
5052
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
5053
+ text: [lst(change.text)], origin: change.origin}
5054
+ }
5055
+ var last = doc.lastLine()
5056
+ if (change.to.line > last) {
5057
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
5058
+ text: [change.text[0]], origin: change.origin}
5059
+ }
5060
+
5061
+ change.removed = getBetween(doc, change.from, change.to)
5062
+
5063
+ if (!selAfter) { selAfter = computeSelAfterChange(doc, change) }
5064
+ if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans) }
5065
+ else { updateDoc(doc, change, spans) }
5066
+ setSelectionNoUndo(doc, selAfter, sel_dontScroll)
5067
+ }
5068
+
5069
+ // Handle the interaction of a change to a document with the editor
5070
+ // that this document is part of.
5071
+ function makeChangeSingleDocInEditor(cm, change, spans) {
5072
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to
5073
+
5074
+ var recomputeMaxLength = false, checkWidthStart = from.line
5075
+ if (!cm.options.lineWrapping) {
5076
+ checkWidthStart = lineNo(visualLine(getLine(doc, from.line)))
5077
+ doc.iter(checkWidthStart, to.line + 1, function (line) {
5078
+ if (line == display.maxLine) {
5079
+ recomputeMaxLength = true
5080
+ return true
5081
+ }
5082
+ })
5083
+ }
5084
+
5085
+ if (doc.sel.contains(change.from, change.to) > -1)
5086
+ { signalCursorActivity(cm) }
5087
+
5088
+ updateDoc(doc, change, spans, estimateHeight(cm))
5089
+
5090
+ if (!cm.options.lineWrapping) {
5091
+ doc.iter(checkWidthStart, from.line + change.text.length, function (line) {
5092
+ var len = lineLength(line)
5093
+ if (len > display.maxLineLength) {
5094
+ display.maxLine = line
5095
+ display.maxLineLength = len
5096
+ display.maxLineChanged = true
5097
+ recomputeMaxLength = false
5098
+ }
5099
+ })
5100
+ if (recomputeMaxLength) { cm.curOp.updateMaxLine = true }
5101
+ }
5102
+
5103
+ // Adjust frontier, schedule worker
5104
+ doc.frontier = Math.min(doc.frontier, from.line)
5105
+ startWorker(cm, 400)
5106
+
5107
+ var lendiff = change.text.length - (to.line - from.line) - 1
5108
+ // Remember that these lines changed, for updating the display
5109
+ if (change.full)
5110
+ { regChange(cm) }
5111
+ else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
5112
+ { regLineChange(cm, from.line, "text") }
5113
+ else
5114
+ { regChange(cm, from.line, to.line + 1, lendiff) }
5115
+
5116
+ var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change")
5117
+ if (changeHandler || changesHandler) {
5118
+ var obj = {
5119
+ from: from, to: to,
5120
+ text: change.text,
5121
+ removed: change.removed,
5122
+ origin: change.origin
5123
+ }
5124
+ if (changeHandler) { signalLater(cm, "change", cm, obj) }
5125
+ if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) }
5126
+ }
5127
+ cm.display.selForContextMenu = null
5128
+ }
5129
+
5130
+ function replaceRange(doc, code, from, to, origin) {
5131
+ if (!to) { to = from }
5132
+ if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp }
5133
+ if (typeof code == "string") { code = doc.splitLines(code) }
5134
+ makeChange(doc, {from: from, to: to, text: code, origin: origin})
5135
+ }
5136
+
5137
+ // Rebasing/resetting history to deal with externally-sourced changes
5138
+
5139
+ function rebaseHistSelSingle(pos, from, to, diff) {
5140
+ if (to < pos.line) {
5141
+ pos.line += diff
5142
+ } else if (from < pos.line) {
5143
+ pos.line = from
5144
+ pos.ch = 0
5145
+ }
5146
+ }
5147
+
5148
+ // Tries to rebase an array of history events given a change in the
5149
+ // document. If the change touches the same lines as the event, the
5150
+ // event, and everything 'behind' it, is discarded. If the change is
5151
+ // before the event, the event's positions are updated. Uses a
5152
+ // copy-on-write scheme for the positions, to avoid having to
5153
+ // reallocate them all on every rebase, but also avoid problems with
5154
+ // shared position objects being unsafely updated.
5155
+ function rebaseHistArray(array, from, to, diff) {
5156
+ for (var i = 0; i < array.length; ++i) {
5157
+ var sub = array[i], ok = true
5158
+ if (sub.ranges) {
5159
+ if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true }
5160
+ for (var j = 0; j < sub.ranges.length; j++) {
5161
+ rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff)
5162
+ rebaseHistSelSingle(sub.ranges[j].head, from, to, diff)
5163
+ }
5164
+ continue
5165
+ }
5166
+ for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {
5167
+ var cur = sub.changes[j$1]
5168
+ if (to < cur.from.line) {
5169
+ cur.from = Pos(cur.from.line + diff, cur.from.ch)
5170
+ cur.to = Pos(cur.to.line + diff, cur.to.ch)
5171
+ } else if (from <= cur.to.line) {
5172
+ ok = false
5173
+ break
5174
+ }
5175
+ }
5176
+ if (!ok) {
5177
+ array.splice(0, i + 1)
5178
+ i = 0
5179
+ }
5180
+ }
5181
+ }
5182
+
5183
+ function rebaseHist(hist, change) {
5184
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1
5185
+ rebaseHistArray(hist.done, from, to, diff)
5186
+ rebaseHistArray(hist.undone, from, to, diff)
5187
+ }
5188
+
5189
+ // Utility for applying a change to a line by handle or number,
5190
+ // returning the number and optionally registering the line as
5191
+ // changed.
5192
+ function changeLine(doc, handle, changeType, op) {
5193
+ var no = handle, line = handle
5194
+ if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)) }
5195
+ else { no = lineNo(handle) }
5196
+ if (no == null) { return null }
5197
+ if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType) }
5198
+ return line
5199
+ }
5200
+
5201
+ // The document is represented as a BTree consisting of leaves, with
5202
+ // chunk of lines in them, and branches, with up to ten leaves or
5203
+ // other branch nodes below them. The top node is always a branch
5204
+ // node, and is the document object itself (meaning it has
5205
+ // additional methods and properties).
5206
+ //
5207
+ // All nodes have parent links. The tree is used both to go from
5208
+ // line numbers to line objects, and to go from objects to numbers.
5209
+ // It also indexes by height, and is used to convert between height
5210
+ // and line object, and to find the total height of the document.
5211
+ //
5212
+ // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
5213
+
5214
+ function LeafChunk(lines) {
5215
+ var this$1 = this;
5216
+
5217
+ this.lines = lines
5218
+ this.parent = null
5219
+ var height = 0
5220
+ for (var i = 0; i < lines.length; ++i) {
5221
+ lines[i].parent = this$1
5222
+ height += lines[i].height
5223
+ }
5224
+ this.height = height
5225
+ }
5226
+
5227
+ LeafChunk.prototype = {
5228
+ chunkSize: function() { return this.lines.length },
5229
+ // Remove the n lines at offset 'at'.
5230
+ removeInner: function(at, n) {
5231
+ var this$1 = this;
5232
+
5233
+ for (var i = at, e = at + n; i < e; ++i) {
5234
+ var line = this$1.lines[i]
5235
+ this$1.height -= line.height
5236
+ cleanUpLine(line)
5237
+ signalLater(line, "delete")
5238
+ }
5239
+ this.lines.splice(at, n)
5240
+ },
5241
+ // Helper used to collapse a small branch into a single leaf.
5242
+ collapse: function(lines) {
5243
+ lines.push.apply(lines, this.lines)
5244
+ },
5245
+ // Insert the given array of lines at offset 'at', count them as
5246
+ // having the given height.
5247
+ insertInner: function(at, lines, height) {
5248
+ var this$1 = this;
5249
+
5250
+ this.height += height
5251
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at))
5252
+ for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1 }
5253
+ },
5254
+ // Used to iterate over a part of the tree.
5255
+ iterN: function(at, n, op) {
5256
+ var this$1 = this;
5257
+
5258
+ for (var e = at + n; at < e; ++at)
5259
+ { if (op(this$1.lines[at])) { return true } }
5260
+ }
5261
+ }
5262
+
5263
+ function BranchChunk(children) {
5264
+ var this$1 = this;
5265
+
5266
+ this.children = children
5267
+ var size = 0, height = 0
5268
+ for (var i = 0; i < children.length; ++i) {
5269
+ var ch = children[i]
5270
+ size += ch.chunkSize(); height += ch.height
5271
+ ch.parent = this$1
5272
+ }
5273
+ this.size = size
5274
+ this.height = height
5275
+ this.parent = null
5276
+ }
5277
+
5278
+ BranchChunk.prototype = {
5279
+ chunkSize: function() { return this.size },
5280
+ removeInner: function(at, n) {
5281
+ var this$1 = this;
5282
+
5283
+ this.size -= n
5284
+ for (var i = 0; i < this.children.length; ++i) {
5285
+ var child = this$1.children[i], sz = child.chunkSize()
5286
+ if (at < sz) {
5287
+ var rm = Math.min(n, sz - at), oldHeight = child.height
5288
+ child.removeInner(at, rm)
5289
+ this$1.height -= oldHeight - child.height
5290
+ if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null }
5291
+ if ((n -= rm) == 0) { break }
5292
+ at = 0
5293
+ } else { at -= sz }
5294
+ }
5295
+ // If the result is smaller than 25 lines, ensure that it is a
5296
+ // single leaf node.
5297
+ if (this.size - n < 25 &&
5298
+ (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
5299
+ var lines = []
5300
+ this.collapse(lines)
5301
+ this.children = [new LeafChunk(lines)]
5302
+ this.children[0].parent = this
5303
+ }
5304
+ },
5305
+ collapse: function(lines) {
5306
+ var this$1 = this;
5307
+
5308
+ for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines) }
5309
+ },
5310
+ insertInner: function(at, lines, height) {
5311
+ var this$1 = this;
5312
+
5313
+ this.size += lines.length
5314
+ this.height += height
5315
+ for (var i = 0; i < this.children.length; ++i) {
5316
+ var child = this$1.children[i], sz = child.chunkSize()
5317
+ if (at <= sz) {
5318
+ child.insertInner(at, lines, height)
5319
+ if (child.lines && child.lines.length > 50) {
5320
+ // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
5321
+ // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
5322
+ var remaining = child.lines.length % 25 + 25
5323
+ for (var pos = remaining; pos < child.lines.length;) {
5324
+ var leaf = new LeafChunk(child.lines.slice(pos, pos += 25))
5325
+ child.height -= leaf.height
5326
+ this$1.children.splice(++i, 0, leaf)
5327
+ leaf.parent = this$1
5328
+ }
5329
+ child.lines = child.lines.slice(0, remaining)
5330
+ this$1.maybeSpill()
5331
  }
5332
+ break
 
5333
  }
5334
+ at -= sz
5335
  }
5336
+ },
5337
+ // When a node has grown, check whether it should be split.
5338
+ maybeSpill: function() {
5339
+ if (this.children.length <= 10) { return }
5340
+ var me = this
5341
+ do {
5342
+ var spilled = me.children.splice(me.children.length - 5, 5)
5343
+ var sibling = new BranchChunk(spilled)
5344
+ if (!me.parent) { // Become the parent node
5345
+ var copy = new BranchChunk(me.children)
5346
+ copy.parent = me
5347
+ me.children = [copy, sibling]
5348
+ me = copy
5349
+ } else {
5350
+ me.size -= sibling.size
5351
+ me.height -= sibling.height
5352
+ var myIndex = indexOf(me.parent.children, me)
5353
+ me.parent.children.splice(myIndex + 1, 0, sibling)
5354
+ }
5355
+ sibling.parent = me.parent
5356
+ } while (me.children.length > 10)
5357
+ me.parent.maybeSpill()
5358
+ },
5359
+ iterN: function(at, n, op) {
5360
+ var this$1 = this;
5361
+
5362
+ for (var i = 0; i < this.children.length; ++i) {
5363
+ var child = this$1.children[i], sz = child.chunkSize()
5364
+ if (at < sz) {
5365
+ var used = Math.min(n, sz - at)
5366
+ if (child.iterN(at, used, op)) { return true }
5367
+ if ((n -= used) == 0) { break }
5368
+ at = 0
5369
+ } else { at -= sz }
5370
+ }
5371
+ }
5372
+ }
5373
+
5374
+ // Line widgets are block elements displayed above or below a line.
5375
+
5376
+ function LineWidget(doc, node, options) {
5377
+ var this$1 = this;
5378
+
5379
+ if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
5380
+ { this$1[opt] = options[opt] } } }
5381
+ this.doc = doc
5382
+ this.node = node
5383
+ }
5384
+ eventMixin(LineWidget)
5385
+
5386
+ function adjustScrollWhenAboveVisible(cm, line, diff) {
5387
+ if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
5388
+ { addToScrollPos(cm, null, diff) }
5389
+ }
5390
+
5391
+ LineWidget.prototype.clear = function() {
5392
+ var this$1 = this;
5393
+
5394
+ var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line)
5395
+ if (no == null || !ws) { return }
5396
+ for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1) } }
5397
+ if (!ws.length) { line.widgets = null }
5398
+ var height = widgetHeight(this)
5399
+ updateLineHeight(line, Math.max(0, line.height - height))
5400
+ if (cm) { runInOp(cm, function () {
5401
+ adjustScrollWhenAboveVisible(cm, line, -height)
5402
+ regLineChange(cm, no, "widget")
5403
+ }) }
5404
+ }
5405
+ LineWidget.prototype.changed = function() {
5406
+ var oldH = this.height, cm = this.doc.cm, line = this.line
5407
+ this.height = null
5408
+ var diff = widgetHeight(this) - oldH
5409
+ if (!diff) { return }
5410
+ updateLineHeight(line, line.height + diff)
5411
+ if (cm) { runInOp(cm, function () {
5412
+ cm.curOp.forceUpdate = true
5413
+ adjustScrollWhenAboveVisible(cm, line, diff)
5414
+ }) }
5415
+ }
5416
+
5417
+ function addLineWidget(doc, handle, node, options) {
5418
+ var widget = new LineWidget(doc, node, options)
5419
+ var cm = doc.cm
5420
+ if (cm && widget.noHScroll) { cm.display.alignWidgets = true }
5421
+ changeLine(doc, handle, "widget", function (line) {
5422
+ var widgets = line.widgets || (line.widgets = [])
5423
+ if (widget.insertAt == null) { widgets.push(widget) }
5424
+ else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget) }
5425
+ widget.line = line
5426
+ if (cm && !lineIsHidden(doc, line)) {
5427
+ var aboveVisible = heightAtLine(line) < doc.scrollTop
5428
+ updateLineHeight(line, line.height + widgetHeight(widget))
5429
+ if (aboveVisible) { addToScrollPos(cm, null, widget.height) }
5430
+ cm.curOp.forceUpdate = true
5431
+ }
5432
+ return true
5433
+ })
5434
+ return widget
5435
+ }
5436
+
5437
+ // TEXTMARKERS
5438
+
5439
+ // Created with markText and setBookmark methods. A TextMarker is a
5440
+ // handle that can be used to clear or find a marked position in the
5441
+ // document. Line objects hold arrays (markedSpans) containing
5442
+ // {from, to, marker} object pointing to such marker objects, and
5443
+ // indicating that such a marker is present on that line. Multiple
5444
+ // lines may point to the same marker when it spans across lines.
5445
+ // The spans will have null for their from/to properties when the
5446
+ // marker continues beyond the start/end of the line. Markers have
5447
+ // links back to the lines they currently touch.
5448
+
5449
+ // Collapsed markers have unique ids, in order to be able to order
5450
+ // them, which is needed for uniquely determining an outer marker
5451
+ // when they overlap (they may nest, but not partially overlap).
5452
+ var nextMarkerId = 0
5453
+
5454
+ function TextMarker(doc, type) {
5455
+ this.lines = []
5456
+ this.type = type
5457
+ this.doc = doc
5458
+ this.id = ++nextMarkerId
5459
+ }
5460
+ eventMixin(TextMarker)
5461
+
5462
+ // Clear the marker.
5463
+ TextMarker.prototype.clear = function() {
5464
+ var this$1 = this;
5465
+
5466
+ if (this.explicitlyCleared) { return }
5467
+ var cm = this.doc.cm, withOp = cm && !cm.curOp
5468
+ if (withOp) { startOperation(cm) }
5469
+ if (hasHandler(this, "clear")) {
5470
+ var found = this.find()
5471
+ if (found) { signalLater(this, "clear", found.from, found.to) }
5472
+ }
5473
+ var min = null, max = null
5474
+ for (var i = 0; i < this.lines.length; ++i) {
5475
+ var line = this$1.lines[i]
5476
+ var span = getMarkedSpanFor(line.markedSpans, this$1)
5477
+ if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text") }
5478
+ else if (cm) {
5479
+ if (span.to != null) { max = lineNo(line) }
5480
+ if (span.from != null) { min = lineNo(line) }
5481
+ }
5482
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span)
5483
+ if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm)
5484
+ { updateLineHeight(line, textHeight(cm.display)) }
5485
+ }
5486
+ if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
5487
+ var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual)
5488
+ if (len > cm.display.maxLineLength) {
5489
+ cm.display.maxLine = visual
5490
+ cm.display.maxLineLength = len
5491
+ cm.display.maxLineChanged = true
5492
+ }
5493
+ } }
5494
+
5495
+ if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1) }
5496
+ this.lines.length = 0
5497
+ this.explicitlyCleared = true
5498
+ if (this.atomic && this.doc.cantEdit) {
5499
+ this.doc.cantEdit = false
5500
+ if (cm) { reCheckSelection(cm.doc) }
5501
+ }
5502
+ if (cm) { signalLater(cm, "markerCleared", cm, this) }
5503
+ if (withOp) { endOperation(cm) }
5504
+ if (this.parent) { this.parent.clear() }
5505
+ }
5506
+
5507
+ // Find the position of the marker in the document. Returns a {from,
5508
+ // to} object by default. Side can be passed to get a specific side
5509
+ // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
5510
+ // Pos objects returned contain a line object, rather than a line
5511
+ // number (used to prevent looking up the same line twice).
5512
+ TextMarker.prototype.find = function(side, lineObj) {
5513
+ var this$1 = this;
5514
+
5515
+ if (side == null && this.type == "bookmark") { side = 1 }
5516
+ var from, to
5517
+ for (var i = 0; i < this.lines.length; ++i) {
5518
+ var line = this$1.lines[i]
5519
+ var span = getMarkedSpanFor(line.markedSpans, this$1)
5520
+ if (span.from != null) {
5521
+ from = Pos(lineObj ? line : lineNo(line), span.from)
5522
+ if (side == -1) { return from }
5523
+ }
5524
+ if (span.to != null) {
5525
+ to = Pos(lineObj ? line : lineNo(line), span.to)
5526
+ if (side == 1) { return to }
5527
+ }
5528
+ }
5529
+ return from && {from: from, to: to}
5530
+ }
5531
+
5532
+ // Signals that the marker's widget changed, and surrounding layout
5533
+ // should be recomputed.
5534
+ TextMarker.prototype.changed = function() {
5535
+ var pos = this.find(-1, true), widget = this, cm = this.doc.cm
5536
+ if (!pos || !cm) { return }
5537
+ runInOp(cm, function () {
5538
+ var line = pos.line, lineN = lineNo(pos.line)
5539
+ var view = findViewForLine(cm, lineN)
5540
+ if (view) {
5541
+ clearLineMeasurementCacheFor(view)
5542
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = true
5543
+ }
5544
+ cm.curOp.updateMaxLine = true
5545
+ if (!lineIsHidden(widget.doc, line) && widget.height != null) {
5546
+ var oldHeight = widget.height
5547
+ widget.height = null
5548
+ var dHeight = widgetHeight(widget) - oldHeight
5549
+ if (dHeight)
5550
+ { updateLineHeight(line, line.height + dHeight) }
5551
+ }
5552
+ })
5553
+ }
5554
+
5555
+ TextMarker.prototype.attachLine = function(line) {
5556
+ if (!this.lines.length && this.doc.cm) {
5557
+ var op = this.doc.cm.curOp
5558
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
5559
+ { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this) }
5560
+ }
5561
+ this.lines.push(line)
5562
+ }
5563
+ TextMarker.prototype.detachLine = function(line) {
5564
+ this.lines.splice(indexOf(this.lines, line), 1)
5565
+ if (!this.lines.length && this.doc.cm) {
5566
+ var op = this.doc.cm.curOp
5567
+ ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this)
5568
+ }
5569
+ }
5570
+
5571
+ // Create a marker, wire it up to the right lines, and
5572
+ function markText(doc, from, to, options, type) {
5573
+ // Shared markers (across linked documents) are handled separately
5574
+ // (markTextShared will call out to this again, once per
5575
+ // document).
5576
+ if (options && options.shared) { return markTextShared(doc, from, to, options, type) }
5577
+ // Ensure we are in an operation.
5578
+ if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }
5579
+
5580
+ var marker = new TextMarker(doc, type), diff = cmp(from, to)
5581
+ if (options) { copyObj(options, marker, false) }
5582
+ // Don't connect empty markers unless clearWhenEmpty is false
5583
+ if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
5584
+ { return marker }
5585
+ if (marker.replacedWith) {
5586
+ // Showing up as a widget implies collapsed (widget replaces text)
5587
+ marker.collapsed = true
5588
+ marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget")
5589
+ marker.widgetNode.setAttribute("role", "presentation") // hide from accessibility tree
5590
+ if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true") }
5591
+ if (options.insertLeft) { marker.widgetNode.insertLeft = true }
5592
+ }
5593
+ if (marker.collapsed) {
5594
+ if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
5595
+ from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
5596
+ { throw new Error("Inserting collapsed marker partially overlapping an existing one") }
5597
+ seeCollapsedSpans()
5598
+ }
5599
+
5600
+ if (marker.addToHistory)
5601
+ { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN) }
5602
+
5603
+ var curLine = from.line, cm = doc.cm, updateMaxLine
5604
+ doc.iter(curLine, to.line + 1, function (line) {
5605
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
5606
+ { updateMaxLine = true }
5607
+ if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0) }
5608
+ addMarkedSpan(line, new MarkedSpan(marker,
5609
+ curLine == from.line ? from.ch : null,
5610
+ curLine == to.line ? to.ch : null))
5611
+ ++curLine
5612
+ })
5613
+ // lineIsHidden depends on the presence of the spans, so needs a second pass
5614
+ if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
5615
+ if (lineIsHidden(doc, line)) { updateLineHeight(line, 0) }
5616
+ }) }
5617
+
5618
+ if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }) }
5619
+
5620
+ if (marker.readOnly) {
5621
+ seeReadOnlySpans()
5622
+ if (doc.history.done.length || doc.history.undone.length)
5623
+ { doc.clearHistory() }
5624
+ }
5625
+ if (marker.collapsed) {
5626
+ marker.id = ++nextMarkerId
5627
+ marker.atomic = true
5628
+ }
5629
+ if (cm) {
5630
+ // Sync editor state
5631
+ if (updateMaxLine) { cm.curOp.updateMaxLine = true }
5632
+ if (marker.collapsed)
5633
+ { regChange(cm, from.line, to.line + 1) }
5634
+ else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
5635
+ { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text") } }
5636
+ if (marker.atomic) { reCheckSelection(cm.doc) }
5637
+ signalLater(cm, "markerAdded", cm, marker)
5638
+ }
5639
+ return marker
5640
+ }
5641
+
5642
+ // SHARED TEXTMARKERS
5643
+
5644
+ // A shared marker spans multiple linked documents. It is
5645
+ // implemented as a meta-marker-object controlling multiple normal
5646
+ // markers.
5647
+ function SharedTextMarker(markers, primary) {
5648
+ var this$1 = this;
5649
+
5650
+ this.markers = markers
5651
+ this.primary = primary
5652
+ for (var i = 0; i < markers.length; ++i)
5653
+ { markers[i].parent = this$1 }
5654
+ }
5655
+ eventMixin(SharedTextMarker)
5656
+
5657
+ SharedTextMarker.prototype.clear = function() {
5658
+ var this$1 = this;
5659
+
5660
+ if (this.explicitlyCleared) { return }
5661
+ this.explicitlyCleared = true
5662
+ for (var i = 0; i < this.markers.length; ++i)
5663
+ { this$1.markers[i].clear() }
5664
+ signalLater(this, "clear")
5665
+ }
5666
+ SharedTextMarker.prototype.find = function(side, lineObj) {
5667
+ return this.primary.find(side, lineObj)
5668
+ }
5669
+
5670
+ function markTextShared(doc, from, to, options, type) {
5671
+ options = copyObj(options)
5672
+ options.shared = false
5673
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0]
5674
+ var widget = options.widgetNode
5675
+ linkedDocs(doc, function (doc) {
5676
+ if (widget) { options.widgetNode = widget.cloneNode(true) }
5677
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type))
5678
+ for (var i = 0; i < doc.linked.length; ++i)
5679
+ { if (doc.linked[i].isParent) { return } }
5680
+ primary = lst(markers)
5681
+ })
5682
+ return new SharedTextMarker(markers, primary)
5683
+ }
5684
+
5685
+ function findSharedMarkers(doc) {
5686
+ return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })
5687
+ }
5688
+
5689
+ function copySharedMarkers(doc, markers) {
5690
+ for (var i = 0; i < markers.length; i++) {
5691
+ var marker = markers[i], pos = marker.find()
5692
+ var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to)
5693
+ if (cmp(mFrom, mTo)) {
5694
+ var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type)
5695
+ marker.markers.push(subMark)
5696
+ subMark.parent = marker
5697
+ }
5698
+ }
5699
+ }
5700
+
5701
+ function detachSharedMarkers(markers) {
5702
+ var loop = function ( i ) {
5703
+ var marker = markers[i], linked = [marker.primary.doc]
5704
+ linkedDocs(marker.primary.doc, function (d) { return linked.push(d); })
5705
+ for (var j = 0; j < marker.markers.length; j++) {
5706
+ var subMarker = marker.markers[j]
5707
+ if (indexOf(linked, subMarker.doc) == -1) {
5708
+ subMarker.parent = null
5709
+ marker.markers.splice(j--, 1)
5710
  }
 
5711
  }
5712
+ };
5713
 
5714
+ for (var i = 0; i < markers.length; i++) loop( i );
5715
+ }
5716
+
5717
+ var nextDocId = 0
5718
+ var Doc = function(text, mode, firstLine, lineSep) {
5719
+ if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep) }
5720
+ if (firstLine == null) { firstLine = 0 }
5721
+
5722
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])])
5723
+ this.first = firstLine
5724
+ this.scrollTop = this.scrollLeft = 0
5725
+ this.cantEdit = false
5726
+ this.cleanGeneration = 1
5727
+ this.frontier = firstLine
5728
+ var start = Pos(firstLine, 0)
5729
+ this.sel = simpleSelection(start)
5730
+ this.history = new History(null)
5731
+ this.id = ++nextDocId
5732
+ this.modeOption = mode
5733
+ this.lineSep = lineSep
5734
+ this.extend = false
5735
+
5736
+ if (typeof text == "string") { text = this.splitLines(text) }
5737
+ updateDoc(this, {from: start, to: start, text: text})
5738
+ setSelection(this, simpleSelection(start), sel_dontScroll)
5739
+ }
5740
+
5741
+ Doc.prototype = createObj(BranchChunk.prototype, {
5742
+ constructor: Doc,
5743
+ // Iterate over the document. Supports two forms -- with only one
5744
+ // argument, it calls that for each line in the document. With
5745
+ // three, it iterates over the range given by the first two (with
5746
+ // the second being non-inclusive).
5747
+ iter: function(from, to, op) {
5748
+ if (op) { this.iterN(from - this.first, to - from, op) }
5749
+ else { this.iterN(this.first, this.first + this.size, from) }
5750
+ },
5751
+
5752
+ // Non-public interface for adding and removing lines.
5753
+ insert: function(at, lines) {
5754
+ var height = 0
5755
+ for (var i = 0; i < lines.length; ++i) { height += lines[i].height }
5756
+ this.insertInner(at - this.first, lines, height)
5757
+ },
5758
+ remove: function(at, n) { this.removeInner(at - this.first, n) },
5759
+
5760
+ // From here, the methods are part of the public interface. Most
5761
+ // are also available from CodeMirror (editor) instances.
5762
+
5763
+ getValue: function(lineSep) {
5764
+ var lines = getLines(this, this.first, this.first + this.size)
5765
+ if (lineSep === false) { return lines }
5766
+ return lines.join(lineSep || this.lineSeparator())
5767
+ },
5768
+ setValue: docMethodOp(function(code) {
5769
+ var top = Pos(this.first, 0), last = this.first + this.size - 1
5770
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
5771
+ text: this.splitLines(code), origin: "setValue", full: true}, true)
5772
+ setSelection(this, simpleSelection(top))
5773
+ }),
5774
+ replaceRange: function(code, from, to, origin) {
5775
+ from = clipPos(this, from)
5776
+ to = to ? clipPos(this, to) : from
5777
+ replaceRange(this, code, from, to, origin)
5778
+ },
5779
+ getRange: function(from, to, lineSep) {
5780
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to))
5781
+ if (lineSep === false) { return lines }
5782
+ return lines.join(lineSep || this.lineSeparator())
5783
+ },
5784
+
5785
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},
5786
+
5787
+ getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},
5788
+ getLineNumber: function(line) {return lineNo(line)},
5789
+
5790
+ getLineHandleVisualStart: function(line) {
5791
+ if (typeof line == "number") { line = getLine(this, line) }
5792
+ return visualLine(line)
5793
+ },
5794
+
5795
+ lineCount: function() {return this.size},
5796
+ firstLine: function() {return this.first},
5797
+ lastLine: function() {return this.first + this.size - 1},
5798
+
5799
+ clipPos: function(pos) {return clipPos(this, pos)},
5800
+
5801
+ getCursor: function(start) {
5802
+ var range = this.sel.primary(), pos
5803
+ if (start == null || start == "head") { pos = range.head }
5804
+ else if (start == "anchor") { pos = range.anchor }
5805
+ else if (start == "end" || start == "to" || start === false) { pos = range.to() }
5806
+ else { pos = range.from() }
5807
+ return pos
5808
+ },
5809
+ listSelections: function() { return this.sel.ranges },
5810
+ somethingSelected: function() {return this.sel.somethingSelected()},
5811
+
5812
+ setCursor: docMethodOp(function(line, ch, options) {
5813
+ setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options)
5814
+ }),
5815
+ setSelection: docMethodOp(function(anchor, head, options) {
5816
+ setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options)
5817
+ }),
5818
+ extendSelection: docMethodOp(function(head, other, options) {
5819
+ extendSelection(this, clipPos(this, head), other && clipPos(this, other), options)
5820
+ }),
5821
+ extendSelections: docMethodOp(function(heads, options) {
5822
+ extendSelections(this, clipPosArray(this, heads), options)
5823
+ }),
5824
+ extendSelectionsBy: docMethodOp(function(f, options) {
5825
+ var heads = map(this.sel.ranges, f)
5826
+ extendSelections(this, clipPosArray(this, heads), options)
5827
+ }),
5828
+ setSelections: docMethodOp(function(ranges, primary, options) {
5829
+ var this$1 = this;
5830
+
5831
+ if (!ranges.length) { return }
5832
+ var out = []
5833
+ for (var i = 0; i < ranges.length; i++)
5834
+ { out[i] = new Range(clipPos(this$1, ranges[i].anchor),
5835
+ clipPos(this$1, ranges[i].head)) }
5836
+ if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex) }
5837
+ setSelection(this, normalizeSelection(out, primary), options)
5838
+ }),
5839
+ addSelection: docMethodOp(function(anchor, head, options) {
5840
+ var ranges = this.sel.ranges.slice(0)
5841
+ ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)))
5842
+ setSelection(this, normalizeSelection(ranges, ranges.length - 1), options)
5843
+ }),
5844
+
5845
+ getSelection: function(lineSep) {
5846
+ var this$1 = this;
5847
+
5848
+ var ranges = this.sel.ranges, lines
5849
+ for (var i = 0; i < ranges.length; i++) {
5850
+ var sel = getBetween(this$1, ranges[i].from(), ranges[i].to())
5851
+ lines = lines ? lines.concat(sel) : sel
5852
  }
5853
+ if (lineSep === false) { return lines }
5854
+ else { return lines.join(lineSep || this.lineSeparator()) }
5855
+ },
5856
+ getSelections: function(lineSep) {
5857
+ var this$1 = this;
 
 
 
 
 
5858
 
5859
+ var parts = [], ranges = this.sel.ranges
5860
+ for (var i = 0; i < ranges.length; i++) {
5861
+ var sel = getBetween(this$1, ranges[i].from(), ranges[i].to())
5862
+ if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()) }
5863
+ parts[i] = sel
5864
+ }
5865
+ return parts
5866
+ },
5867
+ replaceSelection: function(code, collapse, origin) {
5868
+ var dup = []
5869
+ for (var i = 0; i < this.sel.ranges.length; i++)
5870
+ { dup[i] = code }
5871
+ this.replaceSelections(dup, collapse, origin || "+input")
5872
+ },
5873
+ replaceSelections: docMethodOp(function(code, collapse, origin) {
5874
+ var this$1 = this;
5875
+
5876
+ var changes = [], sel = this.sel
5877
+ for (var i = 0; i < sel.ranges.length; i++) {
5878
+ var range = sel.ranges[i]
5879
+ changes[i] = {from: range.from(), to: range.to(), text: this$1.splitLines(code[i]), origin: origin}
5880
+ }
5881
+ var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse)
5882
+ for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
5883
+ { makeChange(this$1, changes[i$1]) }
5884
+ if (newSel) { setSelectionReplaceHistory(this, newSel) }
5885
+ else if (this.cm) { ensureCursorVisible(this.cm) }
5886
+ }),
5887
+ undo: docMethodOp(function() {makeChangeFromHistory(this, "undo")}),
5888
+ redo: docMethodOp(function() {makeChangeFromHistory(this, "redo")}),
5889
+ undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true)}),
5890
+ redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true)}),
5891
+
5892
+ setExtending: function(val) {this.extend = val},
5893
+ getExtending: function() {return this.extend},
5894
+
5895
+ historySize: function() {
5896
+ var hist = this.history, done = 0, undone = 0
5897
+ for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done } }
5898
+ for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone } }
5899
+ return {undo: done, redo: undone}
5900
+ },
5901
+ clearHistory: function() {this.history = new History(this.history.maxGeneration)},
5902
+
5903
+ markClean: function() {
5904
+ this.cleanGeneration = this.changeGeneration(true)
5905
+ },
5906
+ changeGeneration: function(forceSplit) {
5907
+ if (forceSplit)
5908
+ { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null }
5909
+ return this.history.generation
5910
+ },
5911
+ isClean: function (gen) {
5912
+ return this.history.generation == (gen || this.cleanGeneration)
5913
+ },
5914
+
5915
+ getHistory: function() {
5916
+ return {done: copyHistoryArray(this.history.done),
5917
+ undone: copyHistoryArray(this.history.undone)}
5918
+ },
5919
+ setHistory: function(histData) {
5920
+ var hist = this.history = new History(this.history.maxGeneration)
5921
+ hist.done = copyHistoryArray(histData.done.slice(0), null, true)
5922
+ hist.undone = copyHistoryArray(histData.undone.slice(0), null, true)
5923
+ },
5924
+
5925
+ setGutterMarker: docMethodOp(function(line, gutterID, value) {
5926
+ return changeLine(this, line, "gutter", function (line) {
5927
+ var markers = line.gutterMarkers || (line.gutterMarkers = {})
5928
+ markers[gutterID] = value
5929
+ if (!value && isEmpty(markers)) { line.gutterMarkers = null }
5930
+ return true
5931
+ })
5932
+ }),
5933
+
5934
+ clearGutter: docMethodOp(function(gutterID) {
5935
+ var this$1 = this;
5936
+
5937
+ this.iter(function (line) {
5938
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
5939
+ changeLine(this$1, line, "gutter", function () {
5940
+ line.gutterMarkers[gutterID] = null
5941
+ if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null }
5942
+ return true
5943
+ })
5944
+ }
5945
+ })
5946
+ }),
5947
+
5948
+ lineInfo: function(line) {
5949
+ var n
5950
+ if (typeof line == "number") {
5951
+ if (!isLine(this, line)) { return null }
5952
+ n = line
5953
+ line = getLine(this, line)
5954
+ if (!line) { return null }
5955
+ } else {
5956
+ n = lineNo(line)
5957
+ if (n == null) { return null }
5958
+ }
5959
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
5960
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
5961
+ widgets: line.widgets}
5962
+ },
5963
+
5964
+ addLineClass: docMethodOp(function(handle, where, cls) {
5965
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
5966
+ var prop = where == "text" ? "textClass"
5967
+ : where == "background" ? "bgClass"
5968
+ : where == "gutter" ? "gutterClass" : "wrapClass"
5969
+ if (!line[prop]) { line[prop] = cls }
5970
+ else if (classTest(cls).test(line[prop])) { return false }
5971
+ else { line[prop] += " " + cls }
5972
+ return true
5973
+ })
5974
+ }),
5975
+ removeLineClass: docMethodOp(function(handle, where, cls) {
5976
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
5977
+ var prop = where == "text" ? "textClass"
5978
+ : where == "background" ? "bgClass"
5979
+ : where == "gutter" ? "gutterClass" : "wrapClass"
5980
+ var cur = line[prop]
5981
+ if (!cur) { return false }
5982
+ else if (cls == null) { line[prop] = null }
5983
+ else {
5984
+ var found = cur.match(classTest(cls))
5985
+ if (!found) { return false }
5986
+ var end = found.index + found[0].length
5987
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null
5988
+ }
5989
+ return true
5990
+ })
5991
+ }),
5992
+
5993
+ addLineWidget: docMethodOp(function(handle, node, options) {
5994
+ return addLineWidget(this, handle, node, options)
5995
+ }),
5996
+ removeLineWidget: function(widget) { widget.clear() },
5997
+
5998
+ markText: function(from, to, options) {
5999
+ return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range")
6000
+ },
6001
+ setBookmark: function(pos, options) {
6002
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
6003
+ insertLeft: options && options.insertLeft,
6004
+ clearWhenEmpty: false, shared: options && options.shared,
6005
+ handleMouseEvents: options && options.handleMouseEvents}
6006
+ pos = clipPos(this, pos)
6007
+ return markText(this, pos, pos, realOpts, "bookmark")
6008
+ },
6009
+ findMarksAt: function(pos) {
6010
+ pos = clipPos(this, pos)
6011
+ var markers = [], spans = getLine(this, pos.line).markedSpans
6012
+ if (spans) { for (var i = 0; i < spans.length; ++i) {
6013
+ var span = spans[i]
6014
+ if ((span.from == null || span.from <= pos.ch) &&
6015
+ (span.to == null || span.to >= pos.ch))
6016
+ { markers.push(span.marker.parent || span.marker) }
6017
+ } }
6018
+ return markers
6019
+ },
6020
+ findMarks: function(from, to, filter) {
6021
+ from = clipPos(this, from); to = clipPos(this, to)
6022
+ var found = [], lineNo = from.line
6023
+ this.iter(from.line, to.line + 1, function (line) {
6024
+ var spans = line.markedSpans
6025
+ if (spans) { for (var i = 0; i < spans.length; i++) {
6026
+ var span = spans[i]
6027
+ if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
6028
+ span.from == null && lineNo != from.line ||
6029
+ span.from != null && lineNo == to.line && span.from >= to.ch) &&
6030
+ (!filter || filter(span.marker)))
6031
+ { found.push(span.marker.parent || span.marker) }
6032
+ } }
6033
+ ++lineNo
6034
+ })
6035
+ return found
6036
+ },
6037
+ getAllMarks: function() {
6038
+ var markers = []
6039
+ this.iter(function (line) {
6040
+ var sps = line.markedSpans
6041
+ if (sps) { for (var i = 0; i < sps.length; ++i)
6042
+ { if (sps[i].from != null) { markers.push(sps[i].marker) } } }
6043
+ })
6044
+ return markers
6045
+ },
6046
+
6047
+ posFromIndex: function(off) {
6048
+ var ch, lineNo = this.first, sepSize = this.lineSeparator().length
6049
+ this.iter(function (line) {
6050
+ var sz = line.text.length + sepSize
6051
+ if (sz > off) { ch = off; return true }
6052
+ off -= sz
6053
+ ++lineNo
6054
+ })
6055
+ return clipPos(this, Pos(lineNo, ch))
6056
+ },
6057
+ indexFromPos: function (coords) {
6058
+ coords = clipPos(this, coords)
6059
+ var index = coords.ch
6060
+ if (coords.line < this.first || coords.ch < 0) { return 0 }
6061
+ var sepSize = this.lineSeparator().length
6062
+ this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value
6063
+ index += line.text.length + sepSize
6064
+ })
6065
+ return index
6066
+ },
6067
+
6068
+ copy: function(copyHistory) {
6069
+ var doc = new Doc(getLines(this, this.first, this.first + this.size),
6070
+ this.modeOption, this.first, this.lineSep)
6071
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft
6072
+ doc.sel = this.sel
6073
+ doc.extend = false
6074
+ if (copyHistory) {
6075
+ doc.history.undoDepth = this.history.undoDepth
6076
+ doc.setHistory(this.getHistory())
6077
+ }
6078
+ return doc
6079
+ },
6080
+
6081
+ linkedDoc: function(options) {
6082
+ if (!options) { options = {} }
6083
+ var from = this.first, to = this.first + this.size
6084
+ if (options.from != null && options.from > from) { from = options.from }
6085
+ if (options.to != null && options.to < to) { to = options.to }
6086
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep)
6087
+ if (options.sharedHist) { copy.history = this.history
6088
+ ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist})
6089
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]
6090
+ copySharedMarkers(copy, findSharedMarkers(this))
6091
+ return copy
6092
+ },
6093
+ unlinkDoc: function(other) {
6094
+ var this$1 = this;
6095
+
6096
+ if (other instanceof CodeMirror) { other = other.doc }
6097
+ if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
6098
+ var link = this$1.linked[i]
6099
+ if (link.doc != other) { continue }
6100
+ this$1.linked.splice(i, 1)
6101
+ other.unlinkDoc(this$1)
6102
+ detachSharedMarkers(findSharedMarkers(this$1))
6103
+ break
6104
+ } }
6105
+ // If the histories were shared, split them again
6106
+ if (other.history == this.history) {
6107
+ var splitIds = [other.id]
6108
+ linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true)
6109
+ other.history = new History(null)
6110
+ other.history.done = copyHistoryArray(this.history.done, splitIds)
6111
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds)
6112
+ }
6113
+ },
6114
+ iterLinkedDocs: function(f) {linkedDocs(this, f)},
6115
+
6116
+ getMode: function() {return this.mode},
6117
+ getEditor: function() {return this.cm},
6118
+
6119
+ splitLines: function(str) {
6120
+ if (this.lineSep) { return str.split(this.lineSep) }
6121
+ return splitLinesAuto(str)
6122
+ },
6123
+ lineSeparator: function() { return this.lineSep || "\n" }
6124
+ })
6125
+
6126
+ // Public alias.
6127
+ Doc.prototype.eachLine = Doc.prototype.iter
6128
+
6129
+ // Kludge to work around strange IE behavior where it'll sometimes
6130
+ // re-fire a series of drag-related events right after the drop (#1551)
6131
+ var lastDrop = 0
6132
+
6133
+ function onDrop(e) {
6134
+ var cm = this
6135
+ clearDragCursor(cm)
6136
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
6137
+ { return }
6138
+ e_preventDefault(e)
6139
+ if (ie) { lastDrop = +new Date }
6140
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files
6141
+ if (!pos || cm.isReadOnly()) { return }
6142
+ // Might be a file drop, in which case we simply extract the text
6143
+ // and insert it.
6144
+ if (files && files.length && window.FileReader && window.File) {
6145
+ var n = files.length, text = Array(n), read = 0
6146
+ var loadFile = function (file, i) {
6147
+ if (cm.options.allowDropFileTypes &&
6148
+ indexOf(cm.options.allowDropFileTypes, file.type) == -1)
6149
+ { return }
6150
+
6151
+ var reader = new FileReader
6152
+ reader.onload = operation(cm, function () {
6153
+ var content = reader.result
6154
+ if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = "" }
6155
+ text[i] = content
6156
+ if (++read == n) {
6157
+ pos = clipPos(cm.doc, pos)
6158
+ var change = {from: pos, to: pos,
6159
+ text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
6160
+ origin: "paste"}
6161
+ makeChange(cm.doc, change)
6162
+ setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)))
6163
+ }
6164
+ })
6165
+ reader.readAsText(file)
6166
+ }
6167
+ for (var i = 0; i < n; ++i) { loadFile(files[i], i) }
6168
+ } else { // Normal drop
6169
+ // Don't do a replace if the drop happened inside of the selected text.
6170
+ if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
6171
+ cm.state.draggingText(e)
6172
+ // Ensure the editor is re-focused
6173
+ setTimeout(function () { return cm.display.input.focus(); }, 20)
6174
+ return
6175
+ }
6176
+ try {
6177
+ var text$1 = e.dataTransfer.getData("Text")
6178
+ if (text$1) {
6179
+ var selected
6180
+ if (cm.state.draggingText && !cm.state.draggingText.copy)
6181
+ { selected = cm.listSelections() }
6182
+ setSelectionNoUndo(cm.doc, simpleSelection(pos, pos))
6183
+ if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)
6184
+ { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag") } }
6185
+ cm.replaceSelection(text$1, "around", "paste")
6186
+ cm.display.input.focus()
6187
+ }
6188
+ }
6189
+ catch(e){}
6190
+ }
6191
+ }
6192
+
6193
+ function onDragStart(cm, e) {
6194
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
6195
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }
6196
+
6197
+ e.dataTransfer.setData("Text", cm.getSelection())
6198
+ e.dataTransfer.effectAllowed = "copyMove"
6199
+
6200
+ // Use dummy image instead of default browsers image.
6201
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
6202
+ if (e.dataTransfer.setDragImage && !safari) {
6203
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;")
6204
+ img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
6205
+ if (presto) {
6206
+ img.width = img.height = 1
6207
+ cm.display.wrapper.appendChild(img)
6208
+ // Force a relayout, or Opera won't use our image for some obscure reason
6209
+ img._top = img.offsetTop
6210
+ }
6211
+ e.dataTransfer.setDragImage(img, 0, 0)
6212
+ if (presto) { img.parentNode.removeChild(img) }
6213
+ }
6214
+ }
6215
+
6216
+ function onDragOver(cm, e) {
6217
+ var pos = posFromMouse(cm, e)
6218
+ if (!pos) { return }
6219
+ var frag = document.createDocumentFragment()
6220
+ drawSelectionCursor(cm, pos, frag)
6221
+ if (!cm.display.dragCursor) {
6222
+ cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors")
6223
+ cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv)
6224
+ }
6225
+ removeChildrenAndAdd(cm.display.dragCursor, frag)
6226
+ }
6227
+
6228
+ function clearDragCursor(cm) {
6229
+ if (cm.display.dragCursor) {
6230
+ cm.display.lineSpace.removeChild(cm.display.dragCursor)
6231
+ cm.display.dragCursor = null
6232
+ }
6233
+ }
6234
+
6235
+ // These must be handled carefully, because naively registering a
6236
+ // handler for each editor will cause the editors to never be
6237
+ // garbage collected.
6238
+
6239
+ function forEachCodeMirror(f) {
6240
+ if (!document.body.getElementsByClassName) { return }
6241
+ var byClass = document.body.getElementsByClassName("CodeMirror")
6242
+ for (var i = 0; i < byClass.length; i++) {
6243
+ var cm = byClass[i].CodeMirror
6244
+ if (cm) { f(cm) }
6245
+ }
6246
+ }
6247
+
6248
+ var globalsRegistered = false
6249
+ function ensureGlobalHandlers() {
6250
+ if (globalsRegistered) { return }
6251
+ registerGlobalHandlers()
6252
+ globalsRegistered = true
6253
+ }
6254
+ function registerGlobalHandlers() {
6255
+ // When the window resizes, we need to refresh active editors.
6256
+ var resizeTimer
6257
+ on(window, "resize", function () {
6258
+ if (resizeTimer == null) { resizeTimer = setTimeout(function () {
6259
+ resizeTimer = null
6260
+ forEachCodeMirror(onResize)
6261
+ }, 100) }
6262
+ })
6263
+ // When the window loses focus, we want to show the editor as blurred
6264
+ on(window, "blur", function () { return forEachCodeMirror(onBlur); })
6265
+ }
6266
+ // Called when the window resizes
6267
+ function onResize(cm) {
6268
+ var d = cm.display
6269
+ if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
6270
+ { return }
6271
+ // Might be a text scaling operation, clear size caches.
6272
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null
6273
+ d.scrollbarsClipped = false
6274
+ cm.setSize()
6275
+ }
6276
+
6277
+ var keyNames = {
6278
+ 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
6279
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
6280
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
6281
+ 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
6282
+ 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
6283
+ 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
6284
+ 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
6285
+ 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
6286
+ }
6287
+
6288
+ // Number keys
6289
+ for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i) }
6290
+ // Alphabetic keys
6291
+ for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1) }
6292
+ // Function keys
6293
+ for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2 }
6294
+
6295
+ var keyMap = {}
6296
+
6297
+ keyMap.basic = {
6298
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
6299
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
6300
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
6301
+ "Tab": "defaultTab", "Shift-Tab": "indentAuto",
6302
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
6303
+ "Esc": "singleSelection"
6304
+ }
6305
+ // Note that the save and find-related commands aren't defined by
6306
+ // default. User code or addons can define them. Unknown commands
6307
+ // are simply ignored.
6308
+ keyMap.pcDefault = {
6309
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
6310
+ "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
6311
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
6312
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
6313
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
6314
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
6315
+ "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
6316
+ fallthrough: "basic"
6317
+ }
6318
+ // Very basic readline/emacs-style bindings, which are standard on Mac.
6319
+ keyMap.emacsy = {
6320
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
6321
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
6322
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
6323
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
6324
+ "Ctrl-O": "openLine"
6325
+ }
6326
+ keyMap.macDefault = {
6327
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
6328
+ "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
6329
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
6330
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
6331
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
6332
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
6333
+ "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
6334
+ fallthrough: ["basic", "emacsy"]
6335
+ }
6336
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault
6337
+
6338
+ // KEYMAP DISPATCH
6339
+
6340
+ function normalizeKeyName(name) {
6341
+ var parts = name.split(/-(?!$)/)
6342
+ name = parts[parts.length - 1]
6343
+ var alt, ctrl, shift, cmd
6344
+ for (var i = 0; i < parts.length - 1; i++) {
6345
+ var mod = parts[i]
6346
+ if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true }
6347
+ else if (/^a(lt)?$/i.test(mod)) { alt = true }
6348
+ else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true }
6349
+ else if (/^s(hift)?$/i.test(mod)) { shift = true }
6350
+ else { throw new Error("Unrecognized modifier name: " + mod) }
6351
+ }
6352
+ if (alt) { name = "Alt-" + name }
6353
+ if (ctrl) { name = "Ctrl-" + name }
6354
+ if (cmd) { name = "Cmd-" + name }
6355
+ if (shift) { name = "Shift-" + name }
6356
+ return name
6357
+ }
6358
+
6359
+ // This is a kludge to keep keymaps mostly working as raw objects
6360
+ // (backwards compatibility) while at the same time support features
6361
+ // like normalization and multi-stroke key bindings. It compiles a
6362
+ // new normalized keymap, and then updates the old object to reflect
6363
+ // this.
6364
+ function normalizeKeyMap(keymap) {
6365
+ var copy = {}
6366
+ for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {
6367
+ var value = keymap[keyname]
6368
+ if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }
6369
+ if (value == "...") { delete keymap[keyname]; continue }
6370
+
6371
+ var keys = map(keyname.split(" "), normalizeKeyName)
6372
+ for (var i = 0; i < keys.length; i++) {
6373
+ var val = (void 0), name = (void 0)
6374
+ if (i == keys.length - 1) {
6375
+ name = keys.join(" ")
6376
+ val = value
6377
+ } else {
6378
+ name = keys.slice(0, i + 1).join(" ")
6379
+ val = "..."
6380
+ }
6381
+ var prev = copy[name]
6382
+ if (!prev) { copy[name] = val }
6383
+ else if (prev != val) { throw new Error("Inconsistent bindings for " + name) }
6384
+ }
6385
+ delete keymap[keyname]
6386
+ } }
6387
+ for (var prop in copy) { keymap[prop] = copy[prop] }
6388
+ return keymap
6389
+ }
6390
+
6391
+ function lookupKey(key, map, handle, context) {
6392
+ map = getKeyMap(map)
6393
+ var found = map.call ? map.call(key, context) : map[key]
6394
+ if (found === false) { return "nothing" }
6395
+ if (found === "...") { return "multi" }
6396
+ if (found != null && handle(found)) { return "handled" }
6397
+
6398
+ if (map.fallthrough) {
6399
+ if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
6400
+ { return lookupKey(key, map.fallthrough, handle, context) }
6401
+ for (var i = 0; i < map.fallthrough.length; i++) {
6402
+ var result = lookupKey(key, map.fallthrough[i], handle, context)
6403
+ if (result) { return result }
6404
+ }
6405
+ }
6406
+ }
6407
+
6408
+ // Modifier key presses don't count as 'real' key presses for the
6409
+ // purpose of keymap fallthrough.
6410
+ function isModifierKey(value) {
6411
+ var name = typeof value == "string" ? value : keyNames[value.keyCode]
6412
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"
6413
+ }
6414
+
6415
+ // Look up the name of a key as indicated by an event object.
6416
+ function keyName(event, noShift) {
6417
+ if (presto && event.keyCode == 34 && event["char"]) { return false }
6418
+ var base = keyNames[event.keyCode], name = base
6419
+ if (name == null || event.altGraphKey) { return false }
6420
+ if (event.altKey && base != "Alt") { name = "Alt-" + name }
6421
+ if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name }
6422
+ if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name }
6423
+ if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name }
6424
+ return name
6425
+ }
6426
+
6427
+ function getKeyMap(val) {
6428
+ return typeof val == "string" ? keyMap[val] : val
6429
+ }
6430
+
6431
+ // Helper for deleting text near the selection(s), used to implement
6432
+ // backspace, delete, and similar functionality.
6433
+ function deleteNearSelection(cm, compute) {
6434
+ var ranges = cm.doc.sel.ranges, kill = []
6435
+ // Build up a set of ranges to kill first, merging overlapping
6436
+ // ranges.
6437
+ for (var i = 0; i < ranges.length; i++) {
6438
+ var toKill = compute(ranges[i])
6439
+ while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
6440
+ var replaced = kill.pop()
6441
+ if (cmp(replaced.from, toKill.from) < 0) {
6442
+ toKill.from = replaced.from
6443
+ break
6444
+ }
6445
+ }
6446
+ kill.push(toKill)
6447
+ }
6448
+ // Next, remove those actual ranges.
6449
+ runInOp(cm, function () {
6450
+ for (var i = kill.length - 1; i >= 0; i--)
6451
+ { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") }
6452
+ ensureCursorVisible(cm)
6453
+ })
6454
+ }
6455
+
6456
+ // Commands are parameter-less actions that can be performed on an
6457
+ // editor, mostly used for keybindings.
6458
+ var commands = {
6459
+ selectAll: selectAll,
6460
+ singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); },
6461
+ killLine: function (cm) { return deleteNearSelection(cm, function (range) {
6462
+ if (range.empty()) {
6463
+ var len = getLine(cm.doc, range.head.line).text.length
6464
+ if (range.head.ch == len && range.head.line < cm.lastLine())
6465
+ { return {from: range.head, to: Pos(range.head.line + 1, 0)} }
6466
+ else
6467
+ { return {from: range.head, to: Pos(range.head.line, len)} }
6468
+ } else {
6469
+ return {from: range.from(), to: range.to()}
6470
+ }
6471
+ }); },
6472
+ deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({
6473
+ from: Pos(range.from().line, 0),
6474
+ to: clipPos(cm.doc, Pos(range.to().line + 1, 0))
6475
+ }); }); },
6476
+ delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({
6477
+ from: Pos(range.from().line, 0), to: range.from()
6478
+ }); }); },
6479
+ delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {
6480
+ var top = cm.charCoords(range.head, "div").top + 5
6481
+ var leftPos = cm.coordsChar({left: 0, top: top}, "div")
6482
+ return {from: leftPos, to: range.from()}
6483
+ }); },
6484
+ delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {
6485
+ var top = cm.charCoords(range.head, "div").top + 5
6486
+ var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
6487
+ return {from: range.from(), to: rightPos }
6488
+ }); },
6489
+ undo: function (cm) { return cm.undo(); },
6490
+ redo: function (cm) { return cm.redo(); },
6491
+ undoSelection: function (cm) { return cm.undoSelection(); },
6492
+ redoSelection: function (cm) { return cm.redoSelection(); },
6493
+ goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },
6494
+ goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },
6495
+ goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },
6496
+ {origin: "+move", bias: 1}
6497
+ ); },
6498
+ goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },
6499
+ {origin: "+move", bias: 1}
6500
+ ); },
6501
+ goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },
6502
+ {origin: "+move", bias: -1}
6503
+ ); },
6504
+ goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {
6505
+ var top = cm.charCoords(range.head, "div").top + 5
6506
+ return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
6507
+ }, sel_move); },
6508
+ goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {
6509
+ var top = cm.charCoords(range.head, "div").top + 5
6510
+ return cm.coordsChar({left: 0, top: top}, "div")
6511
+ }, sel_move); },
6512
+ goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {
6513
+ var top = cm.charCoords(range.head, "div").top + 5
6514
+ var pos = cm.coordsChar({left: 0, top: top}, "div")
6515
+ if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) }
6516
+ return pos
6517
+ }, sel_move); },
6518
+ goLineUp: function (cm) { return cm.moveV(-1, "line"); },
6519
+ goLineDown: function (cm) { return cm.moveV(1, "line"); },
6520
+ goPageUp: function (cm) { return cm.moveV(-1, "page"); },
6521
+ goPageDown: function (cm) { return cm.moveV(1, "page"); },
6522
+ goCharLeft: function (cm) { return cm.moveH(-1, "char"); },
6523
+ goCharRight: function (cm) { return cm.moveH(1, "char"); },
6524
+ goColumnLeft: function (cm) { return cm.moveH(-1, "column"); },
6525
+ goColumnRight: function (cm) { return cm.moveH(1, "column"); },
6526
+ goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
6527
+ goGroupRight: function (cm) { return cm.moveH(1, "group"); },
6528
+ goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
6529
+ goWordRight: function (cm) { return cm.moveH(1, "word"); },
6530
+ delCharBefore: function (cm) { return cm.deleteH(-1, "char"); },
6531
+ delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
6532
+ delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
6533
+ delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
6534
+ delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
6535
+ delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
6536
+ indentAuto: function (cm) { return cm.indentSelection("smart"); },
6537
+ indentMore: function (cm) { return cm.indentSelection("add"); },
6538
+ indentLess: function (cm) { return cm.indentSelection("subtract"); },
6539
+ insertTab: function (cm) { return cm.replaceSelection("\t"); },
6540
+ insertSoftTab: function (cm) {
6541
+ var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize
6542
+ for (var i = 0; i < ranges.length; i++) {
6543
+ var pos = ranges[i].from()
6544
+ var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize)
6545
+ spaces.push(spaceStr(tabSize - col % tabSize))
6546
+ }
6547
+ cm.replaceSelections(spaces)
6548
+ },
6549
+ defaultTab: function (cm) {
6550
+ if (cm.somethingSelected()) { cm.indentSelection("add") }
6551
+ else { cm.execCommand("insertTab") }
6552
+ },
6553
+ // Swap the two chars left and right of each selection's head.
6554
+ // Move cursor behind the two swapped characters afterwards.
6555
+ //
6556
+ // Doesn't consider line feeds a character.
6557
+ // Doesn't scan more than one line above to find a character.
6558
+ // Doesn't do anything on an empty line.
6559
+ // Doesn't do anything with non-empty selections.
6560
+ transposeChars: function (cm) { return runInOp(cm, function () {
6561
+ var ranges = cm.listSelections(), newSel = []
6562
+ for (var i = 0; i < ranges.length; i++) {
6563
+ if (!ranges[i].empty()) { continue }
6564
+ var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text
6565
+ if (line) {
6566
+ if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1) }
6567
+ if (cur.ch > 0) {
6568
+ cur = new Pos(cur.line, cur.ch + 1)
6569
+ cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
6570
+ Pos(cur.line, cur.ch - 2), cur, "+transpose")
6571
+ } else if (cur.line > cm.doc.first) {
6572
+ var prev = getLine(cm.doc, cur.line - 1).text
6573
+ if (prev) {
6574
+ cur = new Pos(cur.line, 1)
6575
+ cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
6576
+ prev.charAt(prev.length - 1),
6577
+ Pos(cur.line - 1, prev.length - 1), cur, "+transpose")
6578
  }
6579
  }
 
6580
  }
6581
+ newSel.push(new Range(cur, cur))
6582
+ }
6583
+ cm.setSelections(newSel)
6584
+ }); },
6585
+ newlineAndIndent: function (cm) { return runInOp(cm, function () {
6586
+ var sels = cm.listSelections()
6587
+ for (var i = sels.length - 1; i >= 0; i--)
6588
+ { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input") }
6589
+ sels = cm.listSelections()
6590
+ for (var i$1 = 0; i$1 < sels.length; i$1++)
6591
+ { cm.indentLine(sels[i$1].from().line, null, true) }
6592
+ ensureCursorVisible(cm)
6593
+ }); },
6594
+ openLine: function (cm) { return cm.replaceSelection("\n", "start"); },
6595
+ toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }
6596
+ }
6597
+
6598
+
6599
+ function lineStart(cm, lineN) {
6600
+ var line = getLine(cm.doc, lineN)
6601
+ var visual = visualLine(line)
6602
+ if (visual != line) { lineN = lineNo(visual) }
6603
+ var order = getOrder(visual)
6604
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual)
6605
+ return Pos(lineN, ch)
6606
+ }
6607
+ function lineEnd(cm, lineN) {
6608
+ var merged, line = getLine(cm.doc, lineN)
6609
+ while (merged = collapsedSpanAtEnd(line)) {
6610
+ line = merged.find(1, true).line
6611
+ lineN = null
6612
+ }
6613
+ var order = getOrder(line)
6614
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line)
6615
+ return Pos(lineN == null ? lineNo(line) : lineN, ch)
6616
+ }
6617
+ function lineStartSmart(cm, pos) {
6618
+ var start = lineStart(cm, pos.line)
6619
+ var line = getLine(cm.doc, start.line)
6620
+ var order = getOrder(line)
6621
+ if (!order || order[0].level == 0) {
6622
+ var firstNonWS = Math.max(0, line.text.search(/\S/))
6623
+ var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch
6624
+ return Pos(start.line, inWS ? 0 : firstNonWS)
6625
+ }
6626
+ return start
6627
+ }
6628
+
6629
+ // Run a handler that was bound to a key.
6630
+ function doHandleBinding(cm, bound, dropShift) {
6631
+ if (typeof bound == "string") {
6632
+ bound = commands[bound]
6633
+ if (!bound) { return false }
6634
+ }
6635
+ // Ensure previous input has been read, so that the handler sees a
6636
+ // consistent view of the document
6637
+ cm.display.input.ensurePolled()
6638
+ var prevShift = cm.display.shift, done = false
6639
+ try {
6640
+ if (cm.isReadOnly()) { cm.state.suppressEdits = true }
6641
+ if (dropShift) { cm.display.shift = false }
6642
+ done = bound(cm) != Pass
6643
+ } finally {
6644
+ cm.display.shift = prevShift
6645
+ cm.state.suppressEdits = false
6646
+ }
6647
+ return done
6648
+ }
6649
+
6650
+ function lookupKeyForEditor(cm, name, handle) {
6651
+ for (var i = 0; i < cm.state.keyMaps.length; i++) {
6652
+ var result = lookupKey(name, cm.state.keyMaps[i], handle, cm)
6653
+ if (result) { return result }
6654
+ }
6655
+ return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
6656
+ || lookupKey(name, cm.options.keyMap, handle, cm)
6657
+ }
6658
+
6659
+ var stopSeq = new Delayed
6660
+ function dispatchKey(cm, name, e, handle) {
6661
+ var seq = cm.state.keySeq
6662
+ if (seq) {
6663
+ if (isModifierKey(name)) { return "handled" }
6664
+ stopSeq.set(50, function () {
6665
+ if (cm.state.keySeq == seq) {
6666
+ cm.state.keySeq = null
6667
+ cm.display.input.reset()
6668
+ }
6669
+ })
6670
+ name = seq + " " + name
6671
+ }
6672
+ var result = lookupKeyForEditor(cm, name, handle)
6673
+
6674
+ if (result == "multi")
6675
+ { cm.state.keySeq = name }
6676
+ if (result == "handled")
6677
+ { signalLater(cm, "keyHandled", cm, name, e) }
6678
+
6679
+ if (result == "handled" || result == "multi") {
6680
+ e_preventDefault(e)
6681
+ restartBlink(cm)
6682
+ }
6683
+
6684
+ if (seq && !result && /\'$/.test(name)) {
6685
+ e_preventDefault(e)
6686
+ return true
6687
+ }
6688
+ return !!result
6689
+ }
6690
+
6691
+ // Handle a key from the keydown event.
6692
+ function handleKeyBinding(cm, e) {
6693
+ var name = keyName(e, true)
6694
+ if (!name) { return false }
6695
+
6696
+ if (e.shiftKey && !cm.state.keySeq) {
6697
+ // First try to resolve full name (including 'Shift-'). Failing
6698
+ // that, see if there is a cursor-motion command (starting with
6699
+ // 'go') bound to the keyname without 'Shift-'.
6700
+ return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); })
6701
+ || dispatchKey(cm, name, e, function (b) {
6702
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
6703
+ { return doHandleBinding(cm, b) }
6704
+ })
6705
+ } else {
6706
+ return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })
6707
+ }
6708
+ }
6709
+
6710
+ // Handle a key from the keypress event
6711
+ function handleCharBinding(cm, e, ch) {
6712
+ return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); })
6713
+ }
6714
+
6715
+ var lastStoppedKey = null
6716
+ function onKeyDown(e) {
6717
+ var cm = this
6718
+ cm.curOp.focus = activeElt()
6719
+ if (signalDOMEvent(cm, e)) { return }
6720
+ // IE does strange things with escape.
6721
+ if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false }
6722
+ var code = e.keyCode
6723
+ cm.display.shift = code == 16 || e.shiftKey
6724
+ var handled = handleKeyBinding(cm, e)
6725
+ if (presto) {
6726
+ lastStoppedKey = handled ? code : null
6727
+ // Opera has no cut event... we try to at least catch the key combo
6728
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
6729
+ { cm.replaceSelection("", null, "cut") }
6730
+ }
6731
+
6732
+ // Turn mouse into crosshair when Alt is held on Mac.
6733
+ if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
6734
+ { showCrossHair(cm) }
6735
+ }
6736
+
6737
+ function showCrossHair(cm) {
6738
+ var lineDiv = cm.display.lineDiv
6739
+ addClass(lineDiv, "CodeMirror-crosshair")
6740
+
6741
+ function up(e) {
6742
+ if (e.keyCode == 18 || !e.altKey) {
6743
+ rmClass(lineDiv, "CodeMirror-crosshair")
6744
+ off(document, "keyup", up)
6745
+ off(document, "mouseover", up)
6746
+ }
6747
+ }
6748
+ on(document, "keyup", up)
6749
+ on(document, "mouseover", up)
6750
+ }
6751
+
6752
+ function onKeyUp(e) {
6753
+ if (e.keyCode == 16) { this.doc.sel.shift = false }
6754
+ signalDOMEvent(this, e)
6755
+ }
6756
+
6757
+ function onKeyPress(e) {
6758
+ var cm = this
6759
+ if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
6760
+ var keyCode = e.keyCode, charCode = e.charCode
6761
+ if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
6762
+ if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }
6763
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode)
6764
+ // Some browsers fire keypress events for backspace
6765
+ if (ch == "\x08") { return }
6766
+ if (handleCharBinding(cm, e, ch)) { return }
6767
+ cm.display.input.onKeyPress(e)
6768
+ }
6769
+
6770
+ // A mouse down can be a single click, double click, triple click,
6771
+ // start of selection drag, start of text drag, new cursor
6772
+ // (ctrl-click), rectangle drag (alt-drag), or xwin
6773
+ // middle-click-paste. Or it might be a click on something we should
6774
+ // not interfere with, such as a scrollbar or widget.
6775
+ function onMouseDown(e) {
6776
+ var cm = this, display = cm.display
6777
+ if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }
6778
+ display.input.ensurePolled()
6779
+ display.shift = e.shiftKey
6780
+
6781
+ if (eventInWidget(display, e)) {
6782
+ if (!webkit) {
6783
+ // Briefly turn off draggability, to allow widgets to do
6784
+ // normal dragging things.
6785
+ display.scroller.draggable = false
6786
+ setTimeout(function () { return display.scroller.draggable = true; }, 100)
6787
+ }
6788
+ return
6789
+ }
6790
+ if (clickInGutter(cm, e)) { return }
6791
+ var start = posFromMouse(cm, e)
6792
+ window.focus()
6793
+
6794
+ switch (e_button(e)) {
6795
+ case 1:
6796
+ // #3261: make sure, that we're not starting a second selection
6797
+ if (cm.state.selectingText)
6798
+ { cm.state.selectingText(e) }
6799
+ else if (start)
6800
+ { leftButtonDown(cm, e, start) }
6801
+ else if (e_target(e) == display.scroller)
6802
+ { e_preventDefault(e) }
6803
+ break
6804
+ case 2:
6805
+ if (webkit) { cm.state.lastMiddleDown = +new Date }
6806
+ if (start) { extendSelection(cm.doc, start) }
6807
+ setTimeout(function () { return display.input.focus(); }, 20)
6808
+ e_preventDefault(e)
6809
+ break
6810
+ case 3:
6811
+ if (captureRightClick) { onContextMenu(cm, e) }
6812
+ else { delayBlurEvent(cm) }
6813
+ break
6814
+ }
6815
+ }
6816
+
6817
+ var lastClick;
6818
+ var lastDoubleClick;
6819
+ function leftButtonDown(cm, e, start) {
6820
+ if (ie) { setTimeout(bind(ensureFocus, cm), 0) }
6821
+ else { cm.curOp.focus = activeElt() }
6822
+
6823
+ var now = +new Date, type
6824
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
6825
+ type = "triple"
6826
+ } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
6827
+ type = "double"
6828
+ lastDoubleClick = {time: now, pos: start}
6829
+ } else {
6830
+ type = "single"
6831
+ lastClick = {time: now, pos: start}
6832
+ }
6833
+
6834
+ var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained
6835
+ if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
6836
+ type == "single" && (contained = sel.contains(start)) > -1 &&
6837
+ (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
6838
+ (cmp(contained.to(), start) > 0 || start.xRel < 0))
6839
+ { leftButtonStartDrag(cm, e, start, modifier) }
6840
+ else
6841
+ { leftButtonSelect(cm, e, start, type, modifier) }
6842
+ }
6843
+
6844
+ // Start a text drag. When it ends, see if any dragging actually
6845
+ // happen, and treat as a click if it didn't.
6846
+ function leftButtonStartDrag(cm, e, start, modifier) {
6847
+ var display = cm.display, startTime = +new Date
6848
+ var dragEnd = operation(cm, function (e2) {
6849
+ if (webkit) { display.scroller.draggable = false }
6850
+ cm.state.draggingText = false
6851
+ off(document, "mouseup", dragEnd)
6852
+ off(display.scroller, "drop", dragEnd)
6853
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
6854
+ e_preventDefault(e2)
6855
+ if (!modifier && +new Date - 200 < startTime)
6856
+ { extendSelection(cm.doc, start) }
6857
+ // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
6858
+ if (webkit || ie && ie_version == 9)
6859
+ { setTimeout(function () {document.body.focus(); display.input.focus()}, 20) }
6860
+ else
6861
+ { display.input.focus() }
6862
+ }
6863
+ })
6864
+ // Let the drag handler handle this.
6865
+ if (webkit) { display.scroller.draggable = true }
6866
+ cm.state.draggingText = dragEnd
6867
+ dragEnd.copy = mac ? e.altKey : e.ctrlKey
6868
+ // IE's approach to draggable
6869
+ if (display.scroller.dragDrop) { display.scroller.dragDrop() }
6870
+ on(document, "mouseup", dragEnd)
6871
+ on(display.scroller, "drop", dragEnd)
6872
+ }
6873
+
6874
+ // Normal selection, as opposed to text dragging.
6875
+ function leftButtonSelect(cm, e, start, type, addNew) {
6876
+ var display = cm.display, doc = cm.doc
6877
+ e_preventDefault(e)
6878
+
6879
+ var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges
6880
+ if (addNew && !e.shiftKey) {
6881
+ ourIndex = doc.sel.contains(start)
6882
+ if (ourIndex > -1)
6883
+ { ourRange = ranges[ourIndex] }
6884
+ else
6885
+ { ourRange = new Range(start, start) }
6886
+ } else {
6887
+ ourRange = doc.sel.primary()
6888
+ ourIndex = doc.sel.primIndex
6889
+ }
6890
+
6891
+ if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) {
6892
+ type = "rect"
6893
+ if (!addNew) { ourRange = new Range(start, start) }
6894
+ start = posFromMouse(cm, e, true, true)
6895
+ ourIndex = -1
6896
+ } else if (type == "double") {
6897
+ var word = cm.findWordAt(start)
6898
+ if (cm.display.shift || doc.extend)
6899
+ { ourRange = extendRange(doc, ourRange, word.anchor, word.head) }
6900
+ else
6901
+ { ourRange = word }
6902
+ } else if (type == "triple") {
6903
+ var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)))
6904
+ if (cm.display.shift || doc.extend)
6905
+ { ourRange = extendRange(doc, ourRange, line.anchor, line.head) }
6906
+ else
6907
+ { ourRange = line }
6908
+ } else {
6909
+ ourRange = extendRange(doc, ourRange, start)
6910
+ }
6911
+
6912
+ if (!addNew) {
6913
+ ourIndex = 0
6914
+ setSelection(doc, new Selection([ourRange], 0), sel_mouse)
6915
+ startSel = doc.sel
6916
+ } else if (ourIndex == -1) {
6917
+ ourIndex = ranges.length
6918
+ setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
6919
+ {scroll: false, origin: "*mouse"})
6920
+ } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
6921
+ setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
6922
+ {scroll: false, origin: "*mouse"})
6923
+ startSel = doc.sel
6924
+ } else {
6925
+ replaceOneSelection(doc, ourIndex, ourRange, sel_mouse)
6926
+ }
6927
+
6928
+ var lastPos = start
6929
+ function extendTo(pos) {
6930
+ if (cmp(lastPos, pos) == 0) { return }
6931
+ lastPos = pos
6932
+
6933
+ if (type == "rect") {
6934
+ var ranges = [], tabSize = cm.options.tabSize
6935
+ var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize)
6936
+ var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize)
6937
+ var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol)
6938
+ for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
6939
+ line <= end; line++) {
6940
+ var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize)
6941
+ if (left == right)
6942
+ { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))) }
6943
+ else if (text.length > leftPos)
6944
+ { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))) }
6945
+ }
6946
+ if (!ranges.length) { ranges.push(new Range(start, start)) }
6947
+ setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
6948
+ {origin: "*mouse", scroll: false})
6949
+ cm.scrollIntoView(pos)
6950
+ } else {
6951
+ var oldRange = ourRange
6952
+ var anchor = oldRange.anchor, head = pos
6953
+ if (type != "single") {
6954
+ var range
6955
+ if (type == "double")
6956
+ { range = cm.findWordAt(pos) }
6957
+ else
6958
+ { range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))) }
6959
+ if (cmp(range.anchor, anchor) > 0) {
6960
+ head = range.head
6961
+ anchor = minPos(oldRange.from(), range.anchor)
6962
+ } else {
6963
+ head = range.anchor
6964
+ anchor = maxPos(oldRange.to(), range.head)
6965
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6966
  }
6967
+ var ranges$1 = startSel.ranges.slice(0)
6968
+ ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head)
6969
+ setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse)
6970
+ }
6971
+ }
6972
+
6973
+ var editorSize = display.wrapper.getBoundingClientRect()
6974
+ // Used to ensure timeout re-tries don't fire when another extend
6975
+ // happened in the meantime (clearTimeout isn't reliable -- at
6976
+ // least on Chrome, the timeouts still happen even when cleared,
6977
+ // if the clear happens after their scheduled firing time).
6978
+ var counter = 0
6979
+
6980
+ function extend(e) {
6981
+ var curCount = ++counter
6982
+ var cur = posFromMouse(cm, e, true, type == "rect")
6983
+ if (!cur) { return }
6984
+ if (cmp(cur, lastPos) != 0) {
6985
+ cm.curOp.focus = activeElt()
6986
+ extendTo(cur)
6987
+ var visible = visibleLines(display, doc)
6988
+ if (cur.line >= visible.to || cur.line < visible.from)
6989
+ { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e) }}), 150) }
6990
+ } else {
6991
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0
6992
+ if (outside) { setTimeout(operation(cm, function () {
6993
+ if (counter != curCount) { return }
6994
+ display.scroller.scrollTop += outside
6995
+ extend(e)
6996
+ }), 50) }
6997
+ }
6998
+ }
6999
+
7000
+ function done(e) {
7001
+ cm.state.selectingText = false
7002
+ counter = Infinity
7003
+ e_preventDefault(e)
7004
+ display.input.focus()
7005
+ off(document, "mousemove", move)
7006
+ off(document, "mouseup", up)
7007
+ doc.history.lastSelOrigin = null
7008
+ }
7009
+
7010
+ var move = operation(cm, function (e) {
7011
+ if (!e_button(e)) { done(e) }
7012
+ else { extend(e) }
7013
+ })
7014
+ var up = operation(cm, done)
7015
+ cm.state.selectingText = up
7016
+ on(document, "mousemove", move)
7017
+ on(document, "mouseup", up)
7018
+ }
7019
+
7020
+
7021
+ // Determines whether an event happened in the gutter, and fires the
7022
+ // handlers for the corresponding event.
7023
+ function gutterEvent(cm, e, type, prevent) {
7024
+ var mX, mY
7025
+ try { mX = e.clientX; mY = e.clientY }
7026
+ catch(e) { return false }
7027
+ if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
7028
+ if (prevent) { e_preventDefault(e) }
7029
+
7030
+ var display = cm.display
7031
+ var lineBox = display.lineDiv.getBoundingClientRect()
7032
+
7033
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }
7034
+ mY -= lineBox.top - display.viewOffset
7035
+
7036
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
7037
+ var g = display.gutters.childNodes[i]
7038
+ if (g && g.getBoundingClientRect().right >= mX) {
7039
+ var line = lineAtHeight(cm.doc, mY)
7040
+ var gutter = cm.options.gutters[i]
7041
+ signal(cm, type, cm, line, gutter, e)
7042
+ return e_defaultPrevented(e)
7043
+ }
7044
+ }
7045
+ }
7046
+
7047
+ function clickInGutter(cm, e) {
7048
+ return gutterEvent(cm, e, "gutterClick", true)
7049
+ }
7050
+
7051
+ // CONTEXT MENU HANDLING
7052
+
7053
+ // To make the context menu work, we need to briefly unhide the
7054
+ // textarea (making it as unobtrusive as possible) to let the
7055
+ // right-click take effect on it.
7056
+ function onContextMenu(cm, e) {
7057
+ if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }
7058
+ if (signalDOMEvent(cm, e, "contextmenu")) { return }
7059
+ cm.display.input.onContextMenu(e)
7060
+ }
7061
+
7062
+ function contextMenuInGutter(cm, e) {
7063
+ if (!hasHandler(cm, "gutterContextMenu")) { return false }
7064
+ return gutterEvent(cm, e, "gutterContextMenu", false)
7065
+ }
7066
+
7067
+ function themeChanged(cm) {
7068
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
7069
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-")
7070
+ clearCaches(cm)
7071
+ }
7072
+
7073
+ var Init = {toString: function(){return "CodeMirror.Init"}}
7074
+
7075
+ var defaults = {}
7076
+ var optionHandlers = {}
7077
+
7078
+ function defineOptions(CodeMirror) {
7079
+ var optionHandlers = CodeMirror.optionHandlers
7080
 
7081
+ function option(name, deflt, handle, notOnInit) {
7082
+ CodeMirror.defaults[name] = deflt
7083
+ if (handle) { optionHandlers[name] =
7084
+ notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old) }} : handle }
7085
+ }
7086
 
7087
+ CodeMirror.defineOption = option
 
 
 
 
 
 
 
 
7088
 
7089
+ // Passed to option handlers when there is no old value.
7090
+ CodeMirror.Init = Init
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7091
 
7092
+ // These two are, on init, called from the constructor because they
7093
+ // have to be initialized before the editor can start at all.
7094
+ option("value", "", function (cm, val) { return cm.setValue(val); }, true)
7095
+ option("mode", null, function (cm, val) {
7096
+ cm.doc.modeOption = val
7097
+ loadMode(cm)
7098
+ }, true)
7099
+
7100
+ option("indentUnit", 2, loadMode, true)
7101
+ option("indentWithTabs", false)
7102
+ option("smartIndent", true)
7103
+ option("tabSize", 4, function (cm) {
7104
+ resetModeState(cm)
7105
+ clearCaches(cm)
7106
+ regChange(cm)
7107
+ }, true)
7108
+ option("lineSeparator", null, function (cm, val) {
7109
+ cm.doc.lineSep = val
7110
+ if (!val) { return }
7111
+ var newBreaks = [], lineNo = cm.doc.first
7112
+ cm.doc.iter(function (line) {
7113
+ for (var pos = 0;;) {
7114
+ var found = line.text.indexOf(val, pos)
7115
+ if (found == -1) { break }
7116
+ pos = found + val.length
7117
+ newBreaks.push(Pos(lineNo, found))
7118
+ }
7119
+ lineNo++
7120
+ })
7121
+ for (var i = newBreaks.length - 1; i >= 0; i--)
7122
+ { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) }
7123
+ })
7124
+ option("specialChars", /[\u0000-\u001f\u007f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) {
7125
+ cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g")
7126
+ if (old != Init) { cm.refresh() }
7127
+ })
7128
+ option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true)
7129
+ option("electricChars", true)
7130
+ option("inputStyle", mobile ? "contenteditable" : "textarea", function () {
7131
+ throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
7132
+ }, true)
7133
+ option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true)
7134
+ option("rtlMoveVisually", !windows)
7135
+ option("wholeLineUpdateBefore", true)
7136
+
7137
+ option("theme", "default", function (cm) {
7138
+ themeChanged(cm)
7139
+ guttersChanged(cm)
7140
+ }, true)
7141
+ option("keyMap", "default", function (cm, val, old) {
7142
+ var next = getKeyMap(val)
7143
+ var prev = old != Init && getKeyMap(old)
7144
+ if (prev && prev.detach) { prev.detach(cm, next) }
7145
+ if (next.attach) { next.attach(cm, prev || null) }
7146
+ })
7147
+ option("extraKeys", null)
7148
+
7149
+ option("lineWrapping", false, wrappingChanged, true)
7150
+ option("gutters", [], function (cm) {
7151
+ setGuttersForLineNumbers(cm.options)
7152
+ guttersChanged(cm)
7153
+ }, true)
7154
+ option("fixedGutter", true, function (cm, val) {
7155
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"
7156
+ cm.refresh()
7157
+ }, true)
7158
+ option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true)
7159
+ option("scrollbarStyle", "native", function (cm) {
7160
+ initScrollbars(cm)
7161
+ updateScrollbars(cm)
7162
+ cm.display.scrollbars.setScrollTop(cm.doc.scrollTop)
7163
+ cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft)
7164
+ }, true)
7165
+ option("lineNumbers", false, function (cm) {
7166
+ setGuttersForLineNumbers(cm.options)
7167
+ guttersChanged(cm)
7168
+ }, true)
7169
+ option("firstLineNumber", 1, guttersChanged, true)
7170
+ option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true)
7171
+ option("showCursorWhenSelecting", false, updateSelection, true)
7172
+
7173
+ option("resetSelectionOnContextMenu", true)
7174
+ option("lineWiseCopyCut", true)
7175
+
7176
+ option("readOnly", false, function (cm, val) {
7177
+ if (val == "nocursor") {
7178
+ onBlur(cm)
7179
+ cm.display.input.blur()
7180
+ cm.display.disabled = true
7181
+ } else {
7182
+ cm.display.disabled = false
7183
+ }
7184
+ cm.display.input.readOnlyChanged(val)
7185
+ })
7186
+ option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset() }}, true)
7187
+ option("dragDrop", true, dragDropChanged)
7188
+ option("allowDropFileTypes", null)
7189
+
7190
+ option("cursorBlinkRate", 530)
7191
+ option("cursorScrollMargin", 0)
7192
+ option("cursorHeight", 1, updateSelection, true)
7193
+ option("singleCursorHeightPerLine", true, updateSelection, true)
7194
+ option("workTime", 100)
7195
+ option("workDelay", 100)
7196
+ option("flattenSpans", true, resetModeState, true)
7197
+ option("addModeClass", false, resetModeState, true)
7198
+ option("pollInterval", 100)
7199
+ option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; })
7200
+ option("historyEventDelay", 1250)
7201
+ option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true)
7202
+ option("maxHighlightLength", 10000, resetModeState, true)
7203
+ option("moveInputWithCursor", true, function (cm, val) {
7204
+ if (!val) { cm.display.input.resetPosition() }
7205
+ })
7206
+
7207
+ option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; })
7208
+ option("autofocus", null)
7209
+ }
7210
+
7211
+ function guttersChanged(cm) {
7212
+ updateGutters(cm)
7213
+ regChange(cm)
7214
+ alignHorizontally(cm)
7215
+ }
7216
+
7217
+ function dragDropChanged(cm, value, old) {
7218
+ var wasOn = old && old != Init
7219
+ if (!value != !wasOn) {
7220
+ var funcs = cm.display.dragFunctions
7221
+ var toggle = value ? on : off
7222
+ toggle(cm.display.scroller, "dragstart", funcs.start)
7223
+ toggle(cm.display.scroller, "dragenter", funcs.enter)
7224
+ toggle(cm.display.scroller, "dragover", funcs.over)
7225
+ toggle(cm.display.scroller, "dragleave", funcs.leave)
7226
+ toggle(cm.display.scroller, "drop", funcs.drop)
7227
+ }
7228
+ }
7229
+
7230
+ function wrappingChanged(cm) {
7231
+ if (cm.options.lineWrapping) {
7232
+ addClass(cm.display.wrapper, "CodeMirror-wrap")
7233
+ cm.display.sizer.style.minWidth = ""
7234
+ cm.display.sizerWidth = null
7235
+ } else {
7236
+ rmClass(cm.display.wrapper, "CodeMirror-wrap")
7237
+ findMaxLine(cm)
7238
+ }
7239
+ estimateLineHeights(cm)
7240
+ regChange(cm)
7241
+ clearCaches(cm)
7242
+ setTimeout(function () { return updateScrollbars(cm); }, 100)
7243
+ }
7244
+
7245
+ // A CodeMirror instance represents an editor. This is the object
7246
+ // that user code is usually dealing with.
7247
+
7248
+ function CodeMirror(place, options) {
7249
+ var this$1 = this;
7250
+
7251
+ if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) }
7252
+
7253
+ this.options = options = options ? copyObj(options) : {}
7254
+ // Determine effective options based on given values and defaults.
7255
+ copyObj(defaults, options, false)
7256
+ setGuttersForLineNumbers(options)
7257
+
7258
+ var doc = options.value
7259
+ if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator) }
7260
+ this.doc = doc
7261
+
7262
+ var input = new CodeMirror.inputStyles[options.inputStyle](this)
7263
+ var display = this.display = new Display(place, doc, input)
7264
+ display.wrapper.CodeMirror = this
7265
+ updateGutters(this)
7266
+ themeChanged(this)
7267
+ if (options.lineWrapping)
7268
+ { this.display.wrapper.className += " CodeMirror-wrap" }
7269
+ initScrollbars(this)
7270
+
7271
+ this.state = {
7272
+ keyMaps: [], // stores maps added by addKeyMap
7273
+ overlays: [], // highlighting overlays, as added by addOverlay
7274
+ modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
7275
+ overwrite: false,
7276
+ delayingBlurEvent: false,
7277
+ focused: false,
7278
+ suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
7279
+ pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
7280
+ selectingText: false,
7281
+ draggingText: false,
7282
+ highlight: new Delayed(), // stores highlight worker timeout
7283
+ keySeq: null, // Unfinished key sequence
7284
+ specialChars: null
7285
+ }
7286
+
7287
+ if (options.autofocus && !mobile) { display.input.focus() }
7288
+
7289
+ // Override magic textarea content restore that IE sometimes does
7290
+ // on our hidden textarea on reload
7291
+ if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20) }
7292
+
7293
+ registerEventHandlers(this)
7294
+ ensureGlobalHandlers()
7295
+
7296
+ startOperation(this)
7297
+ this.curOp.forceUpdate = true
7298
+ attachDoc(this, doc)
7299
+
7300
+ if ((options.autofocus && !mobile) || this.hasFocus())
7301
+ { setTimeout(bind(onFocus, this), 20) }
7302
+ else
7303
+ { onBlur(this) }
7304
+
7305
+ for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
7306
+ { optionHandlers[opt](this$1, options[opt], Init) } }
7307
+ maybeUpdateLineNumberWidth(this)
7308
+ if (options.finishInit) { options.finishInit(this) }
7309
+ for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1) }
7310
+ endOperation(this)
7311
+ // Suppress optimizelegibility in Webkit, since it breaks text
7312
+ // measuring on line wrapping boundaries.
7313
+ if (webkit && options.lineWrapping &&
7314
+ getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
7315
+ { display.lineDiv.style.textRendering = "auto" }
7316
+ }
7317
+
7318
+ // The default configuration options.
7319
+ CodeMirror.defaults = defaults
7320
+ // Functions to run when options are changed.
7321
+ CodeMirror.optionHandlers = optionHandlers
7322
+
7323
+ // Attach the necessary event handlers when initializing the editor
7324
+ function registerEventHandlers(cm) {
7325
+ var d = cm.display
7326
+ on(d.scroller, "mousedown", operation(cm, onMouseDown))
7327
+ // Older IE's will not fire a second mousedown for a double click
7328
+ if (ie && ie_version < 11)
7329
+ { on(d.scroller, "dblclick", operation(cm, function (e) {
7330
+ if (signalDOMEvent(cm, e)) { return }
7331
+ var pos = posFromMouse(cm, e)
7332
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }
7333
+ e_preventDefault(e)
7334
+ var word = cm.findWordAt(pos)
7335
+ extendSelection(cm.doc, word.anchor, word.head)
7336
+ })) }
7337
+ else
7338
+ { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }) }
7339
+ // Some browsers fire contextmenu *after* opening the menu, at
7340
+ // which point we can't mess with it anymore. Context menu is
7341
+ // handled in onMouseDown for these browsers.
7342
+ if (!captureRightClick) { on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }) }
7343
+
7344
+ // Used to suppress mouse event handling when a touch happens
7345
+ var touchFinished, prevTouch = {end: 0}
7346
+ function finishTouch() {
7347
+ if (d.activeTouch) {
7348
+ touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000)
7349
+ prevTouch = d.activeTouch
7350
+ prevTouch.end = +new Date
7351
+ }
7352
+ }
7353
+ function isMouseLikeTouchEvent(e) {
7354
+ if (e.touches.length != 1) { return false }
7355
+ var touch = e.touches[0]
7356
+ return touch.radiusX <= 1 && touch.radiusY <= 1
7357
+ }
7358
+ function farAway(touch, other) {
7359
+ if (other.left == null) { return true }
7360
+ var dx = other.left - touch.left, dy = other.top - touch.top
7361
+ return dx * dx + dy * dy > 20 * 20
7362
+ }
7363
+ on(d.scroller, "touchstart", function (e) {
7364
+ if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
7365
+ d.input.ensurePolled()
7366
+ clearTimeout(touchFinished)
7367
+ var now = +new Date
7368
+ d.activeTouch = {start: now, moved: false,
7369
+ prev: now - prevTouch.end <= 300 ? prevTouch : null}
7370
+ if (e.touches.length == 1) {
7371
+ d.activeTouch.left = e.touches[0].pageX
7372
+ d.activeTouch.top = e.touches[0].pageY
7373
+ }
7374
+ }
7375
+ })
7376
+ on(d.scroller, "touchmove", function () {
7377
+ if (d.activeTouch) { d.activeTouch.moved = true }
7378
+ })
7379
+ on(d.scroller, "touchend", function (e) {
7380
+ var touch = d.activeTouch
7381
+ if (touch && !eventInWidget(d, e) && touch.left != null &&
7382
+ !touch.moved && new Date - touch.start < 300) {
7383
+ var pos = cm.coordsChar(d.activeTouch, "page"), range
7384
+ if (!touch.prev || farAway(touch, touch.prev)) // Single tap
7385
+ { range = new Range(pos, pos) }
7386
+ else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
7387
+ { range = cm.findWordAt(pos) }
7388
+ else // Triple tap
7389
+ { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }
7390
+ cm.setSelection(range.anchor, range.head)
7391
+ cm.focus()
7392
+ e_preventDefault(e)
7393
+ }
7394
+ finishTouch()
7395
+ })
7396
+ on(d.scroller, "touchcancel", finishTouch)
7397
+
7398
+ // Sync scrolling between fake scrollbars and real scrollable
7399
+ // area, ensure viewport is updated when scrolling.
7400
+ on(d.scroller, "scroll", function () {
7401
+ if (d.scroller.clientHeight) {
7402
+ setScrollTop(cm, d.scroller.scrollTop)
7403
+ setScrollLeft(cm, d.scroller.scrollLeft, true)
7404
+ signal(cm, "scroll", cm)
7405
+ }
7406
+ })
7407
+
7408
+ // Listen to wheel events in order to try and update the viewport on time.
7409
+ on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); })
7410
+ on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); })
7411
+
7412
+ // Prevent wrapper from ever scrolling
7413
+ on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; })
7414
+
7415
+ d.dragFunctions = {
7416
+ enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e) }},
7417
+ over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }},
7418
+ start: function (e) { return onDragStart(cm, e); },
7419
+ drop: operation(cm, onDrop),
7420
+ leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }}
7421
+ }
7422
+
7423
+ var inp = d.input.getField()
7424
+ on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); })
7425
+ on(inp, "keydown", operation(cm, onKeyDown))
7426
+ on(inp, "keypress", operation(cm, onKeyPress))
7427
+ on(inp, "focus", function (e) { return onFocus(cm, e); })
7428
+ on(inp, "blur", function (e) { return onBlur(cm, e); })
7429
+ }
7430
+
7431
+ var initHooks = []
7432
+ CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }
7433
+
7434
+ // Indent the given line. The how parameter can be "smart",
7435
+ // "add"/null, "subtract", or "prev". When aggressive is false
7436
+ // (typically set to true for forced single-line indents), empty
7437
+ // lines are not indented, and places where the mode returns Pass
7438
+ // are left alone.
7439
+ function indentLine(cm, n, how, aggressive) {
7440
+ var doc = cm.doc, state
7441
+ if (how == null) { how = "add" }
7442
+ if (how == "smart") {
7443
+ // Fall back to "prev" when the mode doesn't have an indentation
7444
+ // method.
7445
+ if (!doc.mode.indent) { how = "prev" }
7446
+ else { state = getStateBefore(cm, n) }
7447
+ }
7448
+
7449
+ var tabSize = cm.options.tabSize
7450
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize)
7451
+ if (line.stateAfter) { line.stateAfter = null }
7452
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation
7453
+ if (!aggressive && !/\S/.test(line.text)) {
7454
+ indentation = 0
7455
+ how = "not"
7456
+ } else if (how == "smart") {
7457
+ indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text)
7458
+ if (indentation == Pass || indentation > 150) {
7459
+ if (!aggressive) { return }
7460
+ how = "prev"
7461
+ }
7462
+ }
7463
+ if (how == "prev") {
7464
+ if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize) }
7465
+ else { indentation = 0 }
7466
+ } else if (how == "add") {
7467
+ indentation = curSpace + cm.options.indentUnit
7468
+ } else if (how == "subtract") {
7469
+ indentation = curSpace - cm.options.indentUnit
7470
+ } else if (typeof how == "number") {
7471
+ indentation = curSpace + how
7472
+ }
7473
+ indentation = Math.max(0, indentation)
7474
+
7475
+ var indentString = "", pos = 0
7476
+ if (cm.options.indentWithTabs)
7477
+ { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t"} }
7478
+ if (pos < indentation) { indentString += spaceStr(indentation - pos) }
7479
+
7480
+ if (indentString != curSpaceString) {
7481
+ replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input")
7482
+ line.stateAfter = null
7483
+ return true
7484
+ } else {
7485
+ // Ensure that, if the cursor was in the whitespace at the start
7486
+ // of the line, it is moved to the end of that space.
7487
+ for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {
7488
+ var range = doc.sel.ranges[i$1]
7489
+ if (range.head.line == n && range.head.ch < curSpaceString.length) {
7490
+ var pos$1 = Pos(n, curSpaceString.length)
7491
+ replaceOneSelection(doc, i$1, new Range(pos$1, pos$1))
7492
+ break
7493
+ }
7494
+ }
7495
+ }
7496
+ }
7497
+
7498
+ // This will be set to a {lineWise: bool, text: [string]} object, so
7499
+ // that, when pasting, we know what kind of selections the copied
7500
+ // text was made out of.
7501
+ var lastCopied = null
7502
+
7503
+ function setLastCopied(newLastCopied) {
7504
+ lastCopied = newLastCopied
7505
+ }
7506
+
7507
+ function applyTextInput(cm, inserted, deleted, sel, origin) {
7508
+ var doc = cm.doc
7509
+ cm.display.shift = false
7510
+ if (!sel) { sel = doc.sel }
7511
+
7512
+ var paste = cm.state.pasteIncoming || origin == "paste"
7513
+ var textLines = splitLinesAuto(inserted), multiPaste = null
7514
+ // When pasing N lines into N selections, insert one line per selection
7515
+ if (paste && sel.ranges.length > 1) {
7516
+ if (lastCopied && lastCopied.text.join("\n") == inserted) {
7517
+ if (sel.ranges.length % lastCopied.text.length == 0) {
7518
+ multiPaste = []
7519
+ for (var i = 0; i < lastCopied.text.length; i++)
7520
+ { multiPaste.push(doc.splitLines(lastCopied.text[i])) }
7521
+ }
7522
+ } else if (textLines.length == sel.ranges.length) {
7523
+ multiPaste = map(textLines, function (l) { return [l]; })
7524
+ }
7525
+ }
7526
+
7527
+ var updateInput
7528
+ // Normal behavior is to insert the new text into every selection
7529
+ for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
7530
+ var range = sel.ranges[i$1]
7531
+ var from = range.from(), to = range.to()
7532
+ if (range.empty()) {
7533
+ if (deleted && deleted > 0) // Handle deletion
7534
+ { from = Pos(from.line, from.ch - deleted) }
7535
+ else if (cm.state.overwrite && !paste) // Handle overwrite
7536
+ { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)) }
7537
+ else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
7538
+ { from = to = Pos(from.line, 0) }
7539
+ }
7540
+ updateInput = cm.curOp.updateInput
7541
+ var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
7542
+ origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}
7543
+ makeChange(cm.doc, changeEvent)
7544
+ signalLater(cm, "inputRead", cm, changeEvent)
7545
+ }
7546
+ if (inserted && !paste)
7547
+ { triggerElectric(cm, inserted) }
7548
+
7549
+ ensureCursorVisible(cm)
7550
+ cm.curOp.updateInput = updateInput
7551
+ cm.curOp.typing = true
7552
+ cm.state.pasteIncoming = cm.state.cutIncoming = false
7553
+ }
7554
+
7555
+ function handlePaste(e, cm) {
7556
+ var pasted = e.clipboardData && e.clipboardData.getData("Text")
7557
+ if (pasted) {
7558
+ e.preventDefault()
7559
+ if (!cm.isReadOnly() && !cm.options.disableInput)
7560
+ { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }) }
7561
+ return true
7562
+ }
7563
+ }
7564
+
7565
+ function triggerElectric(cm, inserted) {
7566
+ // When an 'electric' character is inserted, immediately trigger a reindent
7567
+ if (!cm.options.electricChars || !cm.options.smartIndent) { return }
7568
+ var sel = cm.doc.sel
7569
+
7570
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
7571
+ var range = sel.ranges[i]
7572
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue }
7573
+ var mode = cm.getModeAt(range.head)
7574
+ var indented = false
7575
+ if (mode.electricChars) {
7576
+ for (var j = 0; j < mode.electricChars.length; j++)
7577
+ { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
7578
+ indented = indentLine(cm, range.head.line, "smart")
7579
+ break
7580
+ } }
7581
+ } else if (mode.electricInput) {
7582
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
7583
+ { indented = indentLine(cm, range.head.line, "smart") }
7584
+ }
7585
+ if (indented) { signalLater(cm, "electricInput", cm, range.head.line) }
7586
+ }
7587
+ }
7588
+
7589
+ function copyableRanges(cm) {
7590
+ var text = [], ranges = []
7591
+ for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
7592
+ var line = cm.doc.sel.ranges[i].head.line
7593
+ var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}
7594
+ ranges.push(lineRange)
7595
+ text.push(cm.getRange(lineRange.anchor, lineRange.head))
7596
+ }
7597
+ return {text: text, ranges: ranges}
7598
+ }
7599
+
7600
+ function disableBrowserMagic(field, spellcheck) {
7601
+ field.setAttribute("autocorrect", "off")
7602
+ field.setAttribute("autocapitalize", "off")
7603
+ field.setAttribute("spellcheck", !!spellcheck)
7604
+ }
7605
+
7606
+ function hiddenTextarea() {
7607
+ var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none")
7608
+ var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;")
7609
+ // The textarea is kept positioned near the cursor to prevent the
7610
+ // fact that it'll be scrolled into view on input from scrolling
7611
+ // our fake cursor out of view. On webkit, when wrap=off, paste is
7612
+ // very slow. So make the area wide instead.
7613
+ if (webkit) { te.style.width = "1000px" }
7614
+ else { te.setAttribute("wrap", "off") }
7615
+ // If border: 0; -- iOS fails to open keyboard (issue #1287)
7616
+ if (ios) { te.style.border = "1px solid black" }
7617
+ disableBrowserMagic(te)
7618
+ return div
7619
+ }
7620
+
7621
+ // The publicly visible API. Note that methodOp(f) means
7622
+ // 'wrap f in an operation, performed on its `this` parameter'.
7623
+
7624
+ // This is not the complete set of editor methods. Most of the
7625
+ // methods defined on the Doc type are also injected into
7626
+ // CodeMirror.prototype, for backwards compatibility and
7627
+ // convenience.
7628
+
7629
+ function addEditorMethods(CodeMirror) {
7630
+ var optionHandlers = CodeMirror.optionHandlers
7631
+
7632
+ var helpers = CodeMirror.helpers = {}
7633
 
7634
+ CodeMirror.prototype = {
7635
+ constructor: CodeMirror,
7636
+ focus: function(){window.focus(); this.display.input.focus()},
7637
 
7638
+ setOption: function(option, value) {
7639
+ var options = this.options, old = options[option]
7640
+ if (options[option] == value && option != "mode") { return }
7641
+ options[option] = value
7642
+ if (optionHandlers.hasOwnProperty(option))
7643
+ { operation(this, optionHandlers[option])(this, value, old) }
7644
+ signal(this, "optionChange", this, option)
7645
  },
7646
 
7647
+ getOption: function(option) {return this.options[option]},
7648
+ getDoc: function() {return this.doc},
7649
 
7650
+ addKeyMap: function(map, bottom) {
7651
+ this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map))
7652
  },
7653
+ removeKeyMap: function(map) {
7654
+ var maps = this.state.keyMaps
7655
+ for (var i = 0; i < maps.length; ++i)
7656
+ { if (maps[i] == map || maps[i].name == map) {
7657
+ maps.splice(i, 1)
7658
+ return true
7659
+ } }
 
 
 
 
 
7660
  },
7661
 
7662
+ addOverlay: methodOp(function(spec, options) {
7663
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec)
7664
+ if (mode.startState) { throw new Error("Overlays may not be stateful.") }
7665
+ insertSorted(this.state.overlays,
7666
+ {mode: mode, modeSpec: spec, opaque: options && options.opaque,
7667
+ priority: (options && options.priority) || 0},
7668
+ function (overlay) { return overlay.priority; })
7669
+ this.state.modeGen++
7670
+ regChange(this)
7671
+ }),
7672
+ removeOverlay: methodOp(function(spec) {
7673
+ var this$1 = this;
 
7674
 
7675
+ var overlays = this.state.overlays
7676
+ for (var i = 0; i < overlays.length; ++i) {
7677
+ var cur = overlays[i].modeSpec
7678
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
7679
+ overlays.splice(i, 1)
7680
+ this$1.state.modeGen++
7681
+ regChange(this$1)
7682
+ return
7683
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7684
  }
7685
+ }),
7686
 
7687
+ indentLine: methodOp(function(n, dir, aggressive) {
7688
+ if (typeof dir != "string" && typeof dir != "number") {
7689
+ if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev" }
7690
+ else { dir = dir ? "add" : "subtract" }
7691
  }
7692
+ if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive) }
7693
+ }),
7694
+ indentSelection: methodOp(function(how) {
7695
+ var this$1 = this;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7696
 
7697
+ var ranges = this.doc.sel.ranges, end = -1
7698
+ for (var i = 0; i < ranges.length; i++) {
7699
+ var range = ranges[i]
7700
+ if (!range.empty()) {
7701
+ var from = range.from(), to = range.to()
7702
+ var start = Math.max(end, from.line)
7703
+ end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1
7704
+ for (var j = start; j < end; ++j)
7705
+ { indentLine(this$1, j, how) }
7706
+ var newRanges = this$1.doc.sel.ranges
7707
+ if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
7708
+ { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll) }
7709
+ } else if (range.head.line > end) {
7710
+ indentLine(this$1, range.head.line, how, true)
7711
+ end = range.head.line
7712
+ if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1) }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7713
  }
7714
  }
7715
+ }),
7716
 
7717
+ // Fetch the parser token for a given character. Useful for hacks
7718
+ // that want to inspect the mode state (say, for completion).
7719
+ getTokenAt: function(pos, precise) {
7720
+ return takeToken(this, pos, precise)
 
 
 
 
 
 
 
7721
  },
7722
 
7723
+ getLineTokens: function(line, precise) {
7724
+ return takeToken(this, Pos(line), precise, true)
7725
  },
7726
 
7727
+ getTokenTypeAt: function(pos) {
7728
+ pos = clipPos(this.doc, pos)
7729
+ var styles = getLineStyles(this, getLine(this.doc, pos.line))
7730
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch
7731
+ var type
7732
+ if (ch == 0) { type = styles[2] }
7733
+ else { for (;;) {
7734
+ var mid = (before + after) >> 1
7735
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid }
7736
+ else if (styles[mid * 2 + 1] < ch) { before = mid + 1 }
7737
+ else { type = styles[mid * 2 + 2]; break }
7738
+ } }
7739
+ var cut = type ? type.indexOf("overlay ") : -1
7740
+ return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7741
  },
7742
 
7743
+ getModeAt: function(pos) {
7744
+ var mode = this.doc.mode
7745
+ if (!mode.innerMode) { return mode }
7746
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode
7747
  },
7748
 
7749
+ getHelper: function(pos, type) {
7750
+ return this.getHelpers(pos, type)[0]
 
 
7751
  },
7752
 
7753
+ getHelpers: function(pos, type) {
7754
+ var this$1 = this;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7755
 
7756
+ var found = []
7757
+ if (!helpers.hasOwnProperty(type)) { return found }
7758
+ var help = helpers[type], mode = this.getModeAt(pos)
7759
+ if (typeof mode[type] == "string") {
7760
+ if (help[mode[type]]) { found.push(help[mode[type]]) }
7761
+ } else if (mode[type]) {
7762
+ for (var i = 0; i < mode[type].length; i++) {
7763
+ var val = help[mode[type][i]]
7764
+ if (val) { found.push(val) }
7765
  }
7766
+ } else if (mode.helperType && help[mode.helperType]) {
7767
+ found.push(help[mode.helperType])
7768
+ } else if (help[mode.name]) {
7769
+ found.push(help[mode.name])
7770
  }
7771
+ for (var i$1 = 0; i$1 < help._global.length; i$1++) {
7772
+ var cur = help._global[i$1]
7773
+ if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1)
7774
+ { found.push(cur.val) }
7775
+ }
7776
+ return found
7777
  },
7778
 
7779
+ getStateAfter: function(line, precise) {
7780
+ var doc = this.doc
7781
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line)
7782
+ return getStateBefore(this, line + 1, precise)
 
 
 
 
7783
  },
7784
 
7785
+ cursorCoords: function(start, mode) {
7786
+ var pos, range = this.doc.sel.primary()
7787
+ if (start == null) { pos = range.head }
7788
+ else if (typeof start == "object") { pos = clipPos(this.doc, start) }
7789
+ else { pos = start ? range.from() : range.to() }
7790
+ return cursorCoords(this, pos, mode || "page")
7791
  },
7792
 
7793
+ charCoords: function(pos, mode) {
7794
+ return charCoords(this, clipPos(this.doc, pos), mode || "page")
 
 
7795
  },
7796
 
7797
+ coordsChar: function(coords, mode) {
7798
+ coords = fromCoordSystem(this, coords, mode || "page")
7799
+ return coordsChar(this, coords.left, coords.top)
 
 
7800
  },
7801
 
7802
+ lineAtHeight: function(height, mode) {
7803
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top
7804
+ return lineAtHeight(this.doc, height + this.display.viewOffset)
7805
  },
7806
+ heightAtLine: function(line, mode, includeWidgets) {
7807
+ var end = false, lineObj
7808
+ if (typeof line == "number") {
7809
+ var last = this.doc.first + this.doc.size - 1
7810
+ if (line < this.doc.first) { line = this.doc.first }
7811
+ else if (line > last) { line = last; end = true }
7812
+ lineObj = getLine(this.doc, line)
7813
+ } else {
7814
+ lineObj = line
 
 
 
 
 
 
 
 
7815
  }
7816
+ return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets).top +
7817
+ (end ? this.doc.height - heightAtLine(lineObj) : 0)
 
 
 
 
 
7818
  },
7819
 
7820
+ defaultTextHeight: function() { return textHeight(this.display) },
7821
+ defaultCharWidth: function() { return charWidth(this.display) },
 
 
 
 
 
 
 
 
 
 
7822
 
7823
+ getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},
 
 
 
7824
 
7825
+ addWidget: function(pos, node, scroll, vert, horiz) {
7826
+ var display = this.display
7827
+ pos = cursorCoords(this, clipPos(this.doc, pos))
7828
+ var top = pos.bottom, left = pos.left
7829
+ node.style.position = "absolute"
7830
+ node.setAttribute("cm-ignore-events", "true")
7831
+ this.display.input.setUneditable(node)
7832
+ display.sizer.appendChild(node)
7833
+ if (vert == "over") {
7834
+ top = pos.top
7835
+ } else if (vert == "above" || vert == "near") {
7836
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
7837
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth)
7838
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
7839
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
7840
+ { top = pos.top - node.offsetHeight }
7841
+ else if (pos.bottom + node.offsetHeight <= vspace)
7842
+ { top = pos.bottom }
7843
+ if (left + node.offsetWidth > hspace)
7844
+ { left = hspace - node.offsetWidth }
7845
  }
7846
+ node.style.top = top + "px"
7847
+ node.style.left = node.style.right = ""
7848
+ if (horiz == "right") {
7849
+ left = display.sizer.clientWidth - node.offsetWidth
7850
+ node.style.right = "0px"
7851
  } else {
7852
+ if (horiz == "left") { left = 0 }
7853
+ else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2 }
7854
+ node.style.left = left + "px"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7855
  }
7856
+ if (scroll)
7857
+ { scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight) }
7858
  },
7859
 
7860
+ triggerOnKeyDown: methodOp(onKeyDown),
7861
+ triggerOnKeyPress: methodOp(onKeyPress),
7862
+ triggerOnKeyUp: onKeyUp,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7863
 
7864
+ execCommand: function(cmd) {
7865
+ if (commands.hasOwnProperty(cmd))
7866
+ { return commands[cmd].call(null, this) }
7867
  },
7868
 
7869
+ triggerElectric: methodOp(function(text) { triggerElectric(this, text) }),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7870
 
7871
+ findPosH: function(from, amount, unit, visually) {
7872
+ var this$1 = this;
7873
 
7874
+ var dir = 1
7875
+ if (amount < 0) { dir = -1; amount = -amount }
7876
+ var cur = clipPos(this.doc, from)
7877
+ for (var i = 0; i < amount; ++i) {
7878
+ cur = findPosH(this$1.doc, cur, dir, unit, visually)
7879
+ if (cur.hitSide) { break }
 
 
 
 
7880
  }
7881
+ return cur
7882
+ },
 
 
 
 
 
7883
 
7884
+ moveH: methodOp(function(dir, unit) {
7885
+ var this$1 = this;
 
 
 
 
 
 
 
 
 
 
7886
 
7887
+ this.extendSelectionsBy(function (range) {
7888
+ if (this$1.display.shift || this$1.doc.extend || range.empty())
7889
+ { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) }
7890
+ else
7891
+ { return dir < 0 ? range.from() : range.to() }
7892
+ }, sel_move)
7893
+ }),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7894
 
7895
+ deleteH: methodOp(function(dir, unit) {
7896
+ var sel = this.doc.sel, doc = this.doc
7897
+ if (sel.somethingSelected())
7898
+ { doc.replaceSelection("", null, "+delete") }
 
 
 
 
 
 
 
 
7899
  else
7900
+ { deleteNearSelection(this, function (range) {
7901
+ var other = findPosH(doc, range.head, dir, unit, false)
7902
+ return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}
7903
+ }) }
7904
+ }),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7905
 
7906
+ findPosV: function(from, amount, unit, goalColumn) {
7907
+ var this$1 = this;
7908
+
7909
+ var dir = 1, x = goalColumn
7910
+ if (amount < 0) { dir = -1; amount = -amount }
7911
+ var cur = clipPos(this.doc, from)
7912
+ for (var i = 0; i < amount; ++i) {
7913
+ var coords = cursorCoords(this$1, cur, "div")
7914
+ if (x == null) { x = coords.left }
7915
+ else { coords.left = x }
7916
+ cur = findPosV(this$1, coords, dir, unit)
7917
+ if (cur.hitSide) { break }
7918
+ }
7919
+ return cur
 
 
 
 
 
 
7920
  },
 
 
 
 
 
 
 
 
 
 
7921
 
7922
+ moveV: methodOp(function(dir, unit) {
7923
+ var this$1 = this;
 
7924
 
7925
+ var doc = this.doc, goals = []
7926
+ var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected()
7927
+ doc.extendSelectionsBy(function (range) {
7928
+ if (collapse)
7929
+ { return dir < 0 ? range.from() : range.to() }
7930
+ var headPos = cursorCoords(this$1, range.head, "div")
7931
+ if (range.goalColumn != null) { headPos.left = range.goalColumn }
7932
+ goals.push(headPos.left)
7933
+ var pos = findPosV(this$1, headPos, dir, unit)
7934
+ if (unit == "page" && range == doc.sel.primary())
7935
+ { addToScrollPos(this$1, null, charCoords(this$1, pos, "div").top - headPos.top) }
7936
+ return pos
7937
+ }, sel_move)
7938
+ if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
7939
+ { doc.sel.ranges[i].goalColumn = goals[i] } }
7940
+ }),
7941
 
7942
+ // Find the word at the given position (as returned by coordsChar).
7943
+ findWordAt: function(pos) {
7944
+ var doc = this.doc, line = getLine(doc, pos.line).text
7945
+ var start = pos.ch, end = pos.ch
7946
+ if (line) {
7947
+ var helper = this.getHelper(pos, "wordChars")
7948
+ if ((pos.xRel < 0 || end == line.length) && start) { --start; } else { ++end }
7949
+ var startChar = line.charAt(start)
7950
+ var check = isWordChar(startChar, helper)
7951
+ ? function (ch) { return isWordChar(ch, helper); }
7952
+ : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); }
7953
+ : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }
7954
+ while (start > 0 && check(line.charAt(start - 1))) { --start }
7955
+ while (end < line.length && check(line.charAt(end))) { ++end }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7956
  }
7957
+ return new Range(Pos(pos.line, start), Pos(pos.line, end))
7958
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7959
 
7960
+ toggleOverwrite: function(value) {
7961
+ if (value != null && value == this.state.overwrite) { return }
7962
+ if (this.state.overwrite = !this.state.overwrite)
7963
+ { addClass(this.display.cursorDiv, "CodeMirror-overwrite") }
7964
+ else
7965
+ { rmClass(this.display.cursorDiv, "CodeMirror-overwrite") }
7966
 
7967
+ signal(this, "overwriteToggle", this, this.state.overwrite)
7968
+ },
7969
+ hasFocus: function() { return this.display.input.getField() == activeElt() },
7970
+ isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
 
 
7971
 
7972
+ scrollTo: methodOp(function(x, y) {
7973
+ if (x != null || y != null) { resolveScrollToPos(this) }
7974
+ if (x != null) { this.curOp.scrollLeft = x }
7975
+ if (y != null) { this.curOp.scrollTop = y }
7976
+ }),
7977
+ getScrollInfo: function() {
7978
+ var scroller = this.display.scroller
7979
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
7980
+ height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
7981
+ width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
7982
+ clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
7983
+ },
7984
 
7985
+ scrollIntoView: methodOp(function(range, margin) {
7986
+ if (range == null) {
7987
+ range = {from: this.doc.sel.primary().head, to: null}
7988
+ if (margin == null) { margin = this.options.cursorScrollMargin }
7989
+ } else if (typeof range == "number") {
7990
+ range = {from: Pos(range, 0), to: null}
7991
+ } else if (range.from == null) {
7992
+ range = {from: range, to: null}
 
 
 
 
7993
  }
7994
+ if (!range.to) { range.to = range.from }
7995
+ range.margin = margin || 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7996
 
7997
+ if (range.from.line != null) {
7998
+ resolveScrollToPos(this)
7999
+ this.curOp.scrollToPos = range
8000
+ } else {
8001
+ var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
8002
+ Math.min(range.from.top, range.to.top) - range.margin,
8003
+ Math.max(range.from.right, range.to.right),
8004
+ Math.max(range.from.bottom, range.to.bottom) + range.margin)
8005
+ this.scrollTo(sPos.scrollLeft, sPos.scrollTop)
8006
  }
8007
+ }),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8008
 
8009
+ setSize: methodOp(function(width, height) {
8010
+ var this$1 = this;
8011
+
8012
+ var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }
8013
+ if (width != null) { this.display.wrapper.style.width = interpret(width) }
8014
+ if (height != null) { this.display.wrapper.style.height = interpret(height) }
8015
+ if (this.options.lineWrapping) { clearLineMeasurementCache(this) }
8016
+ var lineNo = this.display.viewFrom
8017
+ this.doc.iter(lineNo, this.display.viewTo, function (line) {
8018
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
8019
+ { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } }
8020
+ ++lineNo
8021
+ })
8022
+ this.curOp.forceUpdate = true
8023
+ signal(this, "refresh", this)
8024
+ }),
8025
 
8026
+ operation: function(f){return runInOp(this, f)},
8027
 
8028
+ refresh: methodOp(function() {
8029
+ var oldHeight = this.display.cachedTextHeight
8030
+ regChange(this)
8031
+ this.curOp.forceUpdate = true
8032
+ clearCaches(this)
8033
+ this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop)
8034
+ updateGutterSpace(this)
8035
+ if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
8036
+ { estimateLineHeights(this) }
8037
+ signal(this, "refresh", this)
8038
+ }),
8039
 
8040
+ swapDoc: methodOp(function(doc) {
8041
+ var old = this.doc
8042
+ old.cm = null
8043
+ attachDoc(this, doc)
8044
+ clearCaches(this)
8045
+ this.display.input.reset()
8046
+ this.scrollTo(doc.scrollLeft, doc.scrollTop)
8047
+ this.curOp.forceScroll = true
8048
+ signalLater(this, "swapDoc", this, old)
8049
+ return old
8050
+ }),
8051
 
8052
+ getInputField: function(){return this.display.input.getField()},
8053
+ getWrapperElement: function(){return this.display.wrapper},
8054
+ getScrollerElement: function(){return this.display.scroller},
8055
+ getGutterElement: function(){return this.display.gutters}
 
 
 
 
 
 
8056
  }
8057
+ eventMixin(CodeMirror)
8058
 
8059
+ CodeMirror.registerHelper = function(type, name, value) {
8060
+ if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []} }
8061
+ helpers[type][name] = value
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8062
  }
8063
+ CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
8064
+ CodeMirror.registerHelper(type, name, value)
8065
+ helpers[type]._global.push({pred: predicate, val: value})
8066
+ }
8067
+ }
8068
+
8069
+ // Used for horizontal relative motion. Dir is -1 or 1 (left or
8070
+ // right), unit can be "char", "column" (like char, but doesn't
8071
+ // cross line boundaries), "word" (across next word), or "group" (to
8072
+ // the start of next group of word or non-word-non-whitespace
8073
+ // chars). The visually param controls whether, in right-to-left
8074
+ // text, direction 1 means to move towards the next index in the
8075
+ // string, or towards the character to the right of the current
8076
+ // position. The resulting position will have a hitSide=true
8077
+ // property if it reached the end of the document.
8078
+ function findPosH(doc, pos, dir, unit, visually) {
8079
+ var line = pos.line, ch = pos.ch, origDir = dir
8080
+ var lineObj = getLine(doc, line)
8081
+ function findNextLine() {
8082
+ var l = line + dir
8083
+ if (l < doc.first || l >= doc.first + doc.size) { return false }
8084
+ line = l
8085
+ return lineObj = getLine(doc, l)
8086
+ }
8087
+ function moveOnce(boundToLine) {
8088
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true)
8089
+ if (next == null) {
8090
+ if (!boundToLine && findNextLine()) {
8091
+ if (visually) { ch = (dir < 0 ? lineRight : lineLeft)(lineObj) }
8092
+ else { ch = dir < 0 ? lineObj.text.length : 0 }
8093
+ } else { return false }
8094
+ } else { ch = next }
8095
+ return true
8096
+ }
8097
+
8098
+ if (unit == "char") {
8099
+ moveOnce()
8100
+ } else if (unit == "column") {
8101
+ moveOnce(true)
8102
+ } else if (unit == "word" || unit == "group") {
8103
+ var sawType = null, group = unit == "group"
8104
+ var helper = doc.cm && doc.cm.getHelper(pos, "wordChars")
8105
+ for (var first = true;; first = false) {
8106
+ if (dir < 0 && !moveOnce(!first)) { break }
8107
+ var cur = lineObj.text.charAt(ch) || "\n"
8108
+ var type = isWordChar(cur, helper) ? "w"
8109
+ : group && cur == "\n" ? "n"
8110
+ : !group || /\s/.test(cur) ? null
8111
+ : "p"
8112
+ if (group && !first && !type) { type = "s" }
8113
+ if (sawType && sawType != type) {
8114
+ if (dir < 0) {dir = 1; moveOnce()}
8115
+ break
8116
+ }
8117
+
8118
+ if (type) { sawType = type }
8119
+ if (dir > 0 && !moveOnce(!first)) { break }
8120
+ }
8121
+ }
8122
+ var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true)
8123
+ if (!cmp(pos, result)) { result.hitSide = true }
8124
+ return result
8125
+ }
8126
+
8127
+ // For relative vertical movement. Dir may be -1 or 1. Unit can be
8128
+ // "page" or "line". The resulting position will have a hitSide=true
8129
+ // property if it reached the end of the document.
8130
+ function findPosV(cm, pos, dir, unit) {
8131
+ var doc = cm.doc, x = pos.left, y
8132
+ if (unit == "page") {
8133
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight)
8134
+ var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3)
8135
+ y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount
8136
+
8137
+ } else if (unit == "line") {
8138
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3
8139
+ }
8140
+ var target
8141
+ for (;;) {
8142
+ target = coordsChar(cm, x, y)
8143
+ if (!target.outside) { break }
8144
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }
8145
+ y += dir * 5
8146
+ }
8147
+ return target
8148
+ }
8149
+
8150
+ // CONTENTEDITABLE INPUT STYLE
8151
+
8152
+ var ContentEditableInput = function(cm) {
8153
+ this.cm = cm
8154
+ this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null
8155
+ this.polling = new Delayed()
8156
+ this.composing = null
8157
+ this.gracePeriod = false
8158
+ this.readDOMTimeout = null
8159
+ };
8160
+
8161
+ ContentEditableInput.prototype.init = function (display) {
8162
+ var this$1 = this;
8163
+
8164
+ var input = this, cm = input.cm
8165
+ var div = input.div = display.lineDiv
8166
+ disableBrowserMagic(div, cm.options.spellcheck)
8167
+
8168
+ on(div, "paste", function (e) {
8169
+ if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
8170
+ // IE doesn't fire input events, so we schedule a read for the pasted content in this way
8171
+ if (ie_version <= 11) { setTimeout(operation(cm, function () {
8172
+ if (!input.pollContent()) { regChange(cm) }
8173
+ }), 20) }
8174
+ })
8175
+
8176
+ on(div, "compositionstart", function (e) {
8177
+ this$1.composing = {data: e.data, done: false}
8178
+ })
8179
+ on(div, "compositionupdate", function (e) {
8180
+ if (!this$1.composing) { this$1.composing = {data: e.data, done: false} }
8181
+ })
8182
+ on(div, "compositionend", function (e) {
8183
+ if (this$1.composing) {
8184
+ if (e.data != this$1.composing.data) { this$1.readFromDOMSoon() }
8185
+ this$1.composing.done = true
8186
+ }
8187
+ })
8188
+
8189
+ on(div, "touchstart", function () { return input.forceCompositionEnd(); })
8190
+
8191
+ on(div, "input", function () {
8192
+ if (!this$1.composing) { this$1.readFromDOMSoon() }
8193
+ })
8194
+
8195
+ function onCopyCut(e) {
8196
+ if (signalDOMEvent(cm, e)) { return }
8197
+ if (cm.somethingSelected()) {
8198
+ setLastCopied({lineWise: false, text: cm.getSelections()})
8199
+ if (e.type == "cut") { cm.replaceSelection("", null, "cut") }
8200
+ } else if (!cm.options.lineWiseCopyCut) {
8201
+ return
8202
  } else {
8203
+ var ranges = copyableRanges(cm)
8204
+ setLastCopied({lineWise: true, text: ranges.text})
8205
+ if (e.type == "cut") {
8206
+ cm.operation(function () {
8207
+ cm.setSelections(ranges.ranges, 0, sel_dontScroll)
8208
+ cm.replaceSelection("", null, "cut")
8209
+ })
8210
+ }
8211
+ }
8212
+ if (e.clipboardData) {
8213
+ e.clipboardData.clearData()
8214
+ var content = lastCopied.text.join("\n")
8215
+ // iOS exposes the clipboard API, but seems to discard content inserted into it
8216
+ e.clipboardData.setData("Text", content)
8217
+ if (e.clipboardData.getData("Text") == content) {
8218
+ e.preventDefault()
8219
+ return
8220
+ }
8221
+ }
8222
+ // Old-fashioned briefly-focus-a-textarea hack
8223
+ var kludge = hiddenTextarea(), te = kludge.firstChild
8224
+ cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild)
8225
+ te.value = lastCopied.text.join("\n")
8226
+ var hadFocus = document.activeElement
8227
+ selectInput(te)
8228
+ setTimeout(function () {
8229
+ cm.display.lineSpace.removeChild(kludge)
8230
+ hadFocus.focus()
8231
+ if (hadFocus == div) { input.showPrimarySelection() }
8232
+ }, 50)
8233
+ }
8234
+ on(div, "copy", onCopyCut)
8235
+ on(div, "cut", onCopyCut)
8236
+ };
8237
+
8238
+ ContentEditableInput.prototype.prepareSelection = function () {
8239
+ var result = prepareSelection(this.cm, false)
8240
+ result.focus = this.cm.state.focused
8241
+ return result
8242
+ };
8243
+
8244
+ ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
8245
+ if (!info || !this.cm.display.view.length) { return }
8246
+ if (info.focus || takeFocus) { this.showPrimarySelection() }
8247
+ this.showMultipleSelections(info)
8248
+ };
8249
+
8250
+ ContentEditableInput.prototype.showPrimarySelection = function () {
8251
+ var sel = window.getSelection(), prim = this.cm.doc.sel.primary()
8252
+ var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset)
8253
+ var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset)
8254
+ if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
8255
+ cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
8256
+ cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
8257
+ { return }
8258
+
8259
+ var start = posToDOM(this.cm, prim.from())
8260
+ var end = posToDOM(this.cm, prim.to())
8261
+ if (!start && !end) { return }
8262
+
8263
+ var view = this.cm.display.view
8264
+ var old = sel.rangeCount && sel.getRangeAt(0)
8265
+ if (!start) {
8266
+ start = {node: view[0].measure.map[2], offset: 0}
8267
+ } else if (!end) { // FIXME dangerously hacky
8268
+ var measure = view[view.length - 1].measure
8269
+ var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map
8270
+ end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}
8271
+ }
8272
+
8273
+ var rng
8274
+ try { rng = range(start.node, start.offset, end.offset, end.node) }
8275
+ catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
8276
+ if (rng) {
8277
+ if (!gecko && this.cm.state.focused) {
8278
+ sel.collapse(start.node, start.offset)
8279
+ if (!rng.collapsed) {
8280
+ sel.removeAllRanges()
8281
+ sel.addRange(rng)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8282
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8283
  } else {
8284
+ sel.removeAllRanges()
8285
+ sel.addRange(rng)
8286
+ }
8287
+ if (old && sel.anchorNode == null) { sel.addRange(old) }
8288
+ else if (gecko) { this.startGracePeriod() }
8289
+ }
8290
+ this.rememberSelection()
8291
+ };
8292
+
8293
+ ContentEditableInput.prototype.startGracePeriod = function () {
8294
+ var this$1 = this;
8295
+
8296
+ clearTimeout(this.gracePeriod)
8297
+ this.gracePeriod = setTimeout(function () {
8298
+ this$1.gracePeriod = false
8299
+ if (this$1.selectionChanged())
8300
+ { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }) }
8301
+ }, 20)
8302
+ };
8303
+
8304
+ ContentEditableInput.prototype.showMultipleSelections = function (info) {
8305
+ removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors)
8306
+ removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection)
8307
+ };
8308
+
8309
+ ContentEditableInput.prototype.rememberSelection = function () {
8310
+ var sel = window.getSelection()
8311
+ this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset
8312
+ this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset
8313
+ };
8314
+
8315
+ ContentEditableInput.prototype.selectionInEditor = function () {
8316
+ var sel = window.getSelection()
8317
+ if (!sel.rangeCount) { return false }
8318
+ var node = sel.getRangeAt(0).commonAncestorContainer
8319
+ return contains(this.div, node)
8320
+ };
8321
+
8322
+ ContentEditableInput.prototype.focus = function () {
8323
+ if (this.cm.options.readOnly != "nocursor") {
8324
+ if (!this.selectionInEditor())
8325
+ { this.showSelection(this.prepareSelection(), true) }
8326
+ this.div.focus()
8327
+ }
8328
+ };
8329
+ ContentEditableInput.prototype.blur = function () { this.div.blur() };
8330
+ ContentEditableInput.prototype.getField = function () { return this.div };
8331
+
8332
+ ContentEditableInput.prototype.supportsTouch = function () { return true };
8333
+
8334
+ ContentEditableInput.prototype.receivedFocus = function () {
8335
+ var input = this
8336
+ if (this.selectionInEditor())
8337
+ { this.pollSelection() }
8338
+ else
8339
+ { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }) }
8340
+
8341
+ function poll() {
8342
+ if (input.cm.state.focused) {
8343
+ input.pollSelection()
8344
+ input.polling.set(input.cm.options.pollInterval, poll)
8345
+ }
8346
+ }
8347
+ this.polling.set(this.cm.options.pollInterval, poll)
8348
+ };
8349
+
8350
+ ContentEditableInput.prototype.selectionChanged = function () {
8351
+ var sel = window.getSelection()
8352
+ return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
8353
+ sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
8354
+ };
8355
+
8356
+ ContentEditableInput.prototype.pollSelection = function () {
8357
+ if (!this.composing && this.readDOMTimeout == null && !this.gracePeriod && this.selectionChanged()) {
8358
+ var sel = window.getSelection(), cm = this.cm
8359
+ this.rememberSelection()
8360
+ var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset)
8361
+ var head = domToPos(cm, sel.focusNode, sel.focusOffset)
8362
+ if (anchor && head) { runInOp(cm, function () {
8363
+ setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll)
8364
+ if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true }
8365
+ }) }
8366
+ }
8367
+ };
8368
+
8369
+ ContentEditableInput.prototype.pollContent = function () {
8370
+ if (this.readDOMTimeout != null) {
8371
+ clearTimeout(this.readDOMTimeout)
8372
+ this.readDOMTimeout = null
8373
+ }
8374
+
8375
+ var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary()
8376
+ var from = sel.from(), to = sel.to()
8377
+ if (from.ch == 0 && from.line > cm.firstLine())
8378
+ { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length) }
8379
+ if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())
8380
+ { to = Pos(to.line + 1, 0) }
8381
+ if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }
8382
+
8383
+ var fromIndex, fromLine, fromNode
8384
+ if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
8385
+ fromLine = lineNo(display.view[0].line)
8386
+ fromNode = display.view[0].node
8387
+ } else {
8388
+ fromLine = lineNo(display.view[fromIndex].line)
8389
+ fromNode = display.view[fromIndex - 1].node.nextSibling
8390
+ }
8391
+ var toIndex = findViewIndex(cm, to.line)
8392
+ var toLine, toNode
8393
+ if (toIndex == display.view.length - 1) {
8394
+ toLine = display.viewTo - 1
8395
+ toNode = display.lineDiv.lastChild
8396
+ } else {
8397
+ toLine = lineNo(display.view[toIndex + 1].line) - 1
8398
+ toNode = display.view[toIndex + 1].node.previousSibling
8399
+ }
8400
+
8401
+ if (!fromNode) { return false }
8402
+ var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine))
8403
+ var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length))
8404
+ while (newText.length > 1 && oldText.length > 1) {
8405
+ if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine-- }
8406
+ else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++ }
8407
+ else { break }
8408
+ }
8409
+
8410
+ var cutFront = 0, cutEnd = 0
8411
+ var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length)
8412
+ while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
8413
+ { ++cutFront }
8414
+ var newBot = lst(newText), oldBot = lst(oldText)
8415
+ var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
8416
+ oldBot.length - (oldText.length == 1 ? cutFront : 0))
8417
+ while (cutEnd < maxCutEnd &&
8418
+ newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
8419
+ { ++cutEnd }
8420
+
8421
+ newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "")
8422
+ newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "")
8423
+
8424
+ var chFrom = Pos(fromLine, cutFront)
8425
+ var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0)
8426
+ if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
8427
+ replaceRange(cm.doc, newText, chFrom, chTo, "+input")
8428
+ return true
8429
+ }
8430
+ };
8431
+
8432
+ ContentEditableInput.prototype.ensurePolled = function () {
8433
+ this.forceCompositionEnd()
8434
+ };
8435
+ ContentEditableInput.prototype.reset = function () {
8436
+ this.forceCompositionEnd()
8437
+ };
8438
+ ContentEditableInput.prototype.forceCompositionEnd = function () {
8439
+ if (!this.composing) { return }
8440
+ clearTimeout(this.readDOMTimeout)
8441
+ this.composing = null
8442
+ if (!this.pollContent()) { regChange(this.cm) }
8443
+ this.div.blur()
8444
+ this.div.focus()
8445
+ };
8446
+ ContentEditableInput.prototype.readFromDOMSoon = function () {
8447
+ var this$1 = this;
8448
+
8449
+ if (this.readDOMTimeout != null) { return }
8450
+ this.readDOMTimeout = setTimeout(function () {
8451
+ this$1.readDOMTimeout = null
8452
+ if (this$1.composing) {
8453
+ if (this$1.composing.done) { this$1.composing = null }
8454
+ else { return }
8455
+ }
8456
+ if (this$1.cm.isReadOnly() || !this$1.pollContent())
8457
+ { runInOp(this$1.cm, function () { return regChange(this$1.cm); }) }
8458
+ }, 80)
8459
+ };
8460
+
8461
+ ContentEditableInput.prototype.setUneditable = function (node) {
8462
+ node.contentEditable = "false"
8463
+ };
8464
+
8465
+ ContentEditableInput.prototype.onKeyPress = function (e) {
8466
+ e.preventDefault()
8467
+ if (!this.cm.isReadOnly())
8468
+ { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) }
8469
+ };
8470
+
8471
+ ContentEditableInput.prototype.readOnlyChanged = function (val) {
8472
+ this.div.contentEditable = String(val != "nocursor")
8473
+ };
8474
+
8475
+ ContentEditableInput.prototype.onContextMenu = function () {};
8476
+ ContentEditableInput.prototype.resetPosition = function () {};
8477
+
8478
+ ContentEditableInput.prototype.needsContentAttribute = true
8479
+
8480
+ function posToDOM(cm, pos) {
8481
+ var view = findViewForLine(cm, pos.line)
8482
+ if (!view || view.hidden) { return null }
8483
+ var line = getLine(cm.doc, pos.line)
8484
+ var info = mapFromLineView(view, line, pos.line)
8485
+
8486
+ var order = getOrder(line), side = "left"
8487
+ if (order) {
8488
+ var partPos = getBidiPartAt(order, pos.ch)
8489
+ side = partPos % 2 ? "right" : "left"
8490
+ }
8491
+ var result = nodeAndOffsetInLineMap(info.map, pos.ch, side)
8492
+ result.offset = result.collapse == "right" ? result.end : result.start
8493
+ return result
8494
+ }
8495
+
8496
+ function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }
8497
+
8498
+ function domTextBetween(cm, from, to, fromLine, toLine) {
8499
+ var text = "", closing = false, lineSep = cm.doc.lineSeparator()
8500
+ function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
8501
+ function walk(node) {
8502
+ if (node.nodeType == 1) {
8503
+ var cmText = node.getAttribute("cm-text")
8504
+ if (cmText != null) {
8505
+ if (cmText == "") { text += node.textContent.replace(/\u200b/g, "") }
8506
+ else { text += cmText }
8507
+ return
8508
+ }
8509
+ var markerID = node.getAttribute("cm-marker"), range
8510
+ if (markerID) {
8511
+ var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID))
8512
+ if (found.length && (range = found[0].find()))
8513
+ { text += getBetween(cm.doc, range.from, range.to).join(lineSep) }
8514
+ return
8515
+ }
8516
+ if (node.getAttribute("contenteditable") == "false") { return }
8517
+ for (var i = 0; i < node.childNodes.length; i++)
8518
+ { walk(node.childNodes[i]) }
8519
+ if (/^(pre|div|p)$/i.test(node.nodeName))
8520
+ { closing = true }
8521
+ } else if (node.nodeType == 3) {
8522
+ var val = node.nodeValue
8523
+ if (!val) { return }
8524
+ if (closing) {
8525
+ text += lineSep
8526
+ closing = false
8527
+ }
8528
+ text += val
8529
+ }
8530
+ }
8531
+ for (;;) {
8532
+ walk(from)
8533
+ if (from == to) { break }
8534
+ from = from.nextSibling
8535
+ }
8536
+ return text
8537
+ }
8538
+
8539
+ function domToPos(cm, node, offset) {
8540
+ var lineNode
8541
+ if (node == cm.display.lineDiv) {
8542
+ lineNode = cm.display.lineDiv.childNodes[offset]
8543
+ if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }
8544
+ node = null; offset = 0
8545
+ } else {
8546
+ for (lineNode = node;; lineNode = lineNode.parentNode) {
8547
+ if (!lineNode || lineNode == cm.display.lineDiv) { return null }
8548
+ if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }
8549
+ }
8550
+ }
8551
+ for (var i = 0; i < cm.display.view.length; i++) {
8552
+ var lineView = cm.display.view[i]
8553
+ if (lineView.node == lineNode)
8554
+ { return locateNodeInLineView(lineView, node, offset) }
8555
+ }
8556
+ }
8557
+
8558
+ function locateNodeInLineView(lineView, node, offset) {
8559
+ var wrapper = lineView.text.firstChild, bad = false
8560
+ if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }
8561
+ if (node == wrapper) {
8562
+ bad = true
8563
+ node = wrapper.childNodes[offset]
8564
+ offset = 0
8565
+ if (!node) {
8566
+ var line = lineView.rest ? lst(lineView.rest) : lineView.line
8567
+ return badPos(Pos(lineNo(line), line.text.length), bad)
8568
+ }
8569
+ }
8570
+
8571
+ var textNode = node.nodeType == 3 ? node : null, topNode = node
8572
+ if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
8573
+ textNode = node.firstChild
8574
+ if (offset) { offset = textNode.nodeValue.length }
8575
+ }
8576
+ while (topNode.parentNode != wrapper) { topNode = topNode.parentNode }
8577
+ var measure = lineView.measure, maps = measure.maps
8578
+
8579
+ function find(textNode, topNode, offset) {
8580
+ for (var i = -1; i < (maps ? maps.length : 0); i++) {
8581
+ var map = i < 0 ? measure.map : maps[i]
8582
+ for (var j = 0; j < map.length; j += 3) {
8583
+ var curNode = map[j + 2]
8584
+ if (curNode == textNode || curNode == topNode) {
8585
+ var line = lineNo(i < 0 ? lineView.line : lineView.rest[i])
8586
+ var ch = map[j] + offset
8587
+ if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)] }
8588
+ return Pos(line, ch)
8589
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8590
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8591
  }
8592
  }
8593
+ var found = find(textNode, topNode, offset)
8594
+ if (found) { return badPos(found, bad) }
8595
 
8596
+ // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
8597
+ for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
8598
+ found = find(after, after.firstChild, 0)
8599
+ if (found)
8600
+ { return badPos(Pos(found.line, found.ch - dist), bad) }
8601
+ else
8602
+ { dist += after.textContent.length }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8603
  }
8604
+ for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {
8605
+ found = find(before, before.firstChild, -1)
8606
+ if (found)
8607
+ { return badPos(Pos(found.line, found.ch + dist$1), bad) }
8608
+ else
8609
+ { dist$1 += before.textContent.length }
8610
+ }
8611
+ }
8612
+
8613
+ // TEXTAREA INPUT STYLE
8614
+
8615
+ var TextareaInput = function(cm) {
8616
+ this.cm = cm
8617
+ // See input.poll and input.reset
8618
+ this.prevInput = ""
8619
+
8620
+ // Flag that indicates whether we expect input to appear real soon
8621
+ // now (after some event like 'keypress' or 'input') and are
8622
+ // polling intensively.
8623
+ this.pollingFast = false
8624
+ // Self-resetting timeout for the poller
8625
+ this.polling = new Delayed()
8626
+ // Tracks when input.reset has punted to just putting a short
8627
+ // string into the textarea instead of the full selection.
8628
+ this.inaccurateSelection = false
8629
+ // Used to work around IE issue with selection being forgotten when focus moves away from textarea
8630
+ this.hasSelection = false
8631
+ this.composing = null
8632
+ };
8633
+
8634
+ TextareaInput.prototype.init = function (display) {
8635
+ var this$1 = this;
8636
+
8637
+ var input = this, cm = this.cm
8638
+
8639
+ // Wraps and hides input textarea
8640
+ var div = this.wrapper = hiddenTextarea()
8641
+ // The semihidden textarea that is focused when the editor is
8642
+ // focused, and receives input.
8643
+ var te = this.textarea = div.firstChild
8644
+ display.wrapper.insertBefore(div, display.wrapper.firstChild)
8645
+
8646
+ // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
8647
+ if (ios) { te.style.width = "0px" }
8648
+
8649
+ on(te, "input", function () {
8650
+ if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null }
8651
+ input.poll()
8652
+ })
8653
+
8654
+ on(te, "paste", function (e) {
8655
+ if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
8656
+
8657
+ cm.state.pasteIncoming = true
8658
+ input.fastPoll()
8659
+ })
8660
+
8661
+ function prepareCopyCut(e) {
8662
+ if (signalDOMEvent(cm, e)) { return }
8663
+ if (cm.somethingSelected()) {
8664
+ setLastCopied({lineWise: false, text: cm.getSelections()})
8665
+ if (input.inaccurateSelection) {
8666
+ input.prevInput = ""
8667
+ input.inaccurateSelection = false
8668
+ te.value = lastCopied.text.join("\n")
8669
+ selectInput(te)
8670
+ }
8671
+ } else if (!cm.options.lineWiseCopyCut) {
8672
+ return
8673
+ } else {
8674
+ var ranges = copyableRanges(cm)
8675
+ setLastCopied({lineWise: true, text: ranges.text})
8676
+ if (e.type == "cut") {
8677
+ cm.setSelections(ranges.ranges, null, sel_dontScroll)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8678
  } else {
8679
+ input.prevInput = ""
8680
+ te.value = ranges.text.join("\n")
8681
+ selectInput(te)
8682
+ }
8683
+ }
8684
+ if (e.type == "cut") { cm.state.cutIncoming = true }
8685
+ }
8686
+ on(te, "cut", prepareCopyCut)
8687
+ on(te, "copy", prepareCopyCut)
8688
+
8689
+ on(display.scroller, "paste", function (e) {
8690
+ if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }
8691
+ cm.state.pasteIncoming = true
8692
+ input.focus()
8693
+ })
8694
+
8695
+ // Prevent normal selection in the editor (we handle our own)
8696
+ on(display.lineSpace, "selectstart", function (e) {
8697
+ if (!eventInWidget(display, e)) { e_preventDefault(e) }
8698
+ })
8699
+
8700
+ on(te, "compositionstart", function () {
8701
+ var start = cm.getCursor("from")
8702
+ if (input.composing) { input.composing.range.clear() }
8703
+ input.composing = {
8704
+ start: start,
8705
+ range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
8706
+ }
8707
+ })
8708
+ on(te, "compositionend", function () {
8709
+ if (input.composing) {
8710
+ input.poll()
8711
+ input.composing.range.clear()
8712
+ input.composing = null
8713
+ }
8714
+ })
8715
+ };
8716
+
8717
+ TextareaInput.prototype.prepareSelection = function () {
8718
+ // Redraw the selection and/or cursor
8719
+ var cm = this.cm, display = cm.display, doc = cm.doc
8720
+ var result = prepareSelection(cm)
8721
+
8722
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
8723
+ if (cm.options.moveInputWithCursor) {
8724
+ var headPos = cursorCoords(cm, doc.sel.primary().head, "div")
8725
+ var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect()
8726
+ result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
8727
+ headPos.top + lineOff.top - wrapOff.top))
8728
+ result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
8729
+ headPos.left + lineOff.left - wrapOff.left))
8730
+ }
8731
+
8732
+ return result
8733
+ };
8734
+
8735
+ TextareaInput.prototype.showSelection = function (drawn) {
8736
+ var cm = this.cm, display = cm.display
8737
+ removeChildrenAndAdd(display.cursorDiv, drawn.cursors)
8738
+ removeChildrenAndAdd(display.selectionDiv, drawn.selection)
8739
+ if (drawn.teTop != null) {
8740
+ this.wrapper.style.top = drawn.teTop + "px"
8741
+ this.wrapper.style.left = drawn.teLeft + "px"
8742
+ }
8743
+ };
8744
+
8745
+ // Reset the input to correspond to the selection (or to be empty,
8746
+ // when not typing and nothing is selected)
8747
+ TextareaInput.prototype.reset = function (typing) {
8748
+ if (this.contextMenuPending) { return }
8749
+ var minimal, selected, cm = this.cm, doc = cm.doc
8750
+ if (cm.somethingSelected()) {
8751
+ this.prevInput = ""
8752
+ var range = doc.sel.primary()
8753
+ minimal = hasCopyEvent &&
8754
+ (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000)
8755
+ var content = minimal ? "-" : selected || cm.getSelection()
8756
+ this.textarea.value = content
8757
+ if (cm.state.focused) { selectInput(this.textarea) }
8758
+ if (ie && ie_version >= 9) { this.hasSelection = content }
8759
+ } else if (!typing) {
8760
+ this.prevInput = this.textarea.value = ""
8761
+ if (ie && ie_version >= 9) { this.hasSelection = null }
8762
+ }
8763
+ this.inaccurateSelection = minimal
8764
+ };
8765
+
8766
+ TextareaInput.prototype.getField = function () { return this.textarea };
8767
+
8768
+ TextareaInput.prototype.supportsTouch = function () { return false };
8769
+
8770
+ TextareaInput.prototype.focus = function () {
8771
+ if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
8772
+ try { this.textarea.focus() }
8773
+ catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
8774
+ }
8775
+ };
8776
+
8777
+ TextareaInput.prototype.blur = function () { this.textarea.blur() };
8778
+
8779
+ TextareaInput.prototype.resetPosition = function () {
8780
+ this.wrapper.style.top = this.wrapper.style.left = 0
8781
+ };
8782
+
8783
+ TextareaInput.prototype.receivedFocus = function () { this.slowPoll() };
8784
+
8785
+ // Poll for input changes, using the normal rate of polling. This
8786
+ // runs as long as the editor is focused.
8787
+ TextareaInput.prototype.slowPoll = function () {
8788
+ var this$1 = this;
8789
+
8790
+ if (this.pollingFast) { return }
8791
+ this.polling.set(this.cm.options.pollInterval, function () {
8792
+ this$1.poll()
8793
+ if (this$1.cm.state.focused) { this$1.slowPoll() }
8794
+ })
8795
+ };
8796
+
8797
+ // When an event has just come in that is likely to add or change
8798
+ // something in the input textarea, we poll faster, to ensure that
8799
+ // the change appears on the screen quickly.
8800
+ TextareaInput.prototype.fastPoll = function () {
8801
+ var missed = false, input = this
8802
+ input.pollingFast = true
8803
+ function p() {
8804
+ var changed = input.poll()
8805
+ if (!changed && !missed) {missed = true; input.polling.set(60, p)}
8806
+ else {input.pollingFast = false; input.slowPoll()}
8807
+ }
8808
+ input.polling.set(20, p)
8809
+ };
8810
+
8811
+ // Read input from the textarea, and update the document to match.
8812
+ // When something is selected, it is present in the textarea, and
8813
+ // selected (unless it is huge, in which case a placeholder is
8814
+ // used). When nothing is selected, the cursor sits after previously
8815
+ // seen text (can be empty), which is stored in prevInput (we must
8816
+ // not reset the textarea when typing, because that breaks IME).
8817
+ TextareaInput.prototype.poll = function () {
8818
+ var this$1 = this;
8819
+
8820
+ var cm = this.cm, input = this.textarea, prevInput = this.prevInput
8821
+ // Since this is called a *lot*, try to bail out as cheaply as
8822
+ // possible when it is clear that nothing happened. hasSelection
8823
+ // will be the case when there is a lot of text in the textarea,
8824
+ // in which case reading its value would be expensive.
8825
+ if (this.contextMenuPending || !cm.state.focused ||
8826
+ (hasSelection(input) && !prevInput && !this.composing) ||
8827
+ cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
8828
+ { return false }
8829
+
8830
+ var text = input.value
8831
+ // If nothing changed, bail.
8832
+ if (text == prevInput && !cm.somethingSelected()) { return false }
8833
+ // Work around nonsensical selection resetting in IE9/10, and
8834
+ // inexplicable appearance of private area unicode characters on
8835
+ // some key combos in Mac (#2689).
8836
+ if (ie && ie_version >= 9 && this.hasSelection === text ||
8837
+ mac && /[\uf700-\uf7ff]/.test(text)) {
8838
+ cm.display.input.reset()
8839
+ return false
8840
+ }
8841
+
8842
+ if (cm.doc.sel == cm.display.selForContextMenu) {
8843
+ var first = text.charCodeAt(0)
8844
+ if (first == 0x200b && !prevInput) { prevInput = "\u200b" }
8845
+ if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") }
8846
+ }
8847
+ // Find the part of the input that is actually new
8848
+ var same = 0, l = Math.min(prevInput.length, text.length)
8849
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same }
8850
+
8851
+ runInOp(cm, function () {
8852
+ applyTextInput(cm, text.slice(same), prevInput.length - same,
8853
+ null, this$1.composing ? "*compose" : null)
8854
+
8855
+ // Don't leave long text in the textarea, since it makes further polling slow
8856
+ if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = "" }
8857
+ else { this$1.prevInput = text }
8858
+
8859
+ if (this$1.composing) {
8860
+ this$1.composing.range.clear()
8861
+ this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"),
8862
+ {className: "CodeMirror-composing"})
8863
+ }
8864
+ })
8865
+ return true
8866
+ };
8867
+
8868
+ TextareaInput.prototype.ensurePolled = function () {
8869
+ if (this.pollingFast && this.poll()) { this.pollingFast = false }
8870
+ };
8871
+
8872
+ TextareaInput.prototype.onKeyPress = function () {
8873
+ if (ie && ie_version >= 9) { this.hasSelection = null }
8874
+ this.fastPoll()
8875
+ };
8876
+
8877
+ TextareaInput.prototype.onContextMenu = function (e) {
8878
+ var input = this, cm = input.cm, display = cm.display, te = input.textarea
8879
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop
8880
+ if (!pos || presto) { return } // Opera is difficult.
8881
+
8882
+ // Reset the current text selection only if the click is done outside of the selection
8883
+ // and 'resetSelectionOnContextMenu' option is true.
8884
+ var reset = cm.options.resetSelectionOnContextMenu
8885
+ if (reset && cm.doc.sel.contains(pos) == -1)
8886
+ { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll) }
8887
+
8888
+ var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText
8889
+ input.wrapper.style.cssText = "position: absolute"
8890
+ var wrapperBox = input.wrapper.getBoundingClientRect()
8891
+ te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"
8892
+ var oldScrollY
8893
+ if (webkit) { oldScrollY = window.scrollY } // Work around Chrome issue (#2712)
8894
+ display.input.focus()
8895
+ if (webkit) { window.scrollTo(null, oldScrollY) }
8896
+ display.input.reset()
8897
+ // Adds "Select all" to context menu in FF
8898
+ if (!cm.somethingSelected()) { te.value = input.prevInput = " " }
8899
+ input.contextMenuPending = true
8900
+ display.selForContextMenu = cm.doc.sel
8901
+ clearTimeout(display.detectingSelectAll)
8902
+
8903
+ // Select-all will be greyed out if there's nothing to select, so
8904
+ // this adds a zero-width space so that we can later check whether
8905
+ // it got selected.
8906
+ function prepareSelectAllHack() {
8907
+ if (te.selectionStart != null) {
8908
+ var selected = cm.somethingSelected()
8909
+ var extval = "\u200b" + (selected ? te.value : "")
8910
+ te.value = "\u21da" // Used to catch context-menu undo
8911
+ te.value = extval
8912
+ input.prevInput = selected ? "" : "\u200b"
8913
+ te.selectionStart = 1; te.selectionEnd = extval.length
8914
+ // Re-set this, in case some other handler touched the
8915
+ // selection in the meantime.
8916
+ display.selForContextMenu = cm.doc.sel
8917
+ }
8918
+ }
8919
+ function rehide() {
8920
+ input.contextMenuPending = false
8921
+ input.wrapper.style.cssText = oldWrapperCSS
8922
+ te.style.cssText = oldCSS
8923
+ if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos) }
8924
+
8925
+ // Try to detect the user choosing select-all
8926
+ if (te.selectionStart != null) {
8927
+ if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack() }
8928
+ var i = 0, poll = function () {
8929
+ if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
8930
+ te.selectionEnd > 0 && input.prevInput == "\u200b")
8931
+ { operation(cm, selectAll)(cm) }
8932
+ else if (i++ < 10) { display.detectingSelectAll = setTimeout(poll, 500) }
8933
+ else { display.input.reset() }
8934
+ }
8935
+ display.detectingSelectAll = setTimeout(poll, 200)
8936
+ }
8937
+ }
8938
+
8939
+ if (ie && ie_version >= 9) { prepareSelectAllHack() }
8940
+ if (captureRightClick) {
8941
+ e_stop(e)
8942
+ var mouseup = function () {
8943
+ off(window, "mouseup", mouseup)
8944
+ setTimeout(rehide, 20)
8945
+ }
8946
+ on(window, "mouseup", mouseup)
8947
+ } else {
8948
+ setTimeout(rehide, 50)
8949
+ }
8950
+ };
8951
+
8952
+ TextareaInput.prototype.readOnlyChanged = function (val) {
8953
+ if (!val) { this.reset() }
8954
+ };
8955
+
8956
+ TextareaInput.prototype.setUneditable = function () {};
8957
+
8958
+ TextareaInput.prototype.needsContentAttribute = false
8959
+
8960
+ function fromTextArea(textarea, options) {
8961
+ options = options ? copyObj(options) : {}
8962
+ options.value = textarea.value
8963
+ if (!options.tabindex && textarea.tabIndex)
8964
+ { options.tabindex = textarea.tabIndex }
8965
+ if (!options.placeholder && textarea.placeholder)
8966
+ { options.placeholder = textarea.placeholder }
8967
+ // Set autofocus to true if this textarea is focused, or if it has
8968
+ // autofocus and no other element is focused.
8969
+ if (options.autofocus == null) {
8970
+ var hasFocus = activeElt()
8971
+ options.autofocus = hasFocus == textarea ||
8972
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body
8973
+ }
8974
+
8975
+ function save() {textarea.value = cm.getValue()}
8976
+
8977
+ var realSubmit
8978
+ if (textarea.form) {
8979
+ on(textarea.form, "submit", save)
8980
+ // Deplorable hack to make the submit method do the right thing.
8981
+ if (!options.leaveSubmitMethodAlone) {
8982
+ var form = textarea.form
8983
+ realSubmit = form.submit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8984
  try {
8985
+ var wrappedSubmit = form.submit = function () {
8986
+ save()
8987
+ form.submit = realSubmit
8988
+ form.submit()
8989
+ form.submit = wrappedSubmit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8990
  }
8991
+ } catch(e) {}
8992
+ }
8993
+ }
8994
+
8995
+ options.finishInit = function (cm) {
8996
+ cm.save = save
8997
+ cm.getTextArea = function () { return textarea; }
8998
+ cm.toTextArea = function () {
8999
+ cm.toTextArea = isNaN // Prevent this from being ran twice
9000
+ save()
9001
+ textarea.parentNode.removeChild(cm.getWrapperElement())
9002
+ textarea.style.display = ""
9003
+ if (textarea.form) {
9004
+ off(textarea.form, "submit", save)
9005
+ if (typeof textarea.form.submit == "function")
9006
+ { textarea.form.submit = realSubmit }
9007
+ }
9008
+ }
9009
+ }
9010
+
9011
+ textarea.style.display = "none"
9012
+ var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },
9013
+ options)
9014
+ return cm
9015
+ }
9016
+
9017
+ function addLegacyProps(CodeMirror) {
9018
+ CodeMirror.off = off
9019
+ CodeMirror.on = on
9020
+ CodeMirror.wheelEventPixels = wheelEventPixels
9021
+ CodeMirror.Doc = Doc
9022
+ CodeMirror.splitLines = splitLinesAuto
9023
+ CodeMirror.countColumn = countColumn
9024
+ CodeMirror.findColumn = findColumn
9025
+ CodeMirror.isWordChar = isWordCharBasic
9026
+ CodeMirror.Pass = Pass
9027
+ CodeMirror.signal = signal
9028
+ CodeMirror.Line = Line
9029
+ CodeMirror.changeEnd = changeEnd
9030
+ CodeMirror.scrollbarModel = scrollbarModel
9031
+ CodeMirror.Pos = Pos
9032
+ CodeMirror.cmpPos = cmp
9033
+ CodeMirror.modes = modes
9034
+ CodeMirror.mimeModes = mimeModes
9035
+ CodeMirror.resolveMode = resolveMode
9036
+ CodeMirror.getMode = getMode
9037
+ CodeMirror.modeExtensions = modeExtensions
9038
+ CodeMirror.extendMode = extendMode
9039
+ CodeMirror.copyState = copyState
9040
+ CodeMirror.startState = startState
9041
+ CodeMirror.innerMode = innerMode
9042
+ CodeMirror.commands = commands
9043
+ CodeMirror.keyMap = keyMap
9044
+ CodeMirror.keyName = keyName
9045
+ CodeMirror.isModifierKey = isModifierKey
9046
+ CodeMirror.lookupKey = lookupKey
9047
+ CodeMirror.normalizeKeyMap = normalizeKeyMap
9048
+ CodeMirror.StringStream = StringStream
9049
+ CodeMirror.SharedTextMarker = SharedTextMarker
9050
+ CodeMirror.TextMarker = TextMarker
9051
+ CodeMirror.LineWidget = LineWidget
9052
+ CodeMirror.e_preventDefault = e_preventDefault
9053
+ CodeMirror.e_stopPropagation = e_stopPropagation
9054
+ CodeMirror.e_stop = e_stop
9055
+ CodeMirror.addClass = addClass
9056
+ CodeMirror.contains = contains
9057
+ CodeMirror.rmClass = rmClass
9058
+ CodeMirror.keyNames = keyNames
9059
+ }
9060
+
9061
+ // EDITOR CONSTRUCTOR
9062
+
9063
+ defineOptions(CodeMirror)
9064
+
9065
+ addEditorMethods(CodeMirror)
9066
+
9067
+ // Set up methods on CodeMirror's prototype to redirect to the editor's document.
9068
+ var dontDelegate = "iter insert remove copy getEditor constructor".split(" ")
9069
+ for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
9070
+ { CodeMirror.prototype[prop] = (function(method) {
9071
+ return function() {return method.apply(this.doc, arguments)}
9072
+ })(Doc.prototype[prop]) } }
9073
+
9074
+ eventMixin(Doc)
9075
+
9076
+ // INPUT HANDLING
9077
+
9078
+ CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}
9079
+
9080
+ // MODE DEFINITION AND QUERYING
9081
+
9082
+ // Extra arguments are stored as the mode's dependencies, which is
9083
+ // used by (legacy) mechanisms like loadmode.js to automatically
9084
+ // load a mode. (Preferred mechanism is the require/define calls.)
9085
+ CodeMirror.defineMode = function(name/*, mode, …*/) {
9086
+ if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name }
9087
+ defineMode.apply(this, arguments)
9088
+ }
9089
+
9090
+ CodeMirror.defineMIME = defineMIME
9091
+
9092
+ // Minimal default mode.
9093
+ CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); })
9094
+ CodeMirror.defineMIME("text/plain", "null")
9095
+
9096
+ // EXTENSIONS
9097
+
9098
+ CodeMirror.defineExtension = function (name, func) {
9099
+ CodeMirror.prototype[name] = func
9100
+ }
9101
+ CodeMirror.defineDocExtension = function (name, func) {
9102
+ Doc.prototype[name] = func
9103
+ }
9104
+
9105
+ CodeMirror.fromTextArea = fromTextArea
9106
+
9107
+ addLegacyProps(CodeMirror)
9108
+
9109
+ CodeMirror.version = "5.23.0"
9110
+
9111
+ return CodeMirror;
9112
+
9113
+ })));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/codemirror/lib/codemirror.min.js CHANGED
@@ -1,5 +1,5 @@
1
- !function(e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else{if("function"==typeof define&&define.amd)return define([],e);(this||window).CodeMirror=e()}}(function(){"use strict";function e(r,n){if(!(this instanceof e))return new e(r,n);this.options=n=n?zi(n):{},zi(Jo,n,!1),d(n);var i=n.value;"string"==typeof i&&(i=new Sl(i,n.mode,null,n.lineSeparator)),this.doc=i;var o=new e.inputStyles[n.inputStyle](this),l=this.display=new t(r,i,o);l.wrapper.CodeMirror=this,u(this),s(this),n.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),n.autofocus&&!Wo&&l.input.focus(),m(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,selectingText:!1,draggingText:!1,highlight:new Ai,keySeq:null,specialChars:null};var a=this;bo&&wo<11&&setTimeout(function(){a.display.input.reset(!0)},20),Ut(this),$i(),wt(this),this.curOp.forceUpdate=!0,qn(this,i),n.autofocus&&!Wo||a.hasFocus()?setTimeout(Fi(vr,this),20):mr(this);for(var c in el)el.hasOwnProperty(c)&&el[c](this,n[c],tl);C(this),n.finishInit&&n.finishInit(this);for(var h=0;h<ol.length;++h)ol[h](this);Ct(this),xo&&n.lineWrapping&&"optimizelegibility"==getComputedStyle(l.lineDiv).textRendering&&(l.lineDiv.style.textRendering="auto")}function t(e,t,r){var n=this;this.input=r,n.scrollbarFiller=Ui("div",null,"CodeMirror-scrollbar-filler"),n.scrollbarFiller.setAttribute("cm-not-content","true"),n.gutterFiller=Ui("div",null,"CodeMirror-gutter-filler"),n.gutterFiller.setAttribute("cm-not-content","true"),n.lineDiv=Ui("div",null,"CodeMirror-code"),n.selectionDiv=Ui("div",null,null,"position: relative; z-index: 1"),n.cursorDiv=Ui("div",null,"CodeMirror-cursors"),n.measure=Ui("div",null,"CodeMirror-measure"),n.lineMeasure=Ui("div",null,"CodeMirror-measure"),n.lineSpace=Ui("div",[n.measure,n.lineMeasure,n.selectionDiv,n.cursorDiv,n.lineDiv],null,"position: relative; outline: none"),n.mover=Ui("div",[Ui("div",[n.lineSpace],"CodeMirror-lines")],null,"position: relative"),n.sizer=Ui("div",[n.mover],"CodeMirror-sizer"),n.sizerWidth=null,n.heightForcer=Ui("div",null,null,"position: absolute; height: "+Pl+"px; width: 1px;"),n.gutters=Ui("div",null,"CodeMirror-gutters"),n.lineGutter=null,n.scroller=Ui("div",[n.sizer,n.heightForcer,n.gutters],"CodeMirror-scroll"),n.scroller.setAttribute("tabIndex","-1"),n.wrapper=Ui("div",[n.scrollbarFiller,n.gutterFiller,n.scroller],"CodeMirror"),bo&&wo<8&&(n.gutters.style.zIndex=-1,n.scroller.style.paddingRight=0),xo||vo&&Wo||(n.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(n.wrapper):e(n.wrapper)),n.viewFrom=n.viewTo=t.first,n.reportedViewFrom=n.reportedViewTo=t.first,n.view=[],n.renderedView=null,n.externalMeasured=null,n.viewOffset=0,n.lastWrapHeight=n.lastWrapWidth=0,n.updateLineNumbers=null,n.nativeBarWidth=n.barHeight=n.barWidth=0,n.scrollbarsClipped=!1,n.lineNumWidth=n.lineNumInnerWidth=n.lineNumChars=null,n.alignWidgets=!1,n.cachedCharWidth=n.cachedTextHeight=n.cachedPaddingH=null,n.maxLine=null,n.maxLineLength=0,n.maxLineChanged=!1,n.wheelDX=n.wheelDY=n.wheelStartX=n.wheelStartY=null,n.shift=!1,n.selForContextMenu=null,n.activeTouch=null,r.init(n)}function r(t){t.doc.mode=e.getMode(t.options,t.doc.modeOption),n(t)}function n(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.frontier=e.doc.first,Re(e,100),e.state.modeGen++,e.curOp&&Et(e)}function i(e){e.options.lineWrapping?(Zl(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(ql(e.display.wrapper,"CodeMirror-wrap"),f(e)),l(e),Et(e),st(e),setTimeout(function(){y(e)},100)}function o(e){var t=yt(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/bt(e.display)-3);return function(i){if(Cn(e.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l<i.widgets.length;l++)i.widgets[l].height&&(o+=i.widgets[l].height);return r?o+(Math.ceil(i.text.length/n)||1)*t:o+t}}function l(e){var t=e.doc,r=o(e);t.iter(function(e){var t=r(e);t!=e.height&&ei(e,t)})}function s(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),st(e)}function a(e){u(e),Et(e),setTimeout(function(){x(e)},20)}function u(e){var t=e.display.gutters,r=e.options.gutters;Vi(t);for(var n=0;n<r.length;++n){var i=r[n],o=t.appendChild(Ui("div",null,"CodeMirror-gutter "+i));"CodeMirror-linenumbers"==i&&(e.display.lineGutter=o,o.style.width=(e.display.lineNumWidth||1)+"px")}t.style.display=n?"":"none",c(e)}function c(e){var t=e.display.gutters.offsetWidth;e.display.sizer.style.marginLeft=t+"px"}function h(e){if(0==e.height)return 0;for(var t,r=e.text.length,n=e;t=gn(n);){var i=t.find(0,!0);n=i.from.line,r+=i.from.ch-i.to.ch}for(n=e;t=vn(n);){var i=t.find(0,!0);r-=n.text.length-i.from.ch,n=i.to.line,r+=n.text.length-i.to.ch}return r}function f(e){var t=e.display,r=e.doc;t.maxLine=Zn(r,r.first),t.maxLineLength=h(t.maxLine),t.maxLineChanged=!0,r.iter(function(e){var r=h(e);r>t.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)})}function d(e){var t=Hi(e.gutters,"CodeMirror-linenumbers");t==-1&&e.lineNumbers?e.gutters=e.gutters.concat(["CodeMirror-linenumbers"]):t>-1&&!e.lineNumbers&&(e.gutters=e.gutters.slice(0),e.gutters.splice(t,1))}function p(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Ke(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+Xe(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}function g(e,t,r){this.cm=r;var n=this.vert=Ui("div",[Ui("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=Ui("div",[Ui("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");e(n),e(i),Wl(n,"scroll",function(){n.clientHeight&&t(n.scrollTop,"vertical")}),Wl(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,bo&&wo<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}function v(){}function m(t){t.display.scrollbars&&(t.display.scrollbars.clear(),t.display.scrollbars.addClass&&ql(t.display.wrapper,t.display.scrollbars.addClass)),t.display.scrollbars=new e.scrollbarModel[t.options.scrollbarStyle](function(e){t.display.wrapper.insertBefore(e,t.display.scrollbarFiller),Wl(e,"mousedown",function(){t.state.focused&&setTimeout(function(){t.display.input.focus()},0)}),e.setAttribute("cm-not-content","true")},function(e,r){"horizontal"==r?ir(t,e):nr(t,e)},t),t.display.scrollbars.addClass&&Zl(t.display.wrapper,t.display.scrollbars.addClass)}function y(e,t){t||(t=p(e));var r=e.display.barWidth,n=e.display.barHeight;b(e,t);for(var i=0;i<4&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&O(e),b(e,p(e)),r=e.display.barWidth,n=e.display.barHeight}function b(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}function w(e,t,r){var n=r&&null!=r.top?Math.max(0,r.top):e.scroller.scrollTop;n=Math.floor(n-Ve(e));var i=r&&null!=r.bottom?r.bottom:n+e.wrapper.clientHeight,o=ri(t,n),l=ri(t,i);if(r&&r.ensure){var s=r.ensure.from.line,a=r.ensure.to.line;s<o?(o=s,l=ri(t,ni(Zn(t,s))+e.wrapper.clientHeight)):Math.min(a,t.lastLine())>=l&&(o=ri(t,ni(Zn(t,a))-e.wrapper.clientHeight),l=a)}return{from:o,to:Math.max(l,o+1)}}function x(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=L(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",l=0;l<r.length;l++)if(!r[l].hidden){e.options.fixedGutter&&r[l].gutter&&(r[l].gutter.style.left=o);var s=r[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=n+i+"px")}}function C(e){if(!e.options.lineNumbers)return!1;var t=e.doc,r=S(e.options,t.first+t.size-1),n=e.display;if(r.length!=n.lineNumChars){var i=n.measure.appendChild(Ui("div",[Ui("div",r)],"CodeMirror-linenumber CodeMirror-gutter-elt")),o=i.firstChild.offsetWidth,l=i.offsetWidth-o;return n.lineGutter.style.width="",n.lineNumInnerWidth=Math.max(o,n.lineGutter.offsetWidth-l)+1,n.lineNumWidth=n.lineNumInnerWidth+l,n.lineNumChars=n.lineNumInnerWidth?r.length:-1,n.lineGutter.style.width=n.lineNumWidth+"px",c(e),!0}return!1}function S(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function L(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function T(e,t,r){var n=e.display;this.viewport=t,this.visible=w(n,e.doc,t),this.editorIsHidden=!n.wrapper.offsetWidth,this.wrapperHeight=n.wrapper.clientHeight,this.wrapperWidth=n.wrapper.clientWidth,this.oldDisplayWidth=Ye(e),this.force=r,this.dims=H(e),this.events=[]}function k(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=Xe(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=Xe(e)+"px",t.scrollbarsClipped=!0)}function M(e,t){var r=e.display,n=e.doc;if(t.editorIsHidden)return zt(e),!1;if(!t.force&&t.visible.from>=r.viewFrom&&t.visible.to<=r.viewTo&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&0==Gt(e))return!1;C(e)&&(zt(e),t.dims=H(e));var i=n.first+n.size,o=Math.max(t.visible.from-e.options.viewportMargin,n.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);r.viewFrom<o&&o-r.viewFrom<20&&(o=Math.max(n.first,r.viewFrom)),r.viewTo>l&&r.viewTo-l<20&&(l=Math.min(i,r.viewTo)),Io&&(o=wn(e.doc,o),l=xn(e.doc,l));var s=o!=r.viewFrom||l!=r.viewTo||r.lastWrapHeight!=t.wrapperHeight||r.lastWrapWidth!=t.wrapperWidth;Bt(e,o,l),r.viewOffset=ni(Zn(e.doc,r.viewFrom)),e.display.mover.style.top=r.viewOffset+"px";var a=Gt(e);if(!s&&0==a&&!t.force&&r.renderedView==r.view&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo))return!1;var u=ji();return a>4&&(r.lineDiv.style.display="none"),P(e,r.updateLineNumbers,t.dims),a>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,u&&ji()!=u&&u.offsetHeight&&u.focus(),Vi(r.cursorDiv),Vi(r.selectionDiv),r.gutters.style.height=r.sizer.style.minHeight=0,s&&(r.lastWrapHeight=t.wrapperHeight,r.lastWrapWidth=t.wrapperWidth,Re(e,400)),r.updateLineNumbers=null,!0}function N(e,t){for(var r=t.viewport,n=!0;(n&&e.options.lineWrapping&&t.oldDisplayWidth!=Ye(e)||(r&&null!=r.top&&(r={top:Math.min(e.doc.height+Ke(e.display)-_e(e),r.top)}),t.visible=w(e.display,e.doc,r),!(t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)))&&M(e,t);n=!1){O(e);var i=p(e);Pe(e),A(e,i),y(e,i)}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function W(e,t){var r=new T(e,t);if(M(e,r)){O(e),N(e,r);var n=p(e);Pe(e),A(e,n),y(e,n),r.finish()}}function A(e,t){e.display.sizer.style.minHeight=t.docHeight+"px";var r=t.docHeight+e.display.barHeight;e.display.heightForcer.style.top=r+"px",e.display.gutters.style.height=Math.max(r+Xe(e),t.clientHeight)+"px"}function O(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=0;n<t.view.length;n++){var i,o=t.view[n];if(!o.hidden){if(bo&&wo<8){var l=o.node.offsetTop+o.node.offsetHeight;i=l-r,r=l}else{var s=o.node.getBoundingClientRect();i=s.bottom-s.top}var a=o.line.height-i;if(i<2&&(i=yt(t)),(a>.001||a<-.001)&&(ei(o.line,i),D(o.line),o.rest))for(var u=0;u<o.rest.length;u++)D(o.rest[u])}}}function D(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t)e.widgets[t].height=e.widgets[t].node.parentNode.offsetHeight}function H(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l)r[e.options.gutters[l]]=o.offsetLeft+o.clientLeft+i,n[e.options.gutters[l]]=o.clientWidth;return{fixedPos:L(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function P(e,t,r){function n(t){var r=t.nextSibling;return xo&&Ao&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var i=e.display,o=e.options.lineNumbers,l=i.lineDiv,s=l.firstChild,a=i.view,u=i.viewFrom,c=0;c<a.length;c++){var h=a[c];if(h.hidden);else if(h.node&&h.node.parentNode==l){for(;s!=h.node;)s=n(s);var f=o&&null!=t&&t<=u&&h.lineNumber;h.changes&&(Hi(h.changes,"gutter")>-1&&(f=!1),E(e,h,u,r)),f&&(Vi(h.lineNumber),h.lineNumber.appendChild(document.createTextNode(S(e.options,u)))),s=h.node.nextSibling}else{var d=V(e,h,u,r);l.insertBefore(d,s)}u+=h.size}for(;s;)s=n(s)}function E(e,t,r,n){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?R(e,t):"gutter"==o?G(e,t,r,n):"class"==o?B(t):"widget"==o&&U(e,t,n)}t.changes=null}function I(e){return e.node==e.text&&(e.node=Ui("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),bo&&wo<8&&(e.node.style.zIndex=2)),e.node}function z(e){var t=e.bgClass?e.bgClass+" "+(e.line.bgClass||""):e.line.bgClass;if(t&&(t+=" CodeMirror-linebackground"),e.background)t?e.background.className=t:(e.background.parentNode.removeChild(e.background),e.background=null);else if(t){var r=I(e);e.background=r.insertBefore(Ui("div",null,t),r.firstChild)}}function F(e,t){var r=e.display.externalMeasured;return r&&r.line==t.line?(e.display.externalMeasured=null,t.measure=r.measure,r.built):Fn(e,t)}function R(e,t){var r=t.text.className,n=F(e,t);t.text==t.node&&(t.node=n.pre),t.text.parentNode.replaceChild(n.pre,t.text),t.text=n.pre,n.bgClass!=t.bgClass||n.textClass!=t.textClass?(t.bgClass=n.bgClass,t.textClass=n.textClass,B(t)):r&&(t.text.className=r)}function B(e){z(e),e.line.wrapClass?I(e).className=e.line.wrapClass:e.node!=e.text&&(e.node.className="");var t=e.textClass?e.textClass+" "+(e.line.textClass||""):e.line.textClass;e.text.className=t||""}function G(e,t,r,n){if(t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null),t.gutterBackground&&(t.node.removeChild(t.gutterBackground),t.gutterBackground=null),t.line.gutterClass){var i=I(t);t.gutterBackground=Ui("div",null,"CodeMirror-gutter-background "+t.line.gutterClass,"left: "+(e.options.fixedGutter?n.fixedPos:-n.gutterTotalWidth)+"px; width: "+n.gutterTotalWidth+"px"),i.insertBefore(t.gutterBackground,t.text)}var o=t.line.gutterMarkers;if(e.options.lineNumbers||o){var i=I(t),l=t.gutter=Ui("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?n.fixedPos:-n.gutterTotalWidth)+"px");if(e.display.input.setUneditable(l),i.insertBefore(l,t.text),t.line.gutterClass&&(l.className+=" "+t.line.gutterClass),!e.options.lineNumbers||o&&o["CodeMirror-linenumbers"]||(t.lineNumber=l.appendChild(Ui("div",S(e.options,r),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+n.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),o)for(var s=0;s<e.options.gutters.length;++s){var a=e.options.gutters[s],u=o.hasOwnProperty(a)&&o[a];u&&l.appendChild(Ui("div",[u],"CodeMirror-gutter-elt","left: "+n.gutterLeft[a]+"px; width: "+n.gutterWidth[a]+"px"))}}}function U(e,t,r){t.alignable&&(t.alignable=null);for(var n,i=t.node.firstChild;i;i=n){var n=i.nextSibling;"CodeMirror-linewidget"==i.className&&t.node.removeChild(i)}K(e,t,r)}function V(e,t,r,n){var i=F(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),B(t),G(e,t,r,n),K(e,t,n),t.node}function K(e,t,r){if(j(e,t.line,t,r,!0),t.rest)for(var n=0;n<t.rest.length;n++)j(e,t.rest[n],t,r,!1)}function j(e,t,r,n,i){if(t.widgets)for(var o=I(r),l=0,s=t.widgets;l<s.length;++l){var a=s[l],u=Ui("div",[a.node],"CodeMirror-linewidget");a.handleMouseEvents||u.setAttribute("cm-ignore-events","true"),X(a,u,r,n),e.display.input.setUneditable(u),i&&a.above?o.insertBefore(u,r.gutter||r.text):o.appendChild(u),Li(a,"redraw")}}function X(e,t,r,n){if(e.noHScroll){(r.alignable||(r.alignable=[])).push(t);var i=n.wrapperWidth;t.style.left=n.fixedPos+"px",e.coverGutter||(i-=n.gutterTotalWidth,t.style.paddingLeft=n.gutterTotalWidth+"px"),t.style.width=i+"px"}e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-n.gutterTotalWidth+"px"))}function Y(e){return zo(e.line,e.ch)}function _(e,t){return Fo(e,t)<0?t:e}function $(e,t){return Fo(e,t)<0?e:t}function q(e){e.state.focused||(e.display.input.focus(),vr(e))}function Z(e,t,r,n,i){var o=e.doc;e.display.shift=!1,n||(n=o.sel);var l=e.state.pasteIncoming||"paste"==i,s=o.splitLines(t),a=null;if(l&&n.ranges.length>1)if(Ro&&Ro.join("\n")==t){if(n.ranges.length%Ro.length==0){a=[];for(var u=0;u<Ro.length;u++)a.push(o.splitLines(Ro[u]))}}else s.length==n.ranges.length&&(a=Pi(s,function(e){return[e]}));for(var u=n.ranges.length-1;u>=0;u--){var c=n.ranges[u],h=c.from(),f=c.to();c.empty()&&(r&&r>0?h=zo(h.line,h.ch-r):e.state.overwrite&&!l&&(f=zo(f.line,Math.min(Zn(o,f.line).text.length,f.ch+Di(s).length))));var d=e.curOp.updateInput,p={from:h,to:f,text:a?a[u%a.length]:s,origin:i||(l?"paste":e.state.cutIncoming?"cut":"+input")};Tr(e.doc,p),Li(e,"inputRead",e,p)}t&&!l&&J(e,t),zr(e),e.curOp.updateInput=d,e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=!1}function Q(e,t){var r=e.clipboardData&&e.clipboardData.getData("text/plain");if(r)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||Wt(t,function(){Z(t,r,0,null,"paste")}),!0}function J(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var r=e.doc.sel,n=r.ranges.length-1;n>=0;n--){var i=r.ranges[n];if(!(i.head.ch>100||n&&r.ranges[n-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s<o.electricChars.length;s++)if(t.indexOf(o.electricChars.charAt(s))>-1){l=Rr(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Zn(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=Rr(e,i.head.line,"smart"));l&&Li(e,"electricInput",e,i.head.line)}}}function ee(e){for(var t=[],r=[],n=0;n<e.doc.sel.ranges.length;n++){var i=e.doc.sel.ranges[n].head.line,o={anchor:zo(i,0),head:zo(i+1,0)};r.push(o),t.push(e.getRange(o.anchor,o.head))}return{text:t,ranges:r}}function te(e){e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),e.setAttribute("spellcheck","false")}function re(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new Ai,this.inaccurateSelection=!1,this.hasSelection=!1,this.composing=null}function ne(){var e=Ui("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em; outline: none"),t=Ui("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return xo?e.style.width="1000px":e.setAttribute("wrap","off"),No&&(e.style.border="1px solid black"),te(e),t}function ie(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new Ai,this.gracePeriod=!1}function oe(e,t){var r=Je(e,t.line);if(!r||r.hidden)return null;var n=Zn(e.doc,t.line),i=qe(r,n,t.line),o=ii(n),l="left";if(o){var s=uo(o,t.ch);l=s%2?"right":"left"}var a=rt(i.map,t.ch,l);return a.offset="right"==a.collapse?a.end:a.start,a}function le(e,t){return t&&(e.bad=!0),e}function se(e,t,r){var n;if(t==e.display.lineDiv){if(n=e.display.lineDiv.childNodes[r],!n)return le(e.clipPos(zo(e.display.viewTo-1)),!0);t=null,r=0}else for(n=t;;n=n.parentNode){if(!n||n==e.display.lineDiv)return null;if(n.parentNode&&n.parentNode==e.display.lineDiv)break}for(var i=0;i<e.display.view.length;i++){var o=e.display.view[i];if(o.node==n)return ae(o,t,r)}}function ae(e,t,r){function n(t,r,n){for(var i=-1;i<(c?c.length:0);i++)for(var o=i<0?u.map:c[i],l=0;l<o.length;l+=3){var s=o[l+2];if(s==t||s==r){var a=ti(i<0?e.line:e.rest[i]),h=o[l]+n;return(n<0||s!=t)&&(h=o[l+(n?1:0)]),zo(a,h)}}}var i=e.text.firstChild,o=!1;if(!t||!Yl(i,t))return le(zo(ti(e.line),0),!0);if(t==i&&(o=!0,t=i.childNodes[r],r=0,!t)){var l=e.rest?Di(e.rest):e.line;return le(zo(ti(l),l.text.length),o)}var s=3==t.nodeType?t:null,a=t;for(s||1!=t.childNodes.length||3!=t.firstChild.nodeType||(s=t.firstChild,r&&(r=s.nodeValue.length));a.parentNode!=i;)a=a.parentNode;var u=e.measure,c=u.maps,h=n(s,a,r);if(h)return le(h,o);for(var f=a.nextSibling,d=s?s.nodeValue.length-r:0;f;f=f.nextSibling){if(h=n(f,f.firstChild,0))return le(zo(h.line,h.ch-d),o);d+=f.textContent.length}for(var p=a.previousSibling,d=r;p;p=p.previousSibling){if(h=n(p,p.firstChild,-1))return le(zo(h.line,h.ch+d),o);d+=f.textContent.length}}function ue(e,t,r,n,i){function o(e){return function(t){return t.id==e}}function l(t){if(1==t.nodeType){var r=t.getAttribute("cm-text");if(null!=r)return""==r&&(r=t.textContent.replace(/\u200b/g,"")),void(s+=r);var c,h=t.getAttribute("cm-marker");if(h){var f=e.findMarks(zo(n,0),zo(i+1,0),o(+h));return void(f.length&&(c=f[0].find())&&(s+=Qn(e.doc,c.from,c.to).join(u)))}if("false"==t.getAttribute("contenteditable"))return;for(var d=0;d<t.childNodes.length;d++)l(t.childNodes[d]);/^(pre|div|p)$/i.test(t.nodeName)&&(a=!0)}else if(3==t.nodeType){var p=t.nodeValue;if(!p)return;a&&(s+=u,a=!1),s+=p}}for(var s="",a=!1,u=e.doc.lineSeparator();l(t),t!=r;)t=t.nextSibling;return s}function ce(e,t){this.ranges=e,this.primIndex=t}function he(e,t){this.anchor=e,this.head=t}function fe(e,t){var r=e[t];e.sort(function(e,t){return Fo(e.from(),t.from())}),t=Hi(e,r);for(var n=1;n<e.length;n++){var i=e[n],o=e[n-1];if(Fo(o.to(),i.from())>=0){var l=$(o.from(),i.from()),s=_(o.to(),i.to()),a=o.empty()?i.from()==i.head:o.from()==o.head;n<=t&&--t,e.splice(--n,2,new he(a?s:l,a?l:s))}}return new ce(e,t)}function de(e,t){return new ce([new he(e,t||e)],0)}function pe(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function ge(e,t){if(t.line<e.first)return zo(e.first,0);var r=e.first+e.size-1;return t.line>r?zo(r,Zn(e,r).text.length):ve(t,Zn(e,t.line).text.length)}function ve(e,t){var r=e.ch;return null==r||r>t?zo(e.line,t):r<0?zo(e.line,0):e}function me(e,t){return t>=e.first&&t<e.first+e.size}function ye(e,t){for(var r=[],n=0;n<t.length;n++)r[n]=ge(e,t[n]);return r}function be(e,t,r,n){if(e.cm&&e.cm.display.shift||e.extend){var i=t.anchor;if(n){var o=Fo(r,i)<0;o!=Fo(n,i)<0?(i=r,r=n):o!=Fo(r,n)<0&&(r=n)}return new he(i,r)}return new he(n||r,r)}function we(e,t,r,n){ke(e,new ce([be(e,e.sel.primary(),t,r)],0),n)}function xe(e,t,r){for(var n=[],i=0;i<e.sel.ranges.length;i++)n[i]=be(e,e.sel.ranges[i],t[i],null);var o=fe(n,e.sel.primIndex);ke(e,o,r)}function Ce(e,t,r,n){var i=e.sel.ranges.slice(0);i[t]=r,ke(e,fe(i,e.sel.primIndex),n)}function Se(e,t,r,n){ke(e,de(t,r),n)}function Le(e,t,r){var n={ranges:t.ranges,update:function(t){this.ranges=[];for(var r=0;r<t.length;r++)this.ranges[r]=new he(ge(e,t[r].anchor),ge(e,t[r].head))},origin:r&&r.origin};return Dl(e,"beforeSelectionChange",e,n),e.cm&&Dl(e.cm,"beforeSelectionChange",e.cm,n),n.ranges!=t.ranges?fe(n.ranges,n.ranges.length-1):t}function Te(e,t,r){var n=e.history.done,i=Di(n);i&&i.ranges?(n[n.length-1]=t,Me(e,t,r)):ke(e,t,r)}function ke(e,t,r){Me(e,t,r),hi(e,e.sel,e.cm?e.cm.curOp.id:NaN,r)}function Me(e,t,r){(Ni(e,"beforeSelectionChange")||e.cm&&Ni(e.cm,"beforeSelectionChange"))&&(t=Le(e,t,r));var n=r&&r.bias||(Fo(t.primary().head,e.sel.primary().head)<0?-1:1);Ne(e,Ae(e,t,n,!0)),r&&r.scroll===!1||!e.cm||zr(e.cm)}function Ne(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=e.cm.curOp.selectionChanged=!0,Mi(e.cm)),Li(e,"cursorActivity",e))}function We(e){Ne(e,Ae(e,e.sel,null,!1),Il)}function Ae(e,t,r,n){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=t.ranges.length==e.sel.ranges.length&&e.sel.ranges[o],a=De(e,l.anchor,s&&s.anchor,r,n),u=De(e,l.head,s&&s.head,r,n);(i||a!=l.anchor||u!=l.head)&&(i||(i=t.ranges.slice(0,o)),i[o]=new he(a,u))}return i?fe(i,t.primIndex):t}function Oe(e,t,r,n,i){var o=Zn(e,t.line);if(o.markedSpans)for(var l=0;l<o.markedSpans.length;++l){var s=o.markedSpans[l],a=s.marker;if((null==s.from||(a.inclusiveLeft?s.from<=t.ch:s.from<t.ch))&&(null==s.to||(a.inclusiveRight?s.to>=t.ch:s.to>t.ch))){if(i&&(Dl(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(r){var u,c=a.find(n<0?1:-1);if((n<0?a.inclusiveRight:a.inclusiveLeft)&&(c=He(e,c,-n,o)),c&&c.line==t.line&&(u=Fo(c,r))&&(n<0?u<0:u>0))return Oe(e,c,t,n,i)}var h=a.find(n<0?-1:1);return(n<0?a.inclusiveLeft:a.inclusiveRight)&&(h=He(e,h,n,o)),h?Oe(e,h,t,n,i):null}}return t}function De(e,t,r,n,i){var o=n||1,l=Oe(e,t,r,o,i)||!i&&Oe(e,t,r,o,!0)||Oe(e,t,r,-o,i)||!i&&Oe(e,t,r,-o,!0);return l?l:(e.cantEdit=!0,zo(e.first,0))}function He(e,t,r,n){return r<0&&0==t.ch?t.line>e.first?ge(e,zo(t.line-1)):null:r>0&&t.ch==(n||Zn(e,t.line)).text.length?t.line<e.first+e.size-1?zo(t.line+1,0):null:new zo(t.line,t.ch+r)}function Pe(e){e.display.input.showSelection(e.display.input.prepareSelection())}function Ee(e,t){for(var r=e.doc,n={},i=n.cursors=document.createDocumentFragment(),o=n.selection=document.createDocumentFragment(),l=0;l<r.sel.ranges.length;l++)if(t!==!1||l!=r.sel.primIndex){var s=r.sel.ranges[l],a=s.empty();(a||e.options.showCursorWhenSelecting)&&Ie(e,s.head,i),a||ze(e,s,o)}return n}function Ie(e,t,r){var n=dt(e,t,"div",null,null,!e.options.singleCursorHeightPerLine),i=r.appendChild(Ui("div"," ","CodeMirror-cursor"));if(i.style.left=n.left+"px",i.style.top=n.top+"px",i.style.height=Math.max(0,n.bottom-n.top)*e.options.cursorHeight+"px",n.other){var o=r.appendChild(Ui("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));o.style.display="",o.style.left=n.other.left+"px",o.style.top=n.other.top+"px",o.style.height=.85*(n.other.bottom-n.other.top)+"px"}}function ze(e,t,r){function n(e,t,r,n){t<0&&(t=0),t=Math.round(t),n=Math.round(n),s.appendChild(Ui("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px; top: "+t+"px; width: "+(null==r?c-e:r)+"px; height: "+(n-t)+"px"))}function i(t,r,i){function o(r,n){return ft(e,zo(t,r),"div",h,n)}var s,a,h=Zn(l,t),f=h.text.length;return eo(ii(h),r||0,null==i?f:i,function(e,t,l){var h,d,p,g=o(e,"left");if(e==t)h=g,d=p=g.left;else{if(h=o(t-1,"right"),"rtl"==l){var v=g;g=h,h=v}d=g.left,p=h.right}null==r&&0==e&&(d=u),h.top-g.top>3&&(n(d,g.top,null,g.bottom),d=u,g.bottom<h.top&&n(d,g.bottom,null,h.top)),null==i&&t==f&&(p=c),(!s||g.top<s.top||g.top==s.top&&g.left<s.left)&&(s=g),(!a||h.bottom>a.bottom||h.bottom==a.bottom&&h.right>a.right)&&(a=h),d<u+1&&(d=u),n(d,h.top,p-d,h.bottom)}),{start:s,end:a}}var o=e.display,l=e.doc,s=document.createDocumentFragment(),a=je(e.display),u=a.left,c=Math.max(o.sizerWidth,Ye(e)-o.sizer.offsetLeft)-a.right,h=t.from(),f=t.to();if(h.line==f.line)i(h.line,h.ch,f.ch);else{var d=Zn(l,h.line),p=Zn(l,f.line),g=yn(d)==yn(p),v=i(h.line,h.ch,g?d.text.length+1:null).end,m=i(f.line,g?0:null,f.ch).start;g&&(v.top<m.top-2?(n(v.right,v.top,null,v.bottom),n(u,m.top,m.left,m.bottom)):n(v.right,v.top,m.left-v.right,v.bottom)),v.bottom<m.top&&n(u,v.bottom,null,m.top)}r.appendChild(s)}function Fe(e){if(e.state.focused){var t=e.display;clearInterval(t.blinker);var r=!0;t.cursorDiv.style.visibility="",e.options.cursorBlinkRate>0?t.blinker=setInterval(function(){t.cursorDiv.style.visibility=(r=!r)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function Re(e,t){e.doc.mode.startState&&e.doc.frontier<e.display.viewTo&&e.state.highlight.set(t,Fi(Be,e))}function Be(e){var t=e.doc;if(t.frontier<t.first&&(t.frontier=t.first),!(t.frontier>=e.display.viewTo)){var r=+new Date+e.options.workTime,n=sl(t.mode,Ue(e,t.frontier)),i=[];t.iter(t.frontier,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(t.frontier>=e.display.viewFrom){var l=o.styles,s=o.text.length>e.options.maxHighlightLength,a=Pn(e,o,s?sl(t.mode,n):n,!0);o.styles=a.styles;var u=o.styleClasses,c=a.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var h=!l||l.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),f=0;!h&&f<l.length;++f)h=l[f]!=o.styles[f];h&&i.push(t.frontier),o.stateAfter=s?n:sl(t.mode,n)}else o.text.length<=e.options.maxHighlightLength&&In(e,o.text,n),o.stateAfter=t.frontier%5==0?sl(t.mode,n):null;if(++t.frontier,+new Date>r)return Re(e,e.options.workDelay),!0}),i.length&&Wt(e,function(){for(var t=0;t<i.length;t++)It(e,i[t],"text")})}}function Ge(e,t,r){for(var n,i,o=e.doc,l=r?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>l;--s){if(s<=o.first)return o.first;var a=Zn(o,s-1);if(a.stateAfter&&(!r||s<=o.frontier))return s;var u=Rl(a.text,null,e.options.tabSize);(null==i||n>u)&&(i=s-1,n=u)}return i}function Ue(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return!0;var o=Ge(e,t,r),l=o>n.first&&Zn(n,o-1).stateAfter;return l=l?sl(n.mode,l):al(n.mode),n.iter(o,t,function(r){In(e,r.text,l);var s=o==t-1||o%5==0||o>=i.viewFrom&&o<i.viewTo;r.stateAfter=s?sl(n.mode,l):null,++o}),r&&(n.frontier=o),l}function Ve(e){return e.lineSpace.offsetTop}function Ke(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function je(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=Ki(e.measure,Ui("pre","x")),r=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,n={left:parseInt(r.paddingLeft),right:parseInt(r.paddingRight)};return isNaN(n.left)||isNaN(n.right)||(e.cachedPaddingH=n),n}function Xe(e){return Pl-e.display.nativeBarWidth}function Ye(e){return e.display.scroller.clientWidth-Xe(e)-e.display.barWidth}function _e(e){return e.display.scroller.clientHeight-Xe(e)-e.display.barHeight}function $e(e,t,r){var n=e.options.lineWrapping,i=n&&Ye(e);if(!t.measure.heights||n&&t.measure.width!=i){var o=t.measure.heights=[];if(n){t.measure.width=i;for(var l=t.text.firstChild.getClientRects(),s=0;s<l.length-1;s++){var a=l[s],u=l[s+1];Math.abs(a.bottom-u.bottom)>2&&o.push((a.bottom+u.top)/2-r.top)}}o.push(r.bottom-r.top)}}function qe(e,t,r){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var n=0;n<e.rest.length;n++)if(e.rest[n]==t)return{map:e.measure.maps[n],cache:e.measure.caches[n]};for(var n=0;n<e.rest.length;n++)if(ti(e.rest[n])>r)return{map:e.measure.maps[n],cache:e.measure.caches[n],before:!0}}function Ze(e,t){t=yn(t);var r=ti(t),n=e.display.externalMeasured=new Ht(e.doc,t,r);n.lineN=r;var i=n.built=Fn(e,n);return n.text=i.pre,Ki(e.display.lineMeasure,i.pre),n}function Qe(e,t,r,n){return tt(e,et(e,t),r,n)}function Je(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[Ft(e,t)];var r=e.display.externalMeasured;return r&&t>=r.lineN&&t<r.lineN+r.size?r:void 0}function et(e,t){var r=ti(t),n=Je(e,r);n&&!n.text?n=null:n&&n.changes&&(E(e,n,r,H(e)),e.curOp.forceUpdate=!0),n||(n=Ze(e,t));var i=qe(n,t,r);return{line:t,view:n,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function tt(e,t,r,n,i){t.before&&(r=-1);var o,l=r+(n||"");return t.cache.hasOwnProperty(l)?o=t.cache[l]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||($e(e,t.view,t.rect),t.hasHeights=!0),o=nt(e,t,r,n),o.bogus||(t.cache[l]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}function rt(e,t,r){for(var n,i,o,l,s=0;s<e.length;s+=3){var a=e[s],u=e[s+1];if(t<a?(i=0,o=1,l="left"):t<u?(i=t-a,o=i+1):(s==e.length-3||t==u&&e[s+3]>t)&&(o=u-a,i=o-1,t>=u&&(l="right")),null!=i){if(n=e[s+2],a==u&&r==(n.insertLeft?"left":"right")&&(l=r),"left"==r&&0==i)for(;s&&e[s-2]==e[s-3]&&e[s-1].insertLeft;)n=e[(s-=3)+2],l="left";if("right"==r&&i==u-a)for(;s<e.length-3&&e[s+3]==e[s+4]&&!e[s+5].insertLeft;)n=e[(s+=3)+2],
2
- l="right";break}}return{node:n,start:i,end:o,collapse:l,coverStart:a,coverEnd:u}}function nt(e,t,r,n){var i,o=rt(t.map,r,n),l=o.node,s=o.start,a=o.end,u=o.collapse;if(3==l.nodeType){for(var c=0;c<4;c++){for(;s&&Gi(t.line.text.charAt(o.coverStart+s));)--s;for(;o.coverStart+a<o.coverEnd&&Gi(t.line.text.charAt(o.coverStart+a));)++a;if(bo&&wo<9&&0==s&&a==o.coverEnd-o.coverStart)i=l.parentNode.getBoundingClientRect();else if(bo&&e.options.lineWrapping){var h=Vl(l,s,a).getClientRects();i=h.length?h["right"==n?h.length-1:0]:Vo}else i=Vl(l,s,a).getBoundingClientRect()||Vo;if(i.left||i.right||0==s)break;a=s,s-=1,u="right"}bo&&wo<11&&(i=it(e.display.measure,i))}else{s>0&&(u=n="right");var h;i=e.options.lineWrapping&&(h=l.getClientRects()).length>1?h["right"==n?h.length-1:0]:l.getBoundingClientRect()}if(bo&&wo<9&&!s&&(!i||!i.left&&!i.right)){var f=l.parentNode.getClientRects()[0];i=f?{left:f.left,right:f.left+bt(e.display),top:f.top,bottom:f.bottom}:Vo}for(var d=i.top-t.rect.top,p=i.bottom-t.rect.top,g=(d+p)/2,v=t.view.measure.heights,c=0;c<v.length-1&&!(g<v[c]);c++);var m=c?v[c-1]:0,y=v[c],b={left:("right"==u?i.right:i.left)-t.rect.left,right:("left"==u?i.left:i.right)-t.rect.left,top:m,bottom:y};return i.left||i.right||(b.bogus=!0),e.options.singleCursorHeightPerLine||(b.rtop=d,b.rbottom=p),b}function it(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!Ji(e))return t;var r=screen.logicalXDPI/screen.deviceXDPI,n=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*r,right:t.right*r,top:t.top*n,bottom:t.bottom*n}}function ot(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function lt(e){e.display.externalMeasure=null,Vi(e.display.lineMeasure);for(var t=0;t<e.display.view.length;t++)ot(e.display.view[t])}function st(e){lt(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function at(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function ut(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function ct(e,t,r,n){if(t.widgets)for(var i=0;i<t.widgets.length;++i)if(t.widgets[i].above){var o=Tn(t.widgets[i]);r.top+=o,r.bottom+=o}if("line"==n)return r;n||(n="local");var l=ni(t);if("local"==n?l+=Ve(e.display):l-=e.display.viewOffset,"page"==n||"window"==n){var s=e.display.lineSpace.getBoundingClientRect();l+=s.top+("window"==n?0:ut());var a=s.left+("window"==n?0:at());r.left+=a,r.right+=a}return r.top+=l,r.bottom+=l,r}function ht(e,t,r){if("div"==r)return t;var n=t.left,i=t.top;if("page"==r)n-=at(),i-=ut();else if("local"==r||!r){var o=e.display.sizer.getBoundingClientRect();n+=o.left,i+=o.top}var l=e.display.lineSpace.getBoundingClientRect();return{left:n-l.left,top:i-l.top}}function ft(e,t,r,n,i){return n||(n=Zn(e.doc,t.line)),ct(e,n,Qe(e,n,t.ch,i),r)}function dt(e,t,r,n,i,o){function l(t,l){var s=tt(e,i,t,l?"right":"left",o);return l?s.left=s.right:s.right=s.left,ct(e,n,s,r)}function s(e,t){var r=a[t],n=r.level%2;return e==to(r)&&t&&r.level<a[t-1].level?(r=a[--t],e=ro(r)-(r.level%2?0:1),n=!0):e==ro(r)&&t<a.length-1&&r.level<a[t+1].level&&(r=a[++t],e=to(r)-r.level%2,n=!1),n&&e==r.to&&e>r.from?l(e-1):l(e,n)}n=n||Zn(e.doc,t.line),i||(i=et(e,n));var a=ii(n),u=t.ch;if(!a)return l(u);var c=uo(a,u),h=s(u,c);return null!=os&&(h.other=s(u,os)),h}function pt(e,t){var r=0,t=ge(e.doc,t);e.options.lineWrapping||(r=bt(e.display)*t.ch);var n=Zn(e.doc,t.line),i=ni(n)+Ve(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function gt(e,t,r,n){var i=zo(e,t);return i.xRel=n,r&&(i.outside=!0),i}function vt(e,t,r){var n=e.doc;if(r+=e.display.viewOffset,r<0)return gt(n.first,0,!0,-1);var i=ri(n,r),o=n.first+n.size-1;if(i>o)return gt(n.first+n.size-1,Zn(n,o).text.length,!0,1);t<0&&(t=0);for(var l=Zn(n,i);;){var s=mt(e,l,i,t,r),a=vn(l),u=a&&a.find(0,!0);if(!a||!(s.ch>u.from.ch||s.ch==u.from.ch&&s.xRel>0))return s;i=ti(l=u.to.line)}}function mt(e,t,r,n,i){function o(n){var i=dt(e,zo(r,n),"line",t,u);return s=!0,l>i.bottom?i.left-a:l<i.top?i.left+a:(s=!1,i.left)}var l=i-ni(t),s=!1,a=2*e.display.wrapper.clientWidth,u=et(e,t),c=ii(t),h=t.text.length,f=no(t),d=io(t),p=o(f),g=s,v=o(d),m=s;if(n>v)return gt(r,d,m,1);for(;;){if(c?d==f||d==ho(t,f,1):d-f<=1){for(var y=n<p||n-p<=v-n?f:d,b=n-(y==f?p:v);Gi(t.text.charAt(y));)++y;var w=gt(r,y,y==f?g:m,b<-1?-1:b>1?1:0);return w}var x=Math.ceil(h/2),C=f+x;if(c){C=f;for(var S=0;S<x;++S)C=ho(t,C,1)}var L=o(C);L>n?(d=C,v=L,(m=s)&&(v+=1e3),h=x):(f=C,p=L,g=s,h-=x)}}function yt(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Bo){Bo=Ui("pre");for(var t=0;t<49;++t)Bo.appendChild(document.createTextNode("x")),Bo.appendChild(Ui("br"));Bo.appendChild(document.createTextNode("x"))}Ki(e.measure,Bo);var r=Bo.offsetHeight/50;return r>3&&(e.cachedTextHeight=r),Vi(e.measure),r||1}function bt(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=Ui("span","xxxxxxxxxx"),r=Ui("pre",[t]);Ki(e.measure,r);var n=t.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function wt(e){e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++jo},Ko?Ko.ops.push(e.curOp):e.curOp.ownsGroup=Ko={ops:[e.curOp],delayedCallbacks:[]}}function xt(e){var t=e.delayedCallbacks,r=0;do{for(;r<t.length;r++)t[r].call(null);for(var n=0;n<e.ops.length;n++){var i=e.ops[n];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++].call(null,i.cm)}}while(r<t.length)}function Ct(e){var t=e.curOp,r=t.ownsGroup;if(r)try{xt(r)}finally{Ko=null;for(var n=0;n<r.ops.length;n++)r.ops[n].cm.curOp=null;St(r)}}function St(e){for(var t=e.ops,r=0;r<t.length;r++)Lt(t[r]);for(var r=0;r<t.length;r++)Tt(t[r]);for(var r=0;r<t.length;r++)kt(t[r]);for(var r=0;r<t.length;r++)Mt(t[r]);for(var r=0;r<t.length;r++)Nt(t[r])}function Lt(e){var t=e.cm,r=t.display;k(t),e.updateMaxLine&&f(t),e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<r.viewFrom||e.scrollToPos.to.line>=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new T(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Tt(e){e.updatedDisplay=e.mustUpdate&&M(e.cm,e.update)}function kt(e){var t=e.cm,r=t.display;e.updatedDisplay&&O(t),e.barMeasure=p(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Qe(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+Xe(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Ye(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection())}function Mt(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&ir(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1),e.preparedSelection&&t.display.input.showSelection(e.preparedSelection),e.updatedDisplay&&A(t,e.barMeasure),(e.updatedDisplay||e.startHeight!=t.doc.height)&&y(t,e.barMeasure),e.selectionChanged&&Fe(t),t.state.focused&&e.updateInput&&t.display.input.reset(e.typing),!e.focus||e.focus!=ji()||document.hasFocus&&!document.hasFocus()||q(e.cm)}function Nt(e){var t=e.cm,r=t.display,n=t.doc;if(e.updatedDisplay&&N(t,e.update),null==r.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(r.wheelStartX=r.wheelStartY=null),null==e.scrollTop||r.scroller.scrollTop==e.scrollTop&&!e.forceScroll||(n.scrollTop=Math.max(0,Math.min(r.scroller.scrollHeight-r.scroller.clientHeight,e.scrollTop)),r.scrollbars.setScrollTop(n.scrollTop),r.scroller.scrollTop=n.scrollTop),null==e.scrollLeft||r.scroller.scrollLeft==e.scrollLeft&&!e.forceScroll||(n.scrollLeft=Math.max(0,Math.min(r.scroller.scrollWidth-Ye(t),e.scrollLeft)),r.scrollbars.setScrollLeft(n.scrollLeft),r.scroller.scrollLeft=n.scrollLeft,x(t)),e.scrollToPos){var i=Hr(t,ge(n,e.scrollToPos.from),ge(n,e.scrollToPos.to),e.scrollToPos.margin);e.scrollToPos.isCursor&&t.state.focused&&Dr(t,i)}var o=e.maybeHiddenMarkers,l=e.maybeUnhiddenMarkers;if(o)for(var s=0;s<o.length;++s)o[s].lines.length||Dl(o[s],"hide");if(l)for(var s=0;s<l.length;++s)l[s].lines.length&&Dl(l[s],"unhide");r.wrapper.offsetHeight&&(n.scrollTop=t.display.scroller.scrollTop),e.changeObjs&&Dl(t,"changes",t,e.changeObjs),e.update&&e.update.finish()}function Wt(e,t){if(e.curOp)return t();wt(e);try{return t()}finally{Ct(e)}}function At(e,t){return function(){if(e.curOp)return t.apply(e,arguments);wt(e);try{return t.apply(e,arguments)}finally{Ct(e)}}}function Ot(e){return function(){if(this.curOp)return e.apply(this,arguments);wt(this);try{return e.apply(this,arguments)}finally{Ct(this)}}}function Dt(e){return function(){var t=this.cm;if(!t||t.curOp)return e.apply(this,arguments);wt(t);try{return e.apply(this,arguments)}finally{Ct(t)}}}function Ht(e,t,r){this.line=t,this.rest=bn(t),this.size=this.rest?ti(Di(this.rest))-r+1:1,this.node=this.text=null,this.hidden=Cn(e,t)}function Pt(e,t,r){for(var n,i=[],o=t;o<r;o=n){var l=new Ht(e.doc,Zn(e.doc,o),o);n=o+l.size,i.push(l)}return i}function Et(e,t,r,n){null==t&&(t=e.doc.first),null==r&&(r=e.doc.first+e.doc.size),n||(n=0);var i=e.display;if(n&&r<i.viewTo&&(null==i.updateLineNumbers||i.updateLineNumbers>t)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Io&&wn(e.doc,t)<i.viewTo&&zt(e);else if(r<=i.viewFrom)Io&&xn(e.doc,r+n)>i.viewFrom?zt(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)zt(e);else if(t<=i.viewFrom){var o=Rt(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):zt(e)}else if(r>=i.viewTo){var o=Rt(e,t,t,-1);o?(i.view=i.view.slice(0,o.index),i.viewTo=o.lineN):zt(e)}else{var l=Rt(e,t,t,-1),s=Rt(e,r,r+n,1);l&&s?(i.view=i.view.slice(0,l.index).concat(Pt(e,l.lineN,s.lineN)).concat(i.view.slice(s.index)),i.viewTo+=n):zt(e)}var a=i.externalMeasured;a&&(r<a.lineN?a.lineN+=n:t<a.lineN+a.size&&(i.externalMeasured=null))}function It(e,t,r){e.curOp.viewChanged=!0;var n=e.display,i=e.display.externalMeasured;if(i&&t>=i.lineN&&t<i.lineN+i.size&&(n.externalMeasured=null),!(t<n.viewFrom||t>=n.viewTo)){var o=n.view[Ft(e,t)];if(null!=o.node){var l=o.changes||(o.changes=[]);Hi(l,r)==-1&&l.push(r)}}}function zt(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function Ft(e,t){if(t>=e.display.viewTo)return null;if(t-=e.display.viewFrom,t<0)return null;for(var r=e.display.view,n=0;n<r.length;n++)if(t-=r[n].size,t<0)return n}function Rt(e,t,r,n){var i,o=Ft(e,t),l=e.display.view;if(!Io||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var s=0,a=e.display.viewFrom;s<o;s++)a+=l[s].size;if(a!=t){if(n>0){if(o==l.length-1)return null;i=a+l[o].size-t,o++}else i=a-t;t+=i,r+=i}for(;wn(e.doc,r)!=r;){if(o==(n<0?0:l.length-1))return null;r+=n*l[o-(n<0?1:0)].size,o+=n}return{index:o,lineN:r}}function Bt(e,t,r){var n=e.display,i=n.view;0==i.length||t>=n.viewTo||r<=n.viewFrom?(n.view=Pt(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=Pt(e,t,n.viewFrom).concat(n.view):n.viewFrom<t&&(n.view=n.view.slice(Ft(e,t))),n.viewFrom=t,n.viewTo<r?n.view=n.view.concat(Pt(e,n.viewTo,r)):n.viewTo>r&&(n.view=n.view.slice(0,Ft(e,r)))),n.viewTo=r}function Gt(e){for(var t=e.display.view,r=0,n=0;n<t.length;n++){var i=t[n];i.hidden||i.node&&!i.changes||++r}return r}function Ut(e){function t(){i.activeTouch&&(o=setTimeout(function(){i.activeTouch=null},1e3),l=i.activeTouch,l.end=+new Date)}function r(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}function n(e,t){if(null==t.left)return!0;var r=t.left-e.left,n=t.top-e.top;return r*r+n*n>400}var i=e.display;Wl(i.scroller,"mousedown",At(e,Yt)),bo&&wo<11?Wl(i.scroller,"dblclick",At(e,function(t){if(!ki(e,t)){var r=Xt(e,t);if(r&&!Qt(e,t)&&!jt(e.display,t)){kl(t);var n=e.findWordAt(r);we(e.doc,n.anchor,n.head)}}})):Wl(i.scroller,"dblclick",function(t){ki(e,t)||kl(t)}),Po||Wl(i.scroller,"contextmenu",function(t){yr(e,t)});var o,l={end:0};Wl(i.scroller,"touchstart",function(e){if(!r(e)){clearTimeout(o);var t=+new Date;i.activeTouch={start:t,moved:!1,prev:t-l.end<=300?l:null},1==e.touches.length&&(i.activeTouch.left=e.touches[0].pageX,i.activeTouch.top=e.touches[0].pageY)}}),Wl(i.scroller,"touchmove",function(){i.activeTouch&&(i.activeTouch.moved=!0)}),Wl(i.scroller,"touchend",function(r){var o=i.activeTouch;if(o&&!jt(i,r)&&null!=o.left&&!o.moved&&new Date-o.start<300){var l,s=e.coordsChar(i.activeTouch,"page");l=!o.prev||n(o,o.prev)?new he(s,s):!o.prev.prev||n(o,o.prev.prev)?e.findWordAt(s):new he(zo(s.line,0),ge(e.doc,zo(s.line+1,0))),e.setSelection(l.anchor,l.head),e.focus(),kl(r)}t()}),Wl(i.scroller,"touchcancel",t),Wl(i.scroller,"scroll",function(){i.scroller.clientHeight&&(nr(e,i.scroller.scrollTop),ir(e,i.scroller.scrollLeft,!0),Dl(e,"scroll",e))}),Wl(i.scroller,"mousewheel",function(t){or(e,t)}),Wl(i.scroller,"DOMMouseScroll",function(t){or(e,t)}),Wl(i.wrapper,"scroll",function(){i.wrapper.scrollTop=i.wrapper.scrollLeft=0}),i.dragFunctions={enter:function(t){ki(e,t)||Nl(t)},over:function(t){ki(e,t)||(tr(e,t),Nl(t))},start:function(t){er(e,t)},drop:At(e,Jt),leave:function(){rr(e)}};var s=i.input.getField();Wl(s,"keyup",function(t){dr.call(e,t)}),Wl(s,"keydown",At(e,hr)),Wl(s,"keypress",At(e,pr)),Wl(s,"focus",Fi(vr,e)),Wl(s,"blur",Fi(mr,e))}function Vt(t,r,n){var i=n&&n!=e.Init;if(!r!=!i){var o=t.display.dragFunctions,l=r?Wl:Ol;l(t.display.scroller,"dragstart",o.start),l(t.display.scroller,"dragenter",o.enter),l(t.display.scroller,"dragover",o.over),l(t.display.scroller,"dragleave",o.leave),l(t.display.scroller,"drop",o.drop)}}function Kt(e){var t=e.display;t.lastWrapHeight==t.wrapper.clientHeight&&t.lastWrapWidth==t.wrapper.clientWidth||(t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize())}function jt(e,t){for(var r=xi(t);r!=e.wrapper;r=r.parentNode)if(!r||1==r.nodeType&&"true"==r.getAttribute("cm-ignore-events")||r.parentNode==e.sizer&&r!=e.mover)return!0}function Xt(e,t,r,n){var i=e.display;if(!r&&"true"==xi(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(t){return null}var a,u=vt(e,o,l);if(n&&1==u.xRel&&(a=Zn(e.doc,u.line).text).length==u.ch){var c=Rl(a,a.length,e.options.tabSize)-a.length;u=zo(u.line,Math.max(0,Math.round((o-je(e.display).left)/bt(e.display))-c))}return u}function Yt(e){var t=this,r=t.display;if(!(r.activeTouch&&r.input.supportsTouch()||ki(t,e))){if(r.shift=e.shiftKey,jt(r,e))return void(xo||(r.scroller.draggable=!1,setTimeout(function(){r.scroller.draggable=!0},100)));if(!Qt(t,e)){var n=Xt(t,e);switch(window.focus(),Ci(e)){case 1:t.state.selectingText?t.state.selectingText(e):n?_t(t,e,n):xi(e)==r.scroller&&kl(e);break;case 2:xo&&(t.state.lastMiddleDown=+new Date),n&&we(t.doc,n),setTimeout(function(){r.input.focus()},20),kl(e);break;case 3:Po?yr(t,e):gr(t)}}}}function _t(e,t,r){bo?setTimeout(Fi(q,e),0):e.curOp.focus=ji();var n,i=+new Date;Uo&&Uo.time>i-400&&0==Fo(Uo.pos,r)?n="triple":Go&&Go.time>i-400&&0==Fo(Go.pos,r)?(n="double",Uo={time:i,pos:r}):(n="single",Go={time:i,pos:r});var o,l=e.doc.sel,s=Ao?t.metaKey:t.ctrlKey;e.options.dragDrop&&Jl&&!e.isReadOnly()&&"single"==n&&(o=l.contains(r))>-1&&(Fo((o=l.ranges[o]).from(),r)<0||r.xRel>0)&&(Fo(o.to(),r)>0||r.xRel<0)?$t(e,t,r,s):qt(e,t,r,n,s)}function $t(e,t,r,n){var i=e.display,o=+new Date,l=At(e,function(s){xo&&(i.scroller.draggable=!1),e.state.draggingText=!1,Ol(document,"mouseup",l),Ol(i.scroller,"drop",l),Math.abs(t.clientX-s.clientX)+Math.abs(t.clientY-s.clientY)<10&&(kl(s),!n&&+new Date-200<o&&we(e.doc,r),xo||bo&&9==wo?setTimeout(function(){document.body.focus(),i.input.focus()},20):i.input.focus())});xo&&(i.scroller.draggable=!0),e.state.draggingText=l,i.scroller.dragDrop&&i.scroller.dragDrop(),Wl(document,"mouseup",l),Wl(i.scroller,"drop",l)}function qt(e,t,r,n,i){function o(t){if(0!=Fo(v,t))if(v=t,"rect"==n){for(var i=[],o=e.options.tabSize,l=Rl(Zn(u,r.line).text,r.ch,o),s=Rl(Zn(u,t.line).text,t.ch,o),a=Math.min(l,s),d=Math.max(l,s),p=Math.min(r.line,t.line),g=Math.min(e.lastLine(),Math.max(r.line,t.line));p<=g;p++){var m=Zn(u,p).text,y=Bl(m,a,o);a==d?i.push(new he(zo(p,y),zo(p,y))):m.length>y&&i.push(new he(zo(p,y),zo(p,Bl(m,d,o))))}i.length||i.push(new he(r,r)),ke(u,fe(f.ranges.slice(0,h).concat(i),h),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b=c,w=b.anchor,x=t;if("single"!=n){if("double"==n)var C=e.findWordAt(t);else var C=new he(zo(t.line,0),ge(u,zo(t.line+1,0)));Fo(C.anchor,w)>0?(x=C.head,w=$(b.from(),C.anchor)):(x=C.anchor,w=_(b.to(),C.head))}var i=f.ranges.slice(0);i[h]=new he(ge(u,w),x),ke(u,fe(i,h),zl)}}function l(t){var r=++y,i=Xt(e,t,!0,"rect"==n);if(i)if(0!=Fo(i,v)){e.curOp.focus=ji(),o(i);var s=w(a,u);(i.line>=s.to||i.line<s.from)&&setTimeout(At(e,function(){y==r&&l(t)}),150)}else{var c=t.clientY<m.top?-20:t.clientY>m.bottom?20:0;c&&setTimeout(At(e,function(){y==r&&(a.scroller.scrollTop+=c,l(t))}),50)}}function s(t){e.state.selectingText=!1,y=1/0,kl(t),a.input.focus(),Ol(document,"mousemove",b),Ol(document,"mouseup",x),u.history.lastSelOrigin=null}var a=e.display,u=e.doc;kl(t);var c,h,f=u.sel,d=f.ranges;if(i&&!t.shiftKey?(h=u.sel.contains(r),c=h>-1?d[h]:new he(r,r)):(c=u.sel.primary(),h=u.sel.primIndex),t.altKey)n="rect",i||(c=new he(r,r)),r=Xt(e,t,!0,!0),h=-1;else if("double"==n){var p=e.findWordAt(r);c=e.display.shift||u.extend?be(u,c,p.anchor,p.head):p}else if("triple"==n){var g=new he(zo(r.line,0),ge(u,zo(r.line+1,0)));c=e.display.shift||u.extend?be(u,c,g.anchor,g.head):g}else c=be(u,c,r);i?h==-1?(h=d.length,ke(u,fe(d.concat([c]),h),{scroll:!1,origin:"*mouse"})):d.length>1&&d[h].empty()&&"single"==n&&!t.shiftKey?(ke(u,fe(d.slice(0,h).concat(d.slice(h+1)),0),{scroll:!1,origin:"*mouse"}),f=u.sel):Ce(u,h,c,zl):(h=0,ke(u,new ce([c],0),zl),f=u.sel);var v=r,m=a.wrapper.getBoundingClientRect(),y=0,b=At(e,function(e){Ci(e)?l(e):s(e)}),x=At(e,s);e.state.selectingText=x,Wl(document,"mousemove",b),Wl(document,"mouseup",x)}function Zt(e,t,r,n){try{var i=t.clientX,o=t.clientY}catch(t){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;n&&kl(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!Ni(e,r))return wi(t);o-=s.top-l.viewOffset;for(var a=0;a<e.options.gutters.length;++a){var u=l.gutters.childNodes[a];if(u&&u.getBoundingClientRect().right>=i){var c=ri(e.doc,o),h=e.options.gutters[a];return Dl(e,r,e,c,h,t),wi(t)}}}function Qt(e,t){return Zt(e,t,"gutterClick",!0)}function Jt(e){var t=this;if(rr(t),!ki(t,e)&&!jt(t.display,e)){kl(e),bo&&(Xo=+new Date);var r=Xt(t,e,!0),n=e.dataTransfer.files;if(r&&!t.isReadOnly())if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),l=0,s=function(e,n){if(!t.options.allowDropFileTypes||Hi(t.options.allowDropFileTypes,e.type)!=-1){var s=new FileReader;s.onload=At(t,function(){var e=s.result;if(/[\x00-\x08\x0e-\x1f]{2}/.test(e)&&(e=""),o[n]=e,++l==i){r=ge(t.doc,r);var a={from:r,to:r,text:t.doc.splitLines(o.join(t.doc.lineSeparator())),origin:"paste"};Tr(t.doc,a),Te(t.doc,de(r,Qo(a)))}}),s.readAsText(e)}},a=0;a<i;++a)s(n[a],a);else{if(t.state.draggingText&&t.doc.sel.contains(r)>-1)return t.state.draggingText(e),void setTimeout(function(){t.display.input.focus()},20);try{var o=e.dataTransfer.getData("Text");if(o){if(t.state.draggingText&&!(Ao?e.altKey:e.ctrlKey))var u=t.listSelections();if(Me(t.doc,de(r,r)),u)for(var a=0;a<u.length;++a)Or(t.doc,"",u[a].anchor,u[a].head,"drag");t.replaceSelection(o,"around","paste"),t.display.input.focus()}}catch(e){}}}}function er(e,t){if(bo&&(!e.state.draggingText||+new Date-Xo<100))return void Nl(t);if(!ki(e,t)&&!jt(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.setDragImage&&!To)){var r=Ui("img",null,null,"position: fixed; left: 0; top: 0;");r.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",Lo&&(r.width=r.height=1,e.display.wrapper.appendChild(r),r._top=r.offsetTop),t.dataTransfer.setDragImage(r,0,0),Lo&&r.parentNode.removeChild(r)}}function tr(e,t){var r=Xt(e,t);if(r){var n=document.createDocumentFragment();Ie(e,r,n),e.display.dragCursor||(e.display.dragCursor=Ui("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),Ki(e.display.dragCursor,n)}}function rr(e){e.display.dragCursor&&(e.display.lineSpace.removeChild(e.display.dragCursor),e.display.dragCursor=null)}function nr(e,t){Math.abs(e.doc.scrollTop-t)<2||(e.doc.scrollTop=t,vo||W(e,{top:t}),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t),e.display.scrollbars.setScrollTop(t),vo&&W(e),Re(e,100))}function ir(e,t,r){(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)||(t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),e.doc.scrollLeft=t,x(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function or(e,t){var r=$o(t),n=r.x,i=r.y,o=e.display,l=o.scroller,s=l.scrollWidth>l.clientWidth,a=l.scrollHeight>l.clientHeight;if(n&&s||i&&a){if(i&&Ao&&xo)e:for(var u=t.target,c=o.view;u!=l;u=u.parentNode)for(var h=0;h<c.length;h++)if(c[h].node==u){e.display.currentWheelTarget=u;break e}if(n&&!vo&&!Lo&&null!=_o)return i&&a&&nr(e,Math.max(0,Math.min(l.scrollTop+i*_o,l.scrollHeight-l.clientHeight))),ir(e,Math.max(0,Math.min(l.scrollLeft+n*_o,l.scrollWidth-l.clientWidth))),(!i||i&&a)&&kl(t),void(o.wheelStartX=null);if(i&&null!=_o){var f=i*_o,d=e.doc.scrollTop,p=d+o.wrapper.clientHeight;f<0?d=Math.max(0,d+f-50):p=Math.min(e.doc.height,p+f+50),W(e,{top:d,bottom:p})}Yo<20&&(null==o.wheelStartX?(o.wheelStartX=l.scrollLeft,o.wheelStartY=l.scrollTop,o.wheelDX=n,o.wheelDY=i,setTimeout(function(){if(null!=o.wheelStartX){var e=l.scrollLeft-o.wheelStartX,t=l.scrollTop-o.wheelStartY,r=t&&o.wheelDY&&t/o.wheelDY||e&&o.wheelDX&&e/o.wheelDX;o.wheelStartX=o.wheelStartY=null,r&&(_o=(_o*Yo+r)/(Yo+1),++Yo)}},200)):(o.wheelDX+=n,o.wheelDY+=i))}}function lr(e,t,r){if("string"==typeof t&&(t=ul[t],!t))return!1;e.display.input.ensurePolled();var n=e.display.shift,i=!1;try{e.isReadOnly()&&(e.state.suppressEdits=!0),r&&(e.display.shift=!1),i=t(e)!=El}finally{e.display.shift=n,e.state.suppressEdits=!1}return i}function sr(e,t,r){for(var n=0;n<e.state.keyMaps.length;n++){var i=hl(t,e.state.keyMaps[n],r,e);if(i)return i}return e.options.extraKeys&&hl(t,e.options.extraKeys,r,e)||hl(t,e.options.keyMap,r,e)}function ar(e,t,r,n){var i=e.state.keySeq;if(i){if(fl(t))return"handled";qo.set(50,function(){e.state.keySeq==i&&(e.state.keySeq=null,e.display.input.reset())}),t=i+" "+t}var o=sr(e,t,n);return"multi"==o&&(e.state.keySeq=t),"handled"==o&&Li(e,"keyHandled",e,t,r),"handled"!=o&&"multi"!=o||(kl(r),Fe(e)),i&&!o&&/\'$/.test(t)?(kl(r),!0):!!o}function ur(e,t){var r=dl(t,!0);return!!r&&(t.shiftKey&&!e.state.keySeq?ar(e,"Shift-"+r,t,function(t){return lr(e,t,!0)})||ar(e,r,t,function(t){if("string"==typeof t?/^go[A-Z]/.test(t):t.motion)return lr(e,t)}):ar(e,r,t,function(t){return lr(e,t)}))}function cr(e,t,r){return ar(e,"'"+r+"'",t,function(t){return lr(e,t,!0)})}function hr(e){var t=this;if(t.curOp.focus=ji(),!ki(t,e)){bo&&wo<11&&27==e.keyCode&&(e.returnValue=!1);var r=e.keyCode;t.display.shift=16==r||e.shiftKey;var n=ur(t,e);Lo&&(Zo=n?r:null,!n&&88==r&&!rs&&(Ao?e.metaKey:e.ctrlKey)&&t.replaceSelection("",null,"cut")),18!=r||/\bCodeMirror-crosshair\b/.test(t.display.lineDiv.className)||fr(t)}}function fr(e){function t(e){18!=e.keyCode&&e.altKey||(ql(r,"CodeMirror-crosshair"),Ol(document,"keyup",t),Ol(document,"mouseover",t))}var r=e.display.lineDiv;Zl(r,"CodeMirror-crosshair"),Wl(document,"keyup",t),Wl(document,"mouseover",t)}function dr(e){16==e.keyCode&&(this.doc.sel.shift=!1),ki(this,e)}function pr(e){var t=this;if(!(jt(t.display,e)||ki(t,e)||e.ctrlKey&&!e.altKey||Ao&&e.metaKey)){var r=e.keyCode,n=e.charCode;if(Lo&&r==Zo)return Zo=null,void kl(e);if(!Lo||e.which&&!(e.which<10)||!ur(t,e)){var i=String.fromCharCode(null==n?r:n);cr(t,e,i)||t.display.input.onKeyPress(e)}}}function gr(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,mr(e))},100)}function vr(e){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(Dl(e,"focus",e),e.state.focused=!0,Zl(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),xo&&setTimeout(function(){e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),Fe(e))}function mr(e){e.state.delayingBlurEvent||(e.state.focused&&(Dl(e,"blur",e),e.state.focused=!1,ql(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function yr(e,t){jt(e.display,t)||br(e,t)||ki(e,t,"contextmenu")||e.display.input.onContextMenu(t)}function br(e,t){return!!Ni(e,"gutterContextMenu")&&Zt(e,t,"gutterContextMenu",!1)}function wr(e,t){if(Fo(e,t.from)<0)return e;if(Fo(e,t.to)<=0)return Qo(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=Qo(t).ch-t.to.ch),zo(r,n)}function xr(e,t){for(var r=[],n=0;n<e.sel.ranges.length;n++){var i=e.sel.ranges[n];r.push(new he(wr(i.anchor,t),wr(i.head,t)))}return fe(r,e.sel.primIndex)}function Cr(e,t,r){return e.line==t.line?zo(r.line,e.ch-t.ch+r.ch):zo(r.line+(e.line-t.line),e.ch)}function Sr(e,t,r){for(var n=[],i=zo(e.first,0),o=i,l=0;l<t.length;l++){var s=t[l],a=Cr(s.from,i,o),u=Cr(Qo(s),i,o);if(i=s.to,o=u,"around"==r){var c=e.sel.ranges[l],h=Fo(c.head,c.anchor)<0;n[l]=new he(h?u:a,h?a:u)}else n[l]=new he(a,a)}return new ce(n,e.sel.primIndex)}function Lr(e,t,r){var n={canceled:!1,from:t.from,to:t.to,text:t.text,origin:t.origin,cancel:function(){this.canceled=!0}};return r&&(n.update=function(t,r,n,i){t&&(this.from=ge(e,t)),r&&(this.to=ge(e,r)),n&&(this.text=n),void 0!==i&&(this.origin=i)}),Dl(e,"beforeChange",e,n),e.cm&&Dl(e.cm,"beforeChange",e.cm,n),n.canceled?null:{from:n.from,to:n.to,text:n.text,origin:n.origin}}function Tr(e,t,r){if(e.cm){if(!e.cm.curOp)return At(e.cm,Tr)(e,t,r);if(e.cm.state.suppressEdits)return}if(!(Ni(e,"beforeChange")||e.cm&&Ni(e.cm,"beforeChange"))||(t=Lr(e,t,!0))){var n=Eo&&!r&&an(e,t.from,t.to);if(n)for(var i=n.length-1;i>=0;--i)kr(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text});else kr(e,t)}}function kr(e,t){if(1!=t.text.length||""!=t.text[0]||0!=Fo(t.from,t.to)){var r=xr(e,t);ui(e,t,r,e.cm?e.cm.curOp.id:NaN),Wr(e,t,r,on(e,t));var n=[];$n(e,function(e,r){r||Hi(n,e.history)!=-1||(bi(e.history,t),n.push(e.history)),Wr(e,t,null,on(e,t))})}}function Mr(e,t,r){if(!e.cm||!e.cm.state.suppressEdits){for(var n,i=e.history,o=e.sel,l="undo"==t?i.done:i.undone,s="undo"==t?i.undone:i.done,a=0;a<l.length&&(n=l[a],r?!n.ranges||n.equals(e.sel):n.ranges);a++);if(a!=l.length){for(i.lastOrigin=i.lastSelOrigin=null;n=l.pop(),n.ranges;){if(fi(n,s),r&&!n.equals(e.sel))return void ke(e,n,{clearRedo:!1});o=n}var u=[];fi(o,s),s.push({changes:u,generation:i.generation}),i.generation=n.generation||++i.maxGeneration;for(var c=Ni(e,"beforeChange")||e.cm&&Ni(e.cm,"beforeChange"),a=n.changes.length-1;a>=0;--a){var h=n.changes[a];if(h.origin=t,c&&!Lr(e,h,!1))return void(l.length=0);u.push(li(e,h));var f=a?xr(e,h):Di(l);Wr(e,h,f,sn(e,h)),!a&&e.cm&&e.cm.scrollIntoView({from:h.from,to:Qo(h)});var d=[];$n(e,function(e,t){t||Hi(d,e.history)!=-1||(bi(e.history,h),d.push(e.history)),Wr(e,h,null,sn(e,h))})}}}}function Nr(e,t){if(0!=t&&(e.first+=t,e.sel=new ce(Pi(e.sel.ranges,function(e){return new he(zo(e.anchor.line+t,e.anchor.ch),zo(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){Et(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;n<r.viewTo;n++)It(e.cm,n,"gutter")}}function Wr(e,t,r,n){if(e.cm&&!e.cm.curOp)return At(e.cm,Wr)(e,t,r,n);if(t.to.line<e.first)return void Nr(e,t.text.length-1-(t.to.line-t.from.line));if(!(t.from.line>e.lastLine())){if(t.from.line<e.first){var i=t.text.length-1-(e.first-t.from.line);Nr(e,i),t={from:zo(e.first,0),to:zo(t.to.line+i,t.to.ch),text:[Di(t.text)],origin:t.origin}}var o=e.lastLine();t.to.line>o&&(t={from:t.from,to:zo(o,Zn(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Qn(e,t.from,t.to),r||(r=xr(e,t)),e.cm?Ar(e.cm,t,n):Xn(e,t,n),Me(e,r,Il)}}function Ar(e,t,r){var n=e.doc,i=e.display,l=t.from,s=t.to,a=!1,u=l.line;e.options.lineWrapping||(u=ti(yn(Zn(n,l.line))),n.iter(u,s.line+1,function(e){if(e==i.maxLine)return a=!0,!0})),n.sel.contains(t.from,t.to)>-1&&Mi(e),Xn(n,t,r,o(e)),e.options.lineWrapping||(n.iter(u,l.line+t.text.length,function(e){var t=h(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,a=!1)}),a&&(e.curOp.updateMaxLine=!0)),n.frontier=Math.min(n.frontier,l.line),Re(e,400);var c=t.text.length-(s.line-l.line)-1;t.full?Et(e):l.line!=s.line||1!=t.text.length||jn(e.doc,t)?Et(e,l.line,s.line+1,c):It(e,l.line,"text");var f=Ni(e,"changes"),d=Ni(e,"change");if(d||f){var p={from:l,to:s,text:t.text,removed:t.removed,origin:t.origin};d&&Li(e,"change",e,p),f&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(p)}e.display.selForContextMenu=null}function Or(e,t,r,n,i){if(n||(n=r),Fo(n,r)<0){var o=n;n=r,r=o}"string"==typeof t&&(t=e.splitLines(t)),Tr(e,{from:r,to:n,text:t,origin:i})}function Dr(e,t){if(!ki(e,"scrollCursorIntoView")){var r=e.display,n=r.sizer.getBoundingClientRect(),i=null;if(t.top+n.top<0?i=!0:t.bottom+n.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!Mo){var o=Ui("div","​",null,"position: absolute; top: "+(t.top-r.viewOffset-Ve(e.display))+"px; height: "+(t.bottom-t.top+Xe(e)+r.barHeight)+"px; left: "+t.left+"px; width: 2px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}function Hr(e,t,r,n){null==n&&(n=0);for(var i=0;i<5;i++){var o=!1,l=dt(e,t),s=r&&r!=t?dt(e,r):l,a=Er(e,Math.min(l.left,s.left),Math.min(l.top,s.top)-n,Math.max(l.left,s.left),Math.max(l.bottom,s.bottom)+n),u=e.doc.scrollTop,c=e.doc.scrollLeft;if(null!=a.scrollTop&&(nr(e,a.scrollTop),Math.abs(e.doc.scrollTop-u)>1&&(o=!0)),null!=a.scrollLeft&&(ir(e,a.scrollLeft),Math.abs(e.doc.scrollLeft-c)>1&&(o=!0)),!o)break}return l}function Pr(e,t,r,n,i){var o=Er(e,t,r,n,i);null!=o.scrollTop&&nr(e,o.scrollTop),null!=o.scrollLeft&&ir(e,o.scrollLeft)}function Er(e,t,r,n,i){var o=e.display,l=yt(e.display);r<0&&(r=0);var s=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:o.scroller.scrollTop,a=_e(e),u={};i-r>a&&(i=r+a);var c=e.doc.height+Ke(o),h=r<l,f=i>c-l;if(r<s)u.scrollTop=h?0:r;else if(i>s+a){var d=Math.min(r,(f?c:i)-a);d!=s&&(u.scrollTop=d)}var p=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:o.scroller.scrollLeft,g=Ye(e)-(e.options.fixedGutter?o.gutters.offsetWidth:0),v=n-t>g;return v&&(n=t+g),t<10?u.scrollLeft=0:t<p?u.scrollLeft=Math.max(0,t-(v?0:10)):n>g+p-3&&(u.scrollLeft=n+(v?0:10)-g),u}function Ir(e,t,r){null==t&&null==r||Fr(e),null!=t&&(e.curOp.scrollLeft=(null==e.curOp.scrollLeft?e.doc.scrollLeft:e.curOp.scrollLeft)+t),null!=r&&(e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+r)}function zr(e){Fr(e);var t=e.getCursor(),r=t,n=t;e.options.lineWrapping||(r=t.ch?zo(t.line,t.ch-1):t,n=zo(t.line,t.ch+1)),e.curOp.scrollToPos={from:r,to:n,margin:e.options.cursorScrollMargin,isCursor:!0}}function Fr(e){var t=e.curOp.scrollToPos;if(t){e.curOp.scrollToPos=null;var r=pt(e,t.from),n=pt(e,t.to),i=Er(e,Math.min(r.left,n.left),Math.min(r.top,n.top)-t.margin,Math.max(r.right,n.right),Math.max(r.bottom,n.bottom)+t.margin);
3
- e.scrollTo(i.scrollLeft,i.scrollTop)}}function Rr(e,t,r,n){var i,o=e.doc;null==r&&(r="add"),"smart"==r&&(o.mode.indent?i=Ue(e,t):r="prev");var l=e.options.tabSize,s=Zn(o,t),a=Rl(s.text,null,l);s.stateAfter&&(s.stateAfter=null);var u,c=s.text.match(/^\s*/)[0];if(n||/\S/.test(s.text)){if("smart"==r&&(u=o.mode.indent(i,s.text.slice(c.length),s.text),u==El||u>150)){if(!n)return;r="prev"}}else u=0,r="not";"prev"==r?u=t>o.first?Rl(Zn(o,t-1).text,null,l):0:"add"==r?u=a+e.options.indentUnit:"subtract"==r?u=a-e.options.indentUnit:"number"==typeof r&&(u=a+r),u=Math.max(0,u);var h="",f=0;if(e.options.indentWithTabs)for(var d=Math.floor(u/l);d;--d)f+=l,h+="\t";if(f<u&&(h+=Oi(u-f)),h!=c)return Or(o,h,zo(t,0),zo(t,c.length),"+input"),s.stateAfter=null,!0;for(var d=0;d<o.sel.ranges.length;d++){var p=o.sel.ranges[d];if(p.head.line==t&&p.head.ch<c.length){var f=zo(t,c.length);Ce(o,d,new he(f,f));break}}}function Br(e,t,r,n){var i=t,o=t;return"number"==typeof t?o=Zn(e,pe(e,t)):i=ti(t),null==i?null:(n(o,i)&&e.cm&&It(e.cm,i,r),o)}function Gr(e,t){for(var r=e.doc.sel.ranges,n=[],i=0;i<r.length;i++){for(var o=t(r[i]);n.length&&Fo(o.from,Di(n).to)<=0;){var l=n.pop();if(Fo(l.from,o.from)<0){o.from=l.from;break}}n.push(o)}Wt(e,function(){for(var t=n.length-1;t>=0;t--)Or(e.doc,"",n[t].from,n[t].to,"+delete");zr(e)})}function Ur(e,t,r,n,i){function o(){var t=s+r;return t<e.first||t>=e.first+e.size?h=!1:(s=t,c=Zn(e,t))}function l(e){var t=(i?ho:fo)(c,a,r,!0);if(null==t){if(e||!o())return h=!1;a=i?(r<0?io:no)(c):r<0?c.text.length:0}else a=t;return!0}var s=t.line,a=t.ch,u=r,c=Zn(e,s),h=!0;if("char"==n)l();else if("column"==n)l(!0);else if("word"==n||"group"==n)for(var f=null,d="group"==n,p=e.cm&&e.cm.getHelper(t,"wordChars"),g=!0;!(r<0)||l(!g);g=!1){var v=c.text.charAt(a)||"\n",m=Ri(v,p)?"w":d&&"\n"==v?"n":!d||/\s/.test(v)?null:"p";if(!d||g||m||(m="s"),f&&f!=m){r<0&&(r=1,l());break}if(m&&(f=m),r>0&&!l(!g))break}var y=De(e,zo(s,a),t,u,!0);return h||(y.hitSide=!0),y}function Vr(e,t,r,n){var i,o=e.doc,l=t.left;if("page"==n){var s=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);i=t.top+r*(s-(r<0?1.5:.5)*yt(e.display))}else"line"==n&&(i=r>0?t.bottom+3:t.top-3);for(;;){var a=vt(e,l,i);if(!a.outside)break;if(r<0?i<=0:i>=o.height){a.hitSide=!0;break}i+=5*r}return a}function Kr(t,r,n,i){e.defaults[t]=r,n&&(el[t]=i?function(e,t,r){r!=tl&&n(e,t,r)}:n)}function jr(e){for(var t,r,n,i,o=e.split(/-(?!$)/),e=o[o.length-1],l=0;l<o.length-1;l++){var s=o[l];if(/^(cmd|meta|m)$/i.test(s))i=!0;else if(/^a(lt)?$/i.test(s))t=!0;else if(/^(c|ctrl|control)$/i.test(s))r=!0;else{if(!/^s(hift)$/i.test(s))throw new Error("Unrecognized modifier name: "+s);n=!0}}return t&&(e="Alt-"+e),r&&(e="Ctrl-"+e),i&&(e="Cmd-"+e),n&&(e="Shift-"+e),e}function Xr(e){return"string"==typeof e?cl[e]:e}function Yr(e,t,r,n,i){if(n&&n.shared)return _r(e,t,r,n,i);if(e.cm&&!e.cm.curOp)return At(e.cm,Yr)(e,t,r,n,i);var o=new vl(e,i),l=Fo(t,r);if(n&&zi(n,o,!1),l>0||0==l&&o.clearWhenEmpty!==!1)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=Ui("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(mn(e,t.line,t,r,o)||t.line!=r.line&&mn(e,r.line,t,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Io=!0}o.addToHistory&&ui(e,{from:t,to:r,origin:"markText"},e.sel,NaN);var s,a=t.line,u=e.cm;if(e.iter(a,r.line+1,function(e){u&&o.collapsed&&!u.options.lineWrapping&&yn(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=t.line&&ei(e,0),tn(e,new Qr(o,a==t.line?t.ch:null,a==r.line?r.ch:null)),++a}),o.collapsed&&e.iter(t.line,r.line+1,function(t){Cn(e,t)&&ei(t,0)}),o.clearOnEnter&&Wl(o,"beforeCursorEnter",function(){o.clear()}),o.readOnly&&(Eo=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++gl,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)Et(u,t.line,r.line+1);else if(o.className||o.title||o.startStyle||o.endStyle||o.css)for(var c=t.line;c<=r.line;c++)It(u,c,"text");o.atomic&&We(u.doc),Li(u,"markerAdded",u,o)}return o}function _r(e,t,r,n,i){n=zi(n),n.shared=!1;var o=[Yr(e,t,r,n,i)],l=o[0],s=n.widgetNode;return $n(e,function(e){s&&(n.widgetNode=s.cloneNode(!0)),o.push(Yr(e,ge(e,t),ge(e,r),n,i));for(var a=0;a<e.linked.length;++a)if(e.linked[a].isParent)return;l=Di(o)}),new ml(o,l)}function $r(e){return e.findMarks(zo(e.first,0),e.clipPos(zo(e.lastLine())),function(e){return e.parent})}function qr(e,t){for(var r=0;r<t.length;r++){var n=t[r],i=n.find(),o=e.clipPos(i.from),l=e.clipPos(i.to);if(Fo(o,l)){var s=Yr(e,o,l,n.primary,n.primary.type);n.markers.push(s),s.parent=n}}}function Zr(e){for(var t=0;t<e.length;t++){var r=e[t],n=[r.primary.doc];$n(r.primary.doc,function(e){n.push(e)});for(var i=0;i<r.markers.length;i++){var o=r.markers[i];Hi(n,o.doc)==-1&&(o.parent=null,r.markers.splice(i--,1))}}}function Qr(e,t,r){this.marker=e,this.from=t,this.to=r}function Jr(e,t){if(e)for(var r=0;r<e.length;++r){var n=e[r];if(n.marker==t)return n}}function en(e,t){for(var r,n=0;n<e.length;++n)e[n]!=t&&(r||(r=[])).push(e[n]);return r}function tn(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}function rn(e,t,r){if(e)for(var n,i=0;i<e.length;++i){var o=e[i],l=o.marker,s=null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t);if(s||o.from==t&&"bookmark"==l.type&&(!r||!o.marker.insertLeft)){var a=null==o.to||(l.inclusiveRight?o.to>=t:o.to>t);(n||(n=[])).push(new Qr(l,o.from,a?null:o.to))}}return n}function nn(e,t,r){if(e)for(var n,i=0;i<e.length;++i){var o=e[i],l=o.marker,s=null==o.to||(l.inclusiveRight?o.to>=t:o.to>t);if(s||o.from==t&&"bookmark"==l.type&&(!r||o.marker.insertLeft)){var a=null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t);(n||(n=[])).push(new Qr(l,a?null:o.from-t,null==o.to?null:o.to-t))}}return n}function on(e,t){if(t.full)return null;var r=me(e,t.from.line)&&Zn(e,t.from.line).markedSpans,n=me(e,t.to.line)&&Zn(e,t.to.line).markedSpans;if(!r&&!n)return null;var i=t.from.ch,o=t.to.ch,l=0==Fo(t.from,t.to),s=rn(r,i,l),a=nn(n,o,l),u=1==t.text.length,c=Di(t.text).length+(u?i:0);if(s)for(var h=0;h<s.length;++h){var f=s[h];if(null==f.to){var d=Jr(a,f.marker);d?u&&(f.to=null==d.to?null:d.to+c):f.to=i}}if(a)for(var h=0;h<a.length;++h){var f=a[h];if(null!=f.to&&(f.to+=c),null==f.from){var d=Jr(s,f.marker);d||(f.from=c,u&&(s||(s=[])).push(f))}else f.from+=c,u&&(s||(s=[])).push(f)}s&&(s=ln(s)),a&&a!=s&&(a=ln(a));var p=[s];if(!u){var g,v=t.text.length-2;if(v>0&&s)for(var h=0;h<s.length;++h)null==s[h].to&&(g||(g=[])).push(new Qr(s[h].marker,null,null));for(var h=0;h<v;++h)p.push(g);p.push(a)}return p}function ln(e){for(var t=0;t<e.length;++t){var r=e[t];null!=r.from&&r.from==r.to&&r.marker.clearWhenEmpty!==!1&&e.splice(t--,1)}return e.length?e:null}function sn(e,t){var r=gi(e,t),n=on(e,t);if(!r)return n;if(!n)return r;for(var i=0;i<r.length;++i){var o=r[i],l=n[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(r[i]=l)}return r}function an(e,t,r){var n=null;if(e.iter(t.line,r.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var r=e.markedSpans[t].marker;!r.readOnly||n&&Hi(n,r)!=-1||(n||(n=[])).push(r)}}),!n)return null;for(var i=[{from:t,to:r}],o=0;o<n.length;++o)for(var l=n[o],s=l.find(0),a=0;a<i.length;++a){var u=i[a];if(!(Fo(u.to,s.from)<0||Fo(u.from,s.to)>0)){var c=[a,1],h=Fo(u.from,s.from),f=Fo(u.to,s.to);(h<0||!l.inclusiveLeft&&!h)&&c.push({from:u.from,to:s.from}),(f>0||!l.inclusiveRight&&!f)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),a+=c.length-1}}return i}function un(e){var t=e.markedSpans;if(t){for(var r=0;r<t.length;++r)t[r].marker.detachLine(e);e.markedSpans=null}}function cn(e,t){if(t){for(var r=0;r<t.length;++r)t[r].marker.attachLine(e);e.markedSpans=t}}function hn(e){return e.inclusiveLeft?-1:0}function fn(e){return e.inclusiveRight?1:0}function dn(e,t){var r=e.lines.length-t.lines.length;if(0!=r)return r;var n=e.find(),i=t.find(),o=Fo(n.from,i.from)||hn(e)-hn(t);if(o)return-o;var l=Fo(n.to,i.to)||fn(e)-fn(t);return l?l:t.id-e.id}function pn(e,t){var r,n=Io&&e.markedSpans;if(n)for(var i,o=0;o<n.length;++o)i=n[o],i.marker.collapsed&&null==(t?i.from:i.to)&&(!r||dn(r,i.marker)<0)&&(r=i.marker);return r}function gn(e){return pn(e,!0)}function vn(e){return pn(e,!1)}function mn(e,t,r,n,i){var o=Zn(e,t),l=Io&&o.markedSpans;if(l)for(var s=0;s<l.length;++s){var a=l[s];if(a.marker.collapsed){var u=a.marker.find(0),c=Fo(u.from,r)||hn(a.marker)-hn(i),h=Fo(u.to,n)||fn(a.marker)-fn(i);if(!(c>=0&&h<=0||c<=0&&h>=0)&&(c<=0&&(Fo(u.to,r)>0||a.marker.inclusiveRight&&i.inclusiveLeft)||c>=0&&(Fo(u.from,n)<0||a.marker.inclusiveLeft&&i.inclusiveRight)))return!0}}}function yn(e){for(var t;t=gn(e);)e=t.find(-1,!0).line;return e}function bn(e){for(var t,r;t=vn(e);)e=t.find(1,!0).line,(r||(r=[])).push(e);return r}function wn(e,t){var r=Zn(e,t),n=yn(r);return r==n?t:ti(n)}function xn(e,t){if(t>e.lastLine())return t;var r,n=Zn(e,t);if(!Cn(e,n))return t;for(;r=vn(n);)n=r.find(1,!0).line;return ti(n)+1}function Cn(e,t){var r=Io&&t.markedSpans;if(r)for(var n,i=0;i<r.length;++i)if(n=r[i],n.marker.collapsed){if(null==n.from)return!0;if(!n.marker.widgetNode&&0==n.from&&n.marker.inclusiveLeft&&Sn(e,t,n))return!0}}function Sn(e,t,r){if(null==r.to){var n=r.marker.find(1,!0);return Sn(e,n.line,Jr(n.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==t.text.length)return!0;for(var i,o=0;o<t.markedSpans.length;++o)if(i=t.markedSpans[o],i.marker.collapsed&&!i.marker.widgetNode&&i.from==r.to&&(null==i.to||i.to!=r.from)&&(i.marker.inclusiveLeft||r.marker.inclusiveRight)&&Sn(e,t,i))return!0}function Ln(e,t,r){ni(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&Ir(e,null,r)}function Tn(e){if(null!=e.height)return e.height;var t=e.doc.cm;if(!t)return 0;if(!Yl(document.body,e.node)){var r="position: relative;";e.coverGutter&&(r+="margin-left: -"+t.display.gutters.offsetWidth+"px;"),e.noHScroll&&(r+="width: "+t.display.wrapper.clientWidth+"px;"),Ki(t.display.measure,Ui("div",[e.node],null,r))}return e.height=e.node.parentNode.offsetHeight}function kn(e,t,r,n){var i=new yl(e,r,n),o=e.cm;return o&&i.noHScroll&&(o.display.alignWidgets=!0),Br(e,t,"widget",function(t){var r=t.widgets||(t.widgets=[]);if(null==i.insertAt?r.push(i):r.splice(Math.min(r.length-1,Math.max(0,i.insertAt)),0,i),i.line=t,o&&!Cn(e,t)){var n=ni(t)<e.scrollTop;ei(t,t.height+Tn(i)),n&&Ir(o,null,i.height),o.curOp.forceUpdate=!0}return!0}),i}function Mn(e,t,r,n){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),un(e),cn(e,r);var i=n?n(e):1;i!=e.height&&ei(e,i)}function Nn(e){e.parent=null,un(e)}function Wn(e,t){if(e)for(;;){var r=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!r)break;e=e.slice(0,r.index)+e.slice(r.index+r[0].length);var n=r[1]?"bgClass":"textClass";null==t[n]?t[n]=r[2]:new RegExp("(?:^|s)"+r[2]+"(?:$|s)").test(t[n])||(t[n]+=" "+r[2])}return e}function An(t,r){if(t.blankLine)return t.blankLine(r);if(t.innerMode){var n=e.innerMode(t,r);return n.mode.blankLine?n.mode.blankLine(n.state):void 0}}function On(t,r,n,i){for(var o=0;o<10;o++){i&&(i[0]=e.innerMode(t,n).mode);var l=t.token(r,n);if(r.pos>r.start)return l}throw new Error("Mode "+t.name+" failed to advance stream.")}function Dn(e,t,r,n){function i(e){return{start:h.start,end:h.pos,string:h.current(),type:o||null,state:e?sl(l.mode,c):c}}var o,l=e.doc,s=l.mode;t=ge(l,t);var a,u=Zn(l,t.line),c=Ue(e,t.line,r),h=new pl(u.text,e.options.tabSize);for(n&&(a=[]);(n||h.pos<t.ch)&&!h.eol();)h.start=h.pos,o=On(s,h,c),n&&a.push(i(!0));return n?a:i()}function Hn(e,t,r,n,i,o,l){var s=r.flattenSpans;null==s&&(s=e.options.flattenSpans);var a,u=0,c=null,h=new pl(t,e.options.tabSize),f=e.options.addModeClass&&[null];for(""==t&&Wn(An(r,n),o);!h.eol();){if(h.pos>e.options.maxHighlightLength?(s=!1,l&&In(e,t,n,h.pos),h.pos=t.length,a=null):a=Wn(On(r,h,n,f),o),f){var d=f[0].name;d&&(a="m-"+(a?d+" "+a:d))}if(!s||c!=a){for(;u<h.start;)u=Math.min(h.start,u+5e4),i(u,c);c=a}h.start=h.pos}for(;u<h.pos;){var p=Math.min(h.pos,u+5e4);i(p,c),u=p}}function Pn(e,t,r,n){var i=[e.state.modeGen],o={};Hn(e,t.text,e.doc.mode,r,function(e,t){i.push(e,t)},o,n);for(var l=0;l<e.state.overlays.length;++l){var s=e.state.overlays[l],a=1,u=0;Hn(e,t.text,s.mode,!0,function(e,t){for(var r=a;u<e;){var n=i[a];n>e&&i.splice(a,1,e,i[a+1],n),a+=2,u=Math.min(e,n)}if(t)if(s.opaque)i.splice(r,a-r,e,"cm-overlay "+t),a=r+2;else for(;r<a;r+=2){var o=i[r+1];i[r+1]=(o?o+" ":"")+"cm-overlay "+t}},o)}return{styles:i,classes:o.bgClass||o.textClass?o:null}}function En(e,t,r){if(!t.styles||t.styles[0]!=e.state.modeGen){var n=Ue(e,ti(t)),i=Pn(e,t,t.text.length>e.options.maxHighlightLength?sl(e.doc.mode,n):n);t.stateAfter=n,t.styles=i.styles,i.classes?t.styleClasses=i.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.frontier&&e.doc.frontier++}return t.styles}function In(e,t,r,n){var i=e.doc.mode,o=new pl(t,e.options.tabSize);for(o.start=o.pos=n||0,""==t&&An(i,r);!o.eol();)On(i,o,r),o.start=o.pos}function zn(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?xl:wl;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function Fn(e,t){var r=Ui("span",null,null,xo?"padding-right: .1px":null),n={pre:Ui("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:e,splitSpaces:(bo||xo)&&e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o,l=i?t.rest[i-1]:t.line;n.pos=0,n.addToken=Bn,Qi(e.display.measure)&&(o=ii(l))&&(n.addToken=Un(n.addToken,o)),n.map=[];var s=t!=e.display.externalMeasured&&ti(l);Kn(l,n,En(e,l,s)),l.styleClasses&&(l.styleClasses.bgClass&&(n.bgClass=Yi(l.styleClasses.bgClass,n.bgClass||"")),l.styleClasses.textClass&&(n.textClass=Yi(l.styleClasses.textClass,n.textClass||""))),0==n.map.length&&n.map.push(0,0,n.content.appendChild(Zi(e.display.measure))),0==i?(t.measure.map=n.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(n.map),(t.measure.caches||(t.measure.caches=[])).push({}))}return xo&&/\bcm-tab\b/.test(n.content.lastChild.className)&&(n.content.className="cm-tab-wrap-hack"),Dl(e,"renderLine",e,t.line,n.pre),n.pre.className&&(n.textClass=Yi(n.pre.className,n.textClass||"")),n}function Rn(e){var t=Ui("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function Bn(e,t,r,n,i,o,l){if(t){var s=e.splitSpaces?t.replace(/ {3,}/g,Gn):t,a=e.cm.state.specialChars,u=!1;if(a.test(t))for(var c=document.createDocumentFragment(),h=0;;){a.lastIndex=h;var f=a.exec(t),d=f?f.index-h:t.length-h;if(d){var p=document.createTextNode(s.slice(h,h+d));bo&&wo<9?c.appendChild(Ui("span",[p])):c.appendChild(p),e.map.push(e.pos,e.pos+d,p),e.col+=d,e.pos+=d}if(!f)break;if(h+=d+1,"\t"==f[0]){var g=e.cm.options.tabSize,v=g-e.col%g,p=c.appendChild(Ui("span",Oi(v),"cm-tab"));p.setAttribute("role","presentation"),p.setAttribute("cm-text","\t"),e.col+=v}else if("\r"==f[0]||"\n"==f[0]){var p=c.appendChild(Ui("span","\r"==f[0]?"␍":"␤","cm-invalidchar"));p.setAttribute("cm-text",f[0]),e.col+=1}else{var p=e.cm.options.specialCharPlaceholder(f[0]);p.setAttribute("cm-text",f[0]),bo&&wo<9?c.appendChild(Ui("span",[p])):c.appendChild(p),e.col+=1}e.map.push(e.pos,e.pos+1,p),e.pos++}else{e.col+=t.length;var c=document.createTextNode(s);e.map.push(e.pos,e.pos+t.length,c),bo&&wo<9&&(u=!0),e.pos+=t.length}if(r||n||i||u||l){var m=r||"";n&&(m+=n),i&&(m+=i);var y=Ui("span",[c],m,l);return o&&(y.title=o),e.content.appendChild(y)}e.content.appendChild(c)}}function Gn(e){for(var t=" ",r=0;r<e.length-2;++r)t+=r%2?" ":" ";return t+=" "}function Un(e,t){return function(r,n,i,o,l,s,a){i=i?i+" cm-force-border":"cm-force-border";for(var u=r.pos,c=u+n.length;;){for(var h=0;h<t.length;h++){var f=t[h];if(f.to>u&&f.from<=u)break}if(f.to>=c)return e(r,n,i,o,l,s,a);e(r,n.slice(0,f.to-u),i,o,null,s,a),o=null,n=n.slice(f.to-u),u=f.to}}}function Vn(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t}function Kn(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var l,s,a,u,c,h,f,d=i.length,p=0,g=1,v="",m=0;;){if(m==p){a=u=c=h=s="",f=null,m=1/0;for(var y,b=[],w=0;w<n.length;++w){var x=n[w],C=x.marker;"bookmark"==C.type&&x.from==p&&C.widgetNode?b.push(C):x.from<=p&&(null==x.to||x.to>p||C.collapsed&&x.to==p&&x.from==p)?(null!=x.to&&x.to!=p&&m>x.to&&(m=x.to,u=""),C.className&&(a+=" "+C.className),C.css&&(s=(s?s+";":"")+C.css),C.startStyle&&x.from==p&&(c+=" "+C.startStyle),C.endStyle&&x.to==m&&(y||(y=[])).push(C.endStyle,x.to),C.title&&!h&&(h=C.title),C.collapsed&&(!f||dn(f.marker,C)<0)&&(f=x)):x.from>p&&m>x.from&&(m=x.from)}if(y)for(var w=0;w<y.length;w+=2)y[w+1]==m&&(u+=" "+y[w]);if(f&&(f.from||0)==p){if(Vn(t,(null==f.to?d+1:f.to)-p,f.marker,null==f.from),null==f.to)return;f.to==p&&(f=!1)}if(!f&&b.length)for(var w=0;w<b.length;++w)Vn(t,0,b[w])}if(p>=d)break;for(var S=Math.min(d,m);;){if(v){var L=p+v.length;if(!f){var T=L>S?v.slice(0,S-p):v;t.addToken(t,T,l?l+a:a,c,p+T.length==m?u:"",h,s)}if(L>=S){v=v.slice(S-p),p=S;break}p=L,c=""}v=i.slice(o,o=r[g++]),l=zn(r[g++],t.cm.options)}}else for(var g=1;g<r.length;g+=2)t.addToken(t,i.slice(o,o=r[g]),zn(r[g+1],t.cm.options))}function jn(e,t){return 0==t.from.ch&&0==t.to.ch&&""==Di(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function Xn(e,t,r,n){function i(e){return r?r[e]:null}function o(e,r,i){Mn(e,r,i,n),Li(e,"change",e,t)}function l(e,t){for(var r=e,o=[];r<t;++r)o.push(new bl(u[r],i(r),n));return o}var s=t.from,a=t.to,u=t.text,c=Zn(e,s.line),h=Zn(e,a.line),f=Di(u),d=i(u.length-1),p=a.line-s.line;if(t.full)e.insert(0,l(0,u.length)),e.remove(u.length,e.size-u.length);else if(jn(e,t)){var g=l(0,u.length-1);o(h,h.text,d),p&&e.remove(s.line,p),g.length&&e.insert(s.line,g)}else if(c==h)if(1==u.length)o(c,c.text.slice(0,s.ch)+f+c.text.slice(a.ch),d);else{var g=l(1,u.length-1);g.push(new bl(f+c.text.slice(a.ch),d,n)),o(c,c.text.slice(0,s.ch)+u[0],i(0)),e.insert(s.line+1,g)}else if(1==u.length)o(c,c.text.slice(0,s.ch)+u[0]+h.text.slice(a.ch),i(0)),e.remove(s.line+1,p);else{o(c,c.text.slice(0,s.ch)+u[0],i(0)),o(h,f+h.text.slice(a.ch),d);var g=l(1,u.length-1);p>1&&e.remove(s.line+1,p-1),e.insert(s.line+1,g)}Li(e,"change",e,t)}function Yn(e){this.lines=e,this.parent=null;for(var t=0,r=0;t<e.length;++t)e[t].parent=this,r+=e[t].height;this.height=r}function _n(e){this.children=e;for(var t=0,r=0,n=0;n<e.length;++n){var i=e[n];t+=i.chunkSize(),r+=i.height,i.parent=this}this.size=t,this.height=r,this.parent=null}function $n(e,t,r){function n(e,i,o){if(e.linked)for(var l=0;l<e.linked.length;++l){var s=e.linked[l];if(s.doc!=i){var a=o&&s.sharedHist;r&&!a||(t(s.doc,a),n(s.doc,e,a))}}}n(e,null,!0)}function qn(e,t){if(t.cm)throw new Error("This document is already in use.");e.doc=t,t.cm=e,l(e),r(e),e.options.lineWrapping||f(e),e.options.mode=t.modeOption,Et(e)}function Zn(e,t){if(t-=e.first,t<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(t<o){r=i;break}t-=o}return r.lines[t]}function Qn(e,t,r){var n=[],i=t.line;return e.iter(t.line,r.line+1,function(e){var o=e.text;i==r.line&&(o=o.slice(0,r.ch)),i==t.line&&(o=o.slice(t.ch)),n.push(o),++i}),n}function Jn(e,t,r){var n=[];return e.iter(t,r,function(e){n.push(e.text)}),n}function ei(e,t){var r=t-e.height;if(r)for(var n=e;n;n=n.parent)n.height+=r}function ti(e){if(null==e.parent)return null;for(var t=e.parent,r=Hi(t.lines,e),n=t.parent;n;t=n,n=n.parent)for(var i=0;n.children[i]!=t;++i)r+=n.children[i].chunkSize();return r+t.first}function ri(e,t){var r=e.first;e:do{for(var n=0;n<e.children.length;++n){var i=e.children[n],o=i.height;if(t<o){e=i;continue e}t-=o,r+=i.chunkSize()}return r}while(!e.lines);for(var n=0;n<e.lines.length;++n){var l=e.lines[n],s=l.height;if(t<s)break;t-=s}return r+n}function ni(e){e=yn(e);for(var t=0,r=e.parent,n=0;n<r.lines.length;++n){var i=r.lines[n];if(i==e)break;t+=i.height}for(var o=r.parent;o;r=o,o=r.parent)for(var n=0;n<o.children.length;++n){var l=o.children[n];if(l==r)break;t+=l.height}return t}function ii(e){var t=e.order;return null==t&&(t=e.order=ls(e.text)),t}function oi(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function li(e,t){var r={from:Y(t.from),to:Qo(t),text:Qn(e,t.from,t.to)};return di(e,r,t.from.line,t.to.line+1),$n(e,function(e){di(e,r,t.from.line,t.to.line+1)},!0),r}function si(e){for(;e.length;){var t=Di(e);if(!t.ranges)break;e.pop()}}function ai(e,t){return t?(si(e.done),Di(e.done)):e.done.length&&!Di(e.done).ranges?Di(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),Di(e.done)):void 0}function ui(e,t,r,n){var i=e.history;i.undone.length=0;var o,l=+new Date;if((i.lastOp==n||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&e.cm&&i.lastModTime>l-e.cm.options.historyEventDelay||"*"==t.origin.charAt(0)))&&(o=ai(i,i.lastOp==n))){var s=Di(o.changes);0==Fo(t.from,t.to)&&0==Fo(t.from,s.to)?s.to=Qo(t):o.changes.push(li(e,t))}else{var a=Di(i.done);for(a&&a.ranges||fi(e.sel,i.done),o={changes:[li(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=l,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,s||Dl(e,"historyAdded")}function ci(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}function hi(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||ci(e,o,Di(i.done),t))?i.done[i.done.length-1]=t:fi(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&n.clearRedo!==!1&&si(i.undone)}function fi(e,t){var r=Di(t);r&&r.ranges&&r.equals(e)||t.push(e)}function di(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o})}function pi(e){if(!e)return null;for(var t,r=0;r<e.length;++r)e[r].marker.explicitlyCleared?t||(t=e.slice(0,r)):t&&t.push(e[r]);return t?t.length?t:null:e}function gi(e,t){var r=t["spans_"+e.id];if(!r)return null;for(var n=0,i=[];n<t.text.length;++n)i.push(pi(r[n]));return i}function vi(e,t,r){for(var n=0,i=[];n<e.length;++n){var o=e[n];if(o.ranges)i.push(r?ce.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];i.push({changes:s});for(var a=0;a<l.length;++a){var u,c=l[a];if(s.push({from:c.from,to:c.to,text:c.text}),t)for(var h in c)(u=h.match(/^spans_(\d+)$/))&&Hi(t,Number(u[1]))>-1&&(Di(s)[h]=c[h],delete c[h])}}}return i}function mi(e,t,r,n){r<e.line?e.line+=n:t<e.line&&(e.line=t,e.ch=0)}function yi(e,t,r,n){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||(o=e[i]=o.deepCopy(),o.copied=!0);for(var s=0;s<o.ranges.length;s++)mi(o.ranges[s].anchor,t,r,n),mi(o.ranges[s].head,t,r,n)}else{for(var s=0;s<o.changes.length;++s){var a=o.changes[s];if(r<a.from.line)a.from=zo(a.from.line+n,a.from.ch),a.to=zo(a.to.line+n,a.to.ch);else if(t<=a.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function bi(e,t){var r=t.from.line,n=t.to.line,i=t.text.length-(n-r)-1;yi(e.done,r,n,i),yi(e.undone,r,n,i)}function wi(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function xi(e){return e.target||e.srcElement}function Ci(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),Ao&&e.ctrlKey&&1==t&&(t=3),t}function Si(e,t,r){var n=e._handlers&&e._handlers[t];return r?n&&n.length>0?n.slice():Al:n||Al}function Li(e,t){function r(e){return function(){e.apply(null,o)}}var n=Si(e,t,!1);if(n.length){var i,o=Array.prototype.slice.call(arguments,2);Ko?i=Ko.delayedCallbacks:Hl?i=Hl:(i=Hl=[],setTimeout(Ti,0));for(var l=0;l<n.length;++l)i.push(r(n[l]))}}function Ti(){var e=Hl;Hl=null;for(var t=0;t<e.length;++t)e[t]()}function ki(e,t,r){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),Dl(e,r||t.type,e,t),wi(t)||t.codemirrorIgnore}function Mi(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var r=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),n=0;n<t.length;++n)Hi(r,t[n])==-1&&r.push(t[n])}function Ni(e,t){return Si(e,t).length>0}function Wi(e){e.prototype.on=function(e,t){Wl(this,e,t)},e.prototype.off=function(e,t){Ol(this,e,t)}}function Ai(){this.id=null}function Oi(e){for(;Gl.length<=e;)Gl.push(Di(Gl)+" ");return Gl[e]}function Di(e){return e[e.length-1]}function Hi(e,t){for(var r=0;r<e.length;++r)if(e[r]==t)return r;return-1}function Pi(e,t){for(var r=[],n=0;n<e.length;n++)r[n]=t(e[n],n);return r}function Ei(){}function Ii(e,t){var r;return Object.create?r=Object.create(e):(Ei.prototype=e,r=new Ei),t&&zi(t,r),r}function zi(e,t,r){t||(t={});for(var n in e)!e.hasOwnProperty(n)||r===!1&&t.hasOwnProperty(n)||(t[n]=e[n]);return t}function Fi(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function Ri(e,t){return t?!!(t.source.indexOf("\\w")>-1&&jl(e))||t.test(e):jl(e)}function Bi(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}function Gi(e){return e.charCodeAt(0)>=768&&Xl.test(e)}function Ui(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function Vi(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function Ki(e,t){return Vi(e).appendChild(t)}function ji(){for(var e=document.activeElement;e&&e.root&&e.root.activeElement;)e=e.root.activeElement;return e}function Xi(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}function Yi(e,t){for(var r=e.split(" "),n=0;n<r.length;n++)r[n]&&!Xi(r[n]).test(t)&&(t+=" "+r[n]);return t}function _i(e){if(document.body.getElementsByClassName)for(var t=document.body.getElementsByClassName("CodeMirror"),r=0;r<t.length;r++){var n=t[r].CodeMirror;n&&e(n)}}function $i(){Ql||(qi(),Ql=!0)}function qi(){var e;Wl(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,_i(Kt)},100))}),Wl(window,"blur",function(){_i(mr)})}function Zi(e){if(null==_l){var t=Ui("span","​");Ki(e,Ui("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(_l=t.offsetWidth<=1&&t.offsetHeight>2&&!(bo&&wo<8))}var r=_l?Ui("span","​"):Ui("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}function Qi(e){if(null!=$l)return $l;var t=Ki(e,document.createTextNode("AخA")),r=Vl(t,0,1).getBoundingClientRect();if(!r||r.left==r.right)return!1;var n=Vl(t,1,2).getBoundingClientRect();return $l=n.right-r.right<3}function Ji(e){if(null!=ns)return ns;var t=Ki(e,Ui("span","x")),r=t.getBoundingClientRect(),n=Vl(t,0,1).getBoundingClientRect();return ns=Math.abs(r.left-n.left)>1}function eo(e,t,r,n){if(!e)return n(t,r,"ltr");for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<r&&l.to>t||t==r&&l.to==t)&&(n(Math.max(l.from,t),Math.min(l.to,r),1==l.level?"rtl":"ltr"),i=!0)}i||n(t,r,"ltr")}function to(e){return e.level%2?e.to:e.from}function ro(e){return e.level%2?e.from:e.to}function no(e){var t=ii(e);return t?to(t[0]):0}function io(e){var t=ii(e);return t?ro(Di(t)):e.text.length}function oo(e,t){var r=Zn(e.doc,t),n=yn(r);n!=r&&(t=ti(n));var i=ii(n),o=i?i[0].level%2?io(n):no(n):0;return zo(t,o)}function lo(e,t){for(var r,n=Zn(e.doc,t);r=vn(n);)n=r.find(1,!0).line,t=null;var i=ii(n),o=i?i[0].level%2?no(n):io(n):n.text.length;return zo(null==t?ti(n):t,o)}function so(e,t){var r=oo(e,t.line),n=Zn(e.doc,r.line),i=ii(n);if(!i||0==i[0].level){var o=Math.max(0,n.text.search(/\S/)),l=t.line==r.line&&t.ch<=o&&t.ch;return zo(r.line,l?0:o)}return r}function ao(e,t,r){var n=e[0].level;return t==n||r!=n&&t<r}function uo(e,t){os=null;for(var r,n=0;n<e.length;++n){var i=e[n];if(i.from<t&&i.to>t)return n;if(i.from==t||i.to==t){if(null!=r)return ao(e,i.level,e[r].level)?(i.from!=i.to&&(os=r),n):(i.from!=i.to&&(os=n),r);r=n}}return r}function co(e,t,r,n){if(!n)return t+r;do t+=r;while(t>0&&Gi(e.text.charAt(t)));return t}function ho(e,t,r,n){var i=ii(e);if(!i)return fo(e,t,r,n);for(var o=uo(i,t),l=i[o],s=co(e,t,l.level%2?-r:r,n);;){if(s>l.from&&s<l.to)return s;if(s==l.from||s==l.to)return uo(i,s)==o?s:(l=i[o+=r],r>0==l.level%2?l.to:l.from);if(l=i[o+=r],!l)return null;s=r>0==l.level%2?co(e,l.to,-1,n):co(e,l.from,1,n)}}function fo(e,t,r,n){var i=t+r;if(n)for(;i>0&&Gi(e.text.charAt(i));)i+=r;return i<0||i>e.text.length?null:i}var po=navigator.userAgent,go=navigator.platform,vo=/gecko\/\d/i.test(po),mo=/MSIE \d/.test(po),yo=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(po),bo=mo||yo,wo=bo&&(mo?document.documentMode||6:yo[1]),xo=/WebKit\//.test(po),Co=xo&&/Qt\/\d+\.\d+/.test(po),So=/Chrome\//.test(po),Lo=/Opera\//.test(po),To=/Apple Computer/.test(navigator.vendor),ko=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(po),Mo=/PhantomJS/.test(po),No=/AppleWebKit/.test(po)&&/Mobile\/\w+/.test(po),Wo=No||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(po),Ao=No||/Mac/.test(go),Oo=/win/i.test(go),Do=Lo&&po.match(/Version\/(\d*\.\d*)/);Do&&(Do=Number(Do[1])),Do&&Do>=15&&(Lo=!1,xo=!0);var Ho=Ao&&(Co||Lo&&(null==Do||Do<12.11)),Po=vo||bo&&wo>=9,Eo=!1,Io=!1;g.prototype=zi({update:function(e){var t=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,n=e.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=t?n+"px":"0";var i=e.viewHeight-(t?n:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(r?n:0);this.horiz.firstChild.style.width=e.scrollWidth-e.clientWidth+o+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==n&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?n:0,bottom:t?n:0}},setScrollLeft:function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz)},setScrollTop:function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert)},zeroWidthHack:function(){var e=Ao&&!ko?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new Ai,this.disableVert=new Ai},enableZeroWidthBar:function(e,t){function r(){var n=e.getBoundingClientRect(),i=document.elementFromPoint(n.left+1,n.bottom-1);i!=e?e.style.pointerEvents="none":t.set(1e3,r)}e.style.pointerEvents="auto",t.set(1e3,r)},clear:function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)}},g.prototype),v.prototype=zi({update:function(){return{bottom:0,right:0}},setScrollLeft:function(){},setScrollTop:function(){},clear:function(){}},v.prototype),e.scrollbarModel={"native":g,"null":v},T.prototype.signal=function(e,t){Ni(e,t)&&this.events.push(arguments)},T.prototype.finish=function(){for(var e=0;e<this.events.length;e++)Dl.apply(null,this.events[e])};var zo=e.Pos=function(e,t){return this instanceof zo?(this.line=e,void(this.ch=t)):new zo(e,t)},Fo=e.cmpPos=function(e,t){return e.line-t.line||e.ch-t.ch},Ro=null;re.prototype=zi({init:function(e){function t(e){
4
- if(n.somethingSelected())Ro=n.getSelections(),r.inaccurateSelection&&(r.prevInput="",r.inaccurateSelection=!1,o.value=Ro.join("\n"),Ul(o));else{if(!n.options.lineWiseCopyCut)return;var t=ee(n);Ro=t.text,"cut"==e.type?n.setSelections(t.ranges,null,Il):(r.prevInput="",o.value=t.text.join("\n"),Ul(o))}"cut"==e.type&&(n.state.cutIncoming=!0)}var r=this,n=this.cm,i=this.wrapper=ne(),o=this.textarea=i.firstChild;e.wrapper.insertBefore(i,e.wrapper.firstChild),No&&(o.style.width="0px"),Wl(o,"input",function(){bo&&wo>=9&&r.hasSelection&&(r.hasSelection=null),r.poll()}),Wl(o,"paste",function(e){ki(n,e)||Q(e,n)||(n.state.pasteIncoming=!0,r.fastPoll())}),Wl(o,"cut",t),Wl(o,"copy",t),Wl(e.scroller,"paste",function(t){jt(e,t)||ki(n,t)||(n.state.pasteIncoming=!0,r.focus())}),Wl(e.lineSpace,"selectstart",function(t){jt(e,t)||kl(t)}),Wl(o,"compositionstart",function(){var e=n.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:n.markText(e,n.getCursor("to"),{className:"CodeMirror-composing"})}}),Wl(o,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},prepareSelection:function(){var e=this.cm,t=e.display,r=e.doc,n=Ee(e);if(e.options.moveInputWithCursor){var i=dt(e,r.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),l=t.lineDiv.getBoundingClientRect();n.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+l.top-o.top)),n.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+l.left-o.left))}return n},showSelection:function(e){var t=this.cm,r=t.display;Ki(r.cursorDiv,e.cursors),Ki(r.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},reset:function(e){if(!this.contextMenuPending){var t,r,n=this.cm,i=n.doc;if(n.somethingSelected()){this.prevInput="";var o=i.sel.primary();t=rs&&(o.to().line-o.from().line>100||(r=n.getSelection()).length>1e3);var l=t?"-":r||n.getSelection();this.textarea.value=l,n.state.focused&&Ul(this.textarea),bo&&wo>=9&&(this.hasSelection=l)}else e||(this.prevInput=this.textarea.value="",bo&&wo>=9&&(this.hasSelection=null));this.inaccurateSelection=t}},getField:function(){return this.textarea},supportsTouch:function(){return!1},focus:function(){if("nocursor"!=this.cm.options.readOnly&&(!Wo||ji()!=this.textarea))try{this.textarea.focus()}catch(e){}},blur:function(){this.textarea.blur()},resetPosition:function(){this.wrapper.style.top=this.wrapper.style.left=0},receivedFocus:function(){this.slowPoll()},slowPoll:function(){var e=this;e.pollingFast||e.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},fastPoll:function(){function e(){var n=r.poll();n||t?(r.pollingFast=!1,r.slowPoll()):(t=!0,r.polling.set(60,e))}var t=!1,r=this;r.pollingFast=!0,r.polling.set(20,e)},poll:function(){var e=this.cm,t=this.textarea,r=this.prevInput;if(this.contextMenuPending||!e.state.focused||ts(t)&&!r&&!this.composing||e.isReadOnly()||e.options.disableInput||e.state.keySeq)return!1;var n=t.value;if(n==r&&!e.somethingSelected())return!1;if(bo&&wo>=9&&this.hasSelection===n||Ao&&/[\uf700-\uf7ff]/.test(n))return e.display.input.reset(),!1;if(e.doc.sel==e.display.selForContextMenu){var i=n.charCodeAt(0);if(8203!=i||r||(r="​"),8666==i)return this.reset(),this.cm.execCommand("undo")}for(var o=0,l=Math.min(r.length,n.length);o<l&&r.charCodeAt(o)==n.charCodeAt(o);)++o;var s=this;return Wt(e,function(){Z(e,n.slice(o),r.length-o,null,s.composing?"*compose":null),n.length>1e3||n.indexOf("\n")>-1?t.value=s.prevInput="":s.prevInput=n,s.composing&&(s.composing.range.clear(),s.composing.range=e.markText(s.composing.start,e.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},ensurePolled:function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},onKeyPress:function(){bo&&wo>=9&&(this.hasSelection=null),this.fastPoll()},onContextMenu:function(e){function t(){if(null!=l.selectionStart){var e=i.somethingSelected(),t="​"+(e?l.value:"");l.value="⇚",l.value=t,n.prevInput=e?"":"​",l.selectionStart=1,l.selectionEnd=t.length,o.selForContextMenu=i.doc.sel}}function r(){if(n.contextMenuPending=!1,n.wrapper.style.position="relative",l.style.cssText=c,bo&&wo<9&&o.scrollbars.setScrollTop(o.scroller.scrollTop=a),null!=l.selectionStart){(!bo||bo&&wo<9)&&t();var e=0,r=function(){o.selForContextMenu==i.doc.sel&&0==l.selectionStart&&l.selectionEnd>0&&"​"==n.prevInput?At(i,ul.selectAll)(i):e++<10?o.detectingSelectAll=setTimeout(r,500):o.input.reset()};o.detectingSelectAll=setTimeout(r,200)}}var n=this,i=n.cm,o=i.display,l=n.textarea,s=Xt(i,e),a=o.scroller.scrollTop;if(s&&!Lo){var u=i.options.resetSelectionOnContextMenu;u&&i.doc.sel.contains(s)==-1&&At(i,ke)(i.doc,de(s),Il);var c=l.style.cssText;if(n.wrapper.style.position="absolute",l.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(e.clientY-5)+"px; left: "+(e.clientX-5)+"px; z-index: 1000; background: "+(bo?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",xo)var h=window.scrollY;if(o.input.focus(),xo&&window.scrollTo(null,h),o.input.reset(),i.somethingSelected()||(l.value=n.prevInput=" "),n.contextMenuPending=!0,o.selForContextMenu=i.doc.sel,clearTimeout(o.detectingSelectAll),bo&&wo>=9&&t(),Po){Nl(e);var f=function(){Ol(window,"mouseup",f),setTimeout(r,20)};Wl(window,"mouseup",f)}else setTimeout(r,50)}},readOnlyChanged:function(e){e||this.reset()},setUneditable:Ei,needsContentAttribute:!1},re.prototype),ie.prototype=zi({init:function(e){function t(e){if(n.somethingSelected())Ro=n.getSelections(),"cut"==e.type&&n.replaceSelection("",null,"cut");else{if(!n.options.lineWiseCopyCut)return;var t=ee(n);Ro=t.text,"cut"==e.type&&n.operation(function(){n.setSelections(t.ranges,0,Il),n.replaceSelection("",null,"cut")})}if(e.clipboardData&&!No)e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData("text/plain",Ro.join("\n"));else{var r=ne(),i=r.firstChild;n.display.lineSpace.insertBefore(r,n.display.lineSpace.firstChild),i.value=Ro.join("\n");var o=document.activeElement;Ul(i),setTimeout(function(){n.display.lineSpace.removeChild(r),o.focus()},50)}}var r=this,n=r.cm,i=r.div=e.lineDiv;te(i),Wl(i,"paste",function(e){ki(n,e)||Q(e,n)}),Wl(i,"compositionstart",function(e){var t=e.data;if(r.composing={sel:n.doc.sel,data:t,startData:t},t){var i=n.doc.sel.primary(),o=n.getLine(i.head.line),l=o.indexOf(t,Math.max(0,i.head.ch-t.length));l>-1&&l<=i.head.ch&&(r.composing.sel=de(zo(i.head.line,l),zo(i.head.line,l+t.length)))}}),Wl(i,"compositionupdate",function(e){r.composing.data=e.data}),Wl(i,"compositionend",function(e){var t=r.composing;t&&(e.data==t.startData||/\u200b/.test(e.data)||(t.data=e.data),setTimeout(function(){t.handled||r.applyComposition(t),r.composing==t&&(r.composing=null)},50))}),Wl(i,"touchstart",function(){r.forceCompositionEnd()}),Wl(i,"input",function(){r.composing||!n.isReadOnly()&&r.pollContent()||Wt(r.cm,function(){Et(n)})}),Wl(i,"copy",t),Wl(i,"cut",t)},prepareSelection:function(){var e=Ee(this.cm,!1);return e.focus=this.cm.state.focused,e},showSelection:function(e){e&&this.cm.display.view.length&&(e.focus&&this.showPrimarySelection(),this.showMultipleSelections(e))},showPrimarySelection:function(){var e=window.getSelection(),t=this.cm.doc.sel.primary(),r=se(this.cm,e.anchorNode,e.anchorOffset),n=se(this.cm,e.focusNode,e.focusOffset);if(!r||r.bad||!n||n.bad||0!=Fo($(r,n),t.from())||0!=Fo(_(r,n),t.to())){var i=oe(this.cm,t.from()),o=oe(this.cm,t.to());if(i||o){var l=this.cm.display.view,s=e.rangeCount&&e.getRangeAt(0);if(i){if(!o){var a=l[l.length-1].measure,u=a.maps?a.maps[a.maps.length-1]:a.map;o={node:u[u.length-1],offset:u[u.length-2]-u[u.length-3]}}}else i={node:l[0].measure.map[2],offset:0};try{var c=Vl(i.node,i.offset,o.offset,o.node)}catch(h){}c&&(!vo&&this.cm.state.focused?(e.collapse(i.node,i.offset),c.collapsed||e.addRange(c)):(e.removeAllRanges(),e.addRange(c)),s&&null==e.anchorNode?e.addRange(s):vo&&this.startGracePeriod()),this.rememberSelection()}}},startGracePeriod:function(){var e=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){e.gracePeriod=!1,e.selectionChanged()&&e.cm.operation(function(){e.cm.curOp.selectionChanged=!0})},20)},showMultipleSelections:function(e){Ki(this.cm.display.cursorDiv,e.cursors),Ki(this.cm.display.selectionDiv,e.selection)},rememberSelection:function(){var e=window.getSelection();this.lastAnchorNode=e.anchorNode,this.lastAnchorOffset=e.anchorOffset,this.lastFocusNode=e.focusNode,this.lastFocusOffset=e.focusOffset},selectionInEditor:function(){var e=window.getSelection();if(!e.rangeCount)return!1;var t=e.getRangeAt(0).commonAncestorContainer;return Yl(this.div,t)},focus:function(){"nocursor"!=this.cm.options.readOnly&&this.div.focus()},blur:function(){this.div.blur()},getField:function(){return this.div},supportsTouch:function(){return!0},receivedFocus:function(){function e(){t.cm.state.focused&&(t.pollSelection(),t.polling.set(t.cm.options.pollInterval,e))}var t=this;this.selectionInEditor()?this.pollSelection():Wt(this.cm,function(){t.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,e)},selectionChanged:function(){var e=window.getSelection();return e.anchorNode!=this.lastAnchorNode||e.anchorOffset!=this.lastAnchorOffset||e.focusNode!=this.lastFocusNode||e.focusOffset!=this.lastFocusOffset},pollSelection:function(){if(!this.composing&&!this.gracePeriod&&this.selectionChanged()){var e=window.getSelection(),t=this.cm;this.rememberSelection();var r=se(t,e.anchorNode,e.anchorOffset),n=se(t,e.focusNode,e.focusOffset);r&&n&&Wt(t,function(){ke(t.doc,de(r,n),Il),(r.bad||n.bad)&&(t.curOp.selectionChanged=!0)})}},pollContent:function(){var e=this.cm,t=e.display,r=e.doc.sel.primary(),n=r.from(),i=r.to();if(n.line<t.viewFrom||i.line>t.viewTo-1)return!1;var o;if(n.line==t.viewFrom||0==(o=Ft(e,n.line)))var l=ti(t.view[0].line),s=t.view[0].node;else var l=ti(t.view[o].line),s=t.view[o-1].node.nextSibling;var a=Ft(e,i.line);if(a==t.view.length-1)var u=t.viewTo-1,c=t.lineDiv.lastChild;else var u=ti(t.view[a+1].line)-1,c=t.view[a+1].node.previousSibling;for(var h=e.doc.splitLines(ue(e,s,c,l,u)),f=Qn(e.doc,zo(l,0),zo(u,Zn(e.doc,u).text.length));h.length>1&&f.length>1;)if(Di(h)==Di(f))h.pop(),f.pop(),u--;else{if(h[0]!=f[0])break;h.shift(),f.shift(),l++}for(var d=0,p=0,g=h[0],v=f[0],m=Math.min(g.length,v.length);d<m&&g.charCodeAt(d)==v.charCodeAt(d);)++d;for(var y=Di(h),b=Di(f),w=Math.min(y.length-(1==h.length?d:0),b.length-(1==f.length?d:0));p<w&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)++p;h[h.length-1]=y.slice(0,y.length-p),h[0]=h[0].slice(d);var x=zo(l,d),C=zo(u,f.length?Di(f).length-p:0);return h.length>1||h[0]||Fo(x,C)?(Or(e.doc,h,x,C,"+input"),!0):void 0},ensurePolled:function(){this.forceCompositionEnd()},reset:function(){this.forceCompositionEnd()},forceCompositionEnd:function(){this.composing&&!this.composing.handled&&(this.applyComposition(this.composing),this.composing.handled=!0,this.div.blur(),this.div.focus())},applyComposition:function(e){this.cm.isReadOnly()?At(this.cm,Et)(this.cm):e.data&&e.data!=e.startData&&At(this.cm,Z)(this.cm,e.data,0,e.sel)},setUneditable:function(e){e.contentEditable="false"},onKeyPress:function(e){e.preventDefault(),this.cm.isReadOnly()||At(this.cm,Z)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0)},readOnlyChanged:function(e){this.div.contentEditable=String("nocursor"!=e)},onContextMenu:Ei,resetPosition:Ei,needsContentAttribute:!0},ie.prototype),e.inputStyles={textarea:re,contenteditable:ie},ce.prototype={primary:function(){return this.ranges[this.primIndex]},equals:function(e){if(e==this)return!0;if(e.primIndex!=this.primIndex||e.ranges.length!=this.ranges.length)return!1;for(var t=0;t<this.ranges.length;t++){var r=this.ranges[t],n=e.ranges[t];if(0!=Fo(r.anchor,n.anchor)||0!=Fo(r.head,n.head))return!1}return!0},deepCopy:function(){for(var e=[],t=0;t<this.ranges.length;t++)e[t]=new he(Y(this.ranges[t].anchor),Y(this.ranges[t].head));return new ce(e,this.primIndex)},somethingSelected:function(){for(var e=0;e<this.ranges.length;e++)if(!this.ranges[e].empty())return!0;return!1},contains:function(e,t){t||(t=e);for(var r=0;r<this.ranges.length;r++){var n=this.ranges[r];if(Fo(t,n.from())>=0&&Fo(e,n.to())<=0)return r}return-1}},he.prototype={from:function(){return $(this.anchor,this.head)},to:function(){return _(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};var Bo,Go,Uo,Vo={left:0,right:0,top:0,bottom:0},Ko=null,jo=0,Xo=0,Yo=0,_o=null;bo?_o=-.53:vo?_o=15:So?_o=-.7:To&&(_o=-1/3);var $o=function(e){var t=e.wheelDeltaX,r=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==r&&e.detail&&e.axis==e.VERTICAL_AXIS?r=e.detail:null==r&&(r=e.wheelDelta),{x:t,y:r}};e.wheelEventPixels=function(e){var t=$o(e);return t.x*=_o,t.y*=_o,t};var qo=new Ai,Zo=null,Qo=e.changeEnd=function(e){return e.text?zo(e.from.line+e.text.length-1,Di(e.text).length+(1==e.text.length?e.from.ch:0)):e.to};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,t){var r=this.options,n=r[e];r[e]==t&&"mode"!=e||(r[e]=t,el.hasOwnProperty(e)&&At(this,el[e])(this,t,n))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Xr(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,r=0;r<t.length;++r)if(t[r]==e||t[r].name==e)return t.splice(r,1),!0},addOverlay:Ot(function(t,r){var n=t.token?t:e.getMode(this.options,t);if(n.startState)throw new Error("Overlays may not be stateful.");this.state.overlays.push({mode:n,modeSpec:t,opaque:r&&r.opaque}),this.state.modeGen++,Et(this)}),removeOverlay:Ot(function(e){for(var t=this.state.overlays,r=0;r<t.length;++r){var n=t[r].modeSpec;if(n==e||"string"==typeof e&&n.name==e)return t.splice(r,1),this.state.modeGen++,void Et(this)}}),indentLine:Ot(function(e,t,r){"string"!=typeof t&&"number"!=typeof t&&(t=null==t?this.options.smartIndent?"smart":"prev":t?"add":"subtract"),me(this.doc,e)&&Rr(this,e,t,r)}),indentSelection:Ot(function(e){for(var t=this.doc.sel.ranges,r=-1,n=0;n<t.length;n++){var i=t[n];if(i.empty())i.head.line>r&&(Rr(this,i.head.line,e,!0),r=i.head.line,n==this.doc.sel.primIndex&&zr(this));else{var o=i.from(),l=i.to(),s=Math.max(r,o.line);r=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1;for(var a=s;a<r;++a)Rr(this,a,e);var u=this.doc.sel.ranges;0==o.ch&&t.length==u.length&&u[n].from().ch>0&&Ce(this.doc,n,new he(o,u[n].to()),Il)}}}),getTokenAt:function(e,t){return Dn(this,e,t)},getLineTokens:function(e,t){return Dn(this,zo(e),t,!0)},getTokenTypeAt:function(e){e=ge(this.doc,e);var t,r=En(this,Zn(this.doc,e.line)),n=0,i=(r.length-1)/2,o=e.ch;if(0==o)t=r[2];else for(;;){var l=n+i>>1;if((l?r[2*l-1]:0)>=o)i=l;else{if(!(r[2*l+1]<o)){t=r[2*l+2];break}n=l+1}}var s=t?t.indexOf("cm-overlay "):-1;return s<0?t:0==s?null:t.slice(0,s-1)},getModeAt:function(t){var r=this.doc.mode;return r.innerMode?e.innerMode(r,this.getTokenAt(t).state).mode:r},getHelper:function(e,t){return this.getHelpers(e,t)[0]},getHelpers:function(e,t){var r=[];if(!ll.hasOwnProperty(t))return r;var n=ll[t],i=this.getModeAt(e);if("string"==typeof i[t])n[i[t]]&&r.push(n[i[t]]);else if(i[t])for(var o=0;o<i[t].length;o++){var l=n[i[t][o]];l&&r.push(l)}else i.helperType&&n[i.helperType]?r.push(n[i.helperType]):n[i.name]&&r.push(n[i.name]);for(var o=0;o<n._global.length;o++){var s=n._global[o];s.pred(i,this)&&Hi(r,s.val)==-1&&r.push(s.val)}return r},getStateAfter:function(e,t){var r=this.doc;return e=pe(r,null==e?r.first+r.size-1:e),Ue(this,e+1,t)},cursorCoords:function(e,t){var r,n=this.doc.sel.primary();return r=null==e?n.head:"object"==typeof e?ge(this.doc,e):e?n.from():n.to(),dt(this,r,t||"page")},charCoords:function(e,t){return ft(this,ge(this.doc,e),t||"page")},coordsChar:function(e,t){return e=ht(this,e,t||"page"),vt(this,e.left,e.top)},lineAtHeight:function(e,t){return e=ht(this,{top:e,left:0},t||"page").top,ri(this.doc,e+this.display.viewOffset)},heightAtLine:function(e,t){var r,n=!1;if("number"==typeof e){var i=this.doc.first+this.doc.size-1;e<this.doc.first?e=this.doc.first:e>i&&(e=i,n=!0),r=Zn(this.doc,e)}else r=e;return ct(this,r,{top:0,left:0},t||"page").top+(n?this.doc.height-ni(r):0)},defaultTextHeight:function(){return yt(this.display)},defaultCharWidth:function(){return bt(this.display)},setGutterMarker:Ot(function(e,t,r){return Br(this.doc,e,"gutter",function(e){var n=e.gutterMarkers||(e.gutterMarkers={});return n[t]=r,!r&&Bi(n)&&(e.gutterMarkers=null),!0})}),clearGutter:Ot(function(e){var t=this,r=t.doc,n=r.first;r.iter(function(r){r.gutterMarkers&&r.gutterMarkers[e]&&(r.gutterMarkers[e]=null,It(t,n,"gutter"),Bi(r.gutterMarkers)&&(r.gutterMarkers=null)),++n})}),lineInfo:function(e){if("number"==typeof e){if(!me(this.doc,e))return null;var t=e;if(e=Zn(this.doc,e),!e)return null}else{var t=ti(e);if(null==t)return null}return{line:t,handle:e,text:e.text,gutterMarkers:e.gutterMarkers,textClass:e.textClass,bgClass:e.bgClass,wrapClass:e.wrapClass,widgets:e.widgets}},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,r,n,i){var o=this.display;e=dt(this,ge(this.doc,e));var l=e.bottom,s=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),o.sizer.appendChild(t),"over"==n)l=e.top;else if("above"==n||"near"==n){var a=Math.max(o.wrapper.clientHeight,this.doc.height),u=Math.max(o.sizer.clientWidth,o.lineSpace.clientWidth);("above"==n||e.bottom+t.offsetHeight>a)&&e.top>t.offsetHeight?l=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=a&&(l=e.bottom),s+t.offsetWidth>u&&(s=u-t.offsetWidth)}t.style.top=l+"px",t.style.left=t.style.right="","right"==i?(s=o.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?s=0:"middle"==i&&(s=(o.sizer.clientWidth-t.offsetWidth)/2),t.style.left=s+"px"),r&&Pr(this,s,l,s+t.offsetWidth,l+t.offsetHeight)},triggerOnKeyDown:Ot(hr),triggerOnKeyPress:Ot(pr),triggerOnKeyUp:dr,execCommand:function(e){if(ul.hasOwnProperty(e))return ul[e].call(null,this)},triggerElectric:Ot(function(e){J(this,e)}),findPosH:function(e,t,r,n){var i=1;t<0&&(i=-1,t=-t);for(var o=0,l=ge(this.doc,e);o<t&&(l=Ur(this.doc,l,i,r,n),!l.hitSide);++o);return l},moveH:Ot(function(e,t){var r=this;r.extendSelectionsBy(function(n){return r.display.shift||r.doc.extend||n.empty()?Ur(r.doc,n.head,e,t,r.options.rtlMoveVisually):e<0?n.from():n.to()},Fl)}),deleteH:Ot(function(e,t){var r=this.doc.sel,n=this.doc;r.somethingSelected()?n.replaceSelection("",null,"+delete"):Gr(this,function(r){var i=Ur(n,r.head,e,t,!1);return e<0?{from:i,to:r.head}:{from:r.head,to:i}})}),findPosV:function(e,t,r,n){var i=1,o=n;t<0&&(i=-1,t=-t);for(var l=0,s=ge(this.doc,e);l<t;++l){var a=dt(this,s,"div");if(null==o?o=a.left:a.left=o,s=Vr(this,a,i,r),s.hitSide)break}return s},moveV:Ot(function(e,t){var r=this,n=this.doc,i=[],o=!r.display.shift&&!n.extend&&n.sel.somethingSelected();if(n.extendSelectionsBy(function(l){if(o)return e<0?l.from():l.to();var s=dt(r,l.head,"div");null!=l.goalColumn&&(s.left=l.goalColumn),i.push(s.left);var a=Vr(r,s,e,t);return"page"==t&&l==n.sel.primary()&&Ir(r,null,ft(r,a,"div").top-s.top),a},Fl),i.length)for(var l=0;l<n.sel.ranges.length;l++)n.sel.ranges[l].goalColumn=i[l]}),findWordAt:function(e){var t=this.doc,r=Zn(t,e.line).text,n=e.ch,i=e.ch;if(r){var o=this.getHelper(e,"wordChars");(e.xRel<0||i==r.length)&&n?--n:++i;for(var l=r.charAt(n),s=Ri(l,o)?function(e){return Ri(e,o)}:/\s/.test(l)?function(e){return/\s/.test(e)}:function(e){return!/\s/.test(e)&&!Ri(e)};n>0&&s(r.charAt(n-1));)--n;for(;i<r.length&&s(r.charAt(i));)++i}return new he(zo(e.line,n),zo(e.line,i))},toggleOverwrite:function(e){null!=e&&e==this.state.overwrite||((this.state.overwrite=!this.state.overwrite)?Zl(this.display.cursorDiv,"CodeMirror-overwrite"):ql(this.display.cursorDiv,"CodeMirror-overwrite"),Dl(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==ji()},isReadOnly:function(){return!(!this.options.readOnly&&!this.doc.cantEdit)},scrollTo:Ot(function(e,t){null==e&&null==t||Fr(this),null!=e&&(this.curOp.scrollLeft=e),null!=t&&(this.curOp.scrollTop=t)}),getScrollInfo:function(){var e=this.display.scroller;return{left:e.scrollLeft,top:e.scrollTop,height:e.scrollHeight-Xe(this)-this.display.barHeight,width:e.scrollWidth-Xe(this)-this.display.barWidth,clientHeight:_e(this),clientWidth:Ye(this)}},scrollIntoView:Ot(function(e,t){if(null==e?(e={from:this.doc.sel.primary().head,to:null},null==t&&(t=this.options.cursorScrollMargin)):"number"==typeof e?e={from:zo(e,0),to:null}:null==e.from&&(e={from:e,to:null}),e.to||(e.to=e.from),e.margin=t||0,null!=e.from.line)Fr(this),this.curOp.scrollToPos=e;else{var r=Er(this,Math.min(e.from.left,e.to.left),Math.min(e.from.top,e.to.top)-e.margin,Math.max(e.from.right,e.to.right),Math.max(e.from.bottom,e.to.bottom)+e.margin);this.scrollTo(r.scrollLeft,r.scrollTop)}}),setSize:Ot(function(e,t){function r(e){return"number"==typeof e||/^\d+$/.test(String(e))?e+"px":e}var n=this;null!=e&&(n.display.wrapper.style.width=r(e)),null!=t&&(n.display.wrapper.style.height=r(t)),n.options.lineWrapping&&lt(this);var i=n.display.viewFrom;n.doc.iter(i,n.display.viewTo,function(e){if(e.widgets)for(var t=0;t<e.widgets.length;t++)if(e.widgets[t].noHScroll){It(n,i,"widget");break}++i}),n.curOp.forceUpdate=!0,Dl(n,"refresh",this)}),operation:function(e){return Wt(this,e)},refresh:Ot(function(){var e=this.display.cachedTextHeight;Et(this),this.curOp.forceUpdate=!0,st(this),this.scrollTo(this.doc.scrollLeft,this.doc.scrollTop),c(this),(null==e||Math.abs(e-yt(this.display))>.5)&&l(this),Dl(this,"refresh",this)}),swapDoc:Ot(function(e){var t=this.doc;return t.cm=null,qn(this,e),st(this),this.display.input.reset(),this.scrollTo(e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,Li(this,"swapDoc",this,t),t}),getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Wi(e);var Jo=e.defaults={},el=e.optionHandlers={},tl=e.Init={toString:function(){return"CodeMirror.Init"}};Kr("value","",function(e,t){e.setValue(t)},!0),Kr("mode",null,function(e,t){e.doc.modeOption=t,r(e)},!0),Kr("indentUnit",2,r,!0),Kr("indentWithTabs",!1),Kr("smartIndent",!0),Kr("tabSize",4,function(e){n(e),st(e),Et(e)},!0),Kr("lineSeparator",null,function(e,t){if(e.doc.lineSep=t,t){var r=[],n=e.doc.first;e.doc.iter(function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(o==-1)break;i=o+t.length,r.push(zo(n,o))}n++});for(var i=r.length-1;i>=0;i--)Or(e.doc,t,r[i],zo(r[i].line,r[i].ch+t.length))}}),Kr("specialChars",/[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g,function(t,r,n){t.state.specialChars=new RegExp(r.source+(r.test("\t")?"":"|\t"),"g"),n!=e.Init&&t.refresh()}),Kr("specialCharPlaceholder",Rn,function(e){e.refresh()},!0),Kr("electricChars",!0),Kr("inputStyle",Wo?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),Kr("rtlMoveVisually",!Oo),Kr("wholeLineUpdateBefore",!0),Kr("theme","default",function(e){s(e),a(e)},!0),Kr("keyMap","default",function(t,r,n){var i=Xr(r),o=n!=e.Init&&Xr(n);o&&o.detach&&o.detach(t,i),i.attach&&i.attach(t,o||null)}),Kr("extraKeys",null),Kr("lineWrapping",!1,i,!0),Kr("gutters",[],function(e){d(e.options),a(e)},!0),Kr("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?L(e.display)+"px":"0",e.refresh()},!0),Kr("coverGutterNextToScrollbar",!1,function(e){y(e)},!0),Kr("scrollbarStyle","native",function(e){m(e),y(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),Kr("lineNumbers",!1,function(e){d(e.options),a(e)},!0),Kr("firstLineNumber",1,a,!0),Kr("lineNumberFormatter",function(e){return e},a,!0),Kr("showCursorWhenSelecting",!1,Pe,!0),Kr("resetSelectionOnContextMenu",!0),Kr("lineWiseCopyCut",!0),Kr("readOnly",!1,function(e,t){"nocursor"==t?(mr(e),e.display.input.blur(),e.display.disabled=!0):e.display.disabled=!1,e.display.input.readOnlyChanged(t)}),Kr("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),Kr("dragDrop",!0,Vt),Kr("allowDropFileTypes",null),Kr("cursorBlinkRate",530),Kr("cursorScrollMargin",0),Kr("cursorHeight",1,Pe,!0),Kr("singleCursorHeightPerLine",!0,Pe,!0),Kr("workTime",100),Kr("workDelay",100),Kr("flattenSpans",!0,n,!0),Kr("addModeClass",!1,n,!0),Kr("pollInterval",100),Kr("undoDepth",200,function(e,t){e.doc.history.undoDepth=t}),Kr("historyEventDelay",1250),Kr("viewportMargin",10,function(e){e.refresh()},!0),Kr("maxHighlightLength",1e4,n,!0),Kr("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),Kr("tabindex",null,function(e,t){e.display.input.getField().tabIndex=t||""}),Kr("autofocus",null);var rl=e.modes={},nl=e.mimeModes={};e.defineMode=function(t,r){e.defaults.mode||"null"==t||(e.defaults.mode=t),arguments.length>2&&(r.dependencies=Array.prototype.slice.call(arguments,2)),rl[t]=r},e.defineMIME=function(e,t){nl[e]=t},e.resolveMode=function(t){if("string"==typeof t&&nl.hasOwnProperty(t))t=nl[t];else if(t&&"string"==typeof t.name&&nl.hasOwnProperty(t.name)){var r=nl[t.name];"string"==typeof r&&(r={name:r}),t=Ii(r,t),t.name=r.name}else if("string"==typeof t&&/^[\w\-]+\/[\w\-]+\+xml$/.test(t))return e.resolveMode("application/xml");return"string"==typeof t?{name:t}:t||{name:"null"}},e.getMode=function(t,r){var r=e.resolveMode(r),n=rl[r.name];if(!n)return e.getMode(t,"text/plain");var i=n(t,r);if(il.hasOwnProperty(r.name)){var o=il[r.name];for(var l in o)o.hasOwnProperty(l)&&(i.hasOwnProperty(l)&&(i["_"+l]=i[l]),i[l]=o[l])}if(i.name=r.name,r.helperType&&(i.helperType=r.helperType),r.modeProps)for(var l in r.modeProps)i[l]=r.modeProps[l];return i},e.defineMode("null",function(){return{token:function(e){e.skipToEnd()}}}),e.defineMIME("text/plain","null");var il=e.modeExtensions={};e.extendMode=function(e,t){var r=il.hasOwnProperty(e)?il[e]:il[e]={};zi(t,r)},e.defineExtension=function(t,r){e.prototype[t]=r},e.defineDocExtension=function(e,t){Sl.prototype[e]=t},e.defineOption=Kr;var ol=[];e.defineInitHook=function(e){ol.push(e)};var ll=e.helpers={};e.registerHelper=function(t,r,n){ll.hasOwnProperty(t)||(ll[t]=e[t]={_global:[]}),ll[t][r]=n},e.registerGlobalHelper=function(t,r,n,i){e.registerHelper(t,r,i),ll[t]._global.push({pred:n,val:i})};var sl=e.copyState=function(e,t){if(t===!0)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r},al=e.startState=function(e,t,r){return!e.startState||e.startState(t,r)};e.innerMode=function(e,t){for(;e.innerMode;){var r=e.innerMode(t);if(!r||r.mode==e)break;t=r.state,e=r.mode}return r||{mode:e,state:t}};var ul=e.commands={selectAll:function(e){e.setSelection(zo(e.firstLine(),0),zo(e.lastLine()),Il)},singleSelection:function(e){e.setSelection(e.getCursor("anchor"),e.getCursor("head"),Il)},killLine:function(e){Gr(e,function(t){if(t.empty()){var r=Zn(e.doc,t.head.line).text.length;return t.head.ch==r&&t.head.line<e.lastLine()?{from:t.head,to:zo(t.head.line+1,0)}:{from:t.head,to:zo(t.head.line,r)}}return{from:t.from(),to:t.to()}})},deleteLine:function(e){Gr(e,function(t){return{from:zo(t.from().line,0),to:ge(e.doc,zo(t.to().line+1,0))}})},delLineLeft:function(e){Gr(e,function(e){return{from:zo(e.from().line,0),to:e.from()}})},delWrappedLineLeft:function(e){Gr(e,function(t){var r=e.charCoords(t.head,"div").top+5,n=e.coordsChar({left:0,top:r},"div");return{from:n,to:t.from()}})},delWrappedLineRight:function(e){Gr(e,function(t){var r=e.charCoords(t.head,"div").top+5,n=e.coordsChar({left:e.display.lineDiv.offsetWidth+100,top:r},"div");return{from:t.from(),to:n}})},undo:function(e){e.undo()},redo:function(e){e.redo()},undoSelection:function(e){e.undoSelection()},redoSelection:function(e){e.redoSelection()},goDocStart:function(e){e.extendSelection(zo(e.firstLine(),0))},goDocEnd:function(e){e.extendSelection(zo(e.lastLine()))},goLineStart:function(e){e.extendSelectionsBy(function(t){return oo(e,t.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(e){e.extendSelectionsBy(function(t){return so(e,t.head)},{origin:"+move",bias:1})},goLineEnd:function(e){e.extendSelectionsBy(function(t){return lo(e,t.head.line)},{origin:"+move",bias:-1})},goLineRight:function(e){e.extendSelectionsBy(function(t){var r=e.charCoords(t.head,"div").top+5;return e.coordsChar({left:e.display.lineDiv.offsetWidth+100,top:r},"div")},Fl)},goLineLeft:function(e){e.extendSelectionsBy(function(t){var r=e.charCoords(t.head,"div").top+5;return e.coordsChar({left:0,top:r},"div")},Fl)},goLineLeftSmart:function(e){e.extendSelectionsBy(function(t){var r=e.charCoords(t.head,"div").top+5,n=e.coordsChar({left:0,top:r},"div");return n.ch<e.getLine(n.line).search(/\S/)?so(e,t.head):n},Fl)},goLineUp:function(e){e.moveV(-1,"line")},goLineDown:function(e){e.moveV(1,"line")},goPageUp:function(e){e.moveV(-1,"page")},goPageDown:function(e){e.moveV(1,"page")},goCharLeft:function(e){e.moveH(-1,"char")},goCharRight:function(e){e.moveH(1,"char")},goColumnLeft:function(e){e.moveH(-1,"column")},goColumnRight:function(e){e.moveH(1,"column")},goWordLeft:function(e){e.moveH(-1,"word")},goGroupRight:function(e){e.moveH(1,"group")},goGroupLeft:function(e){e.moveH(-1,"group")},goWordRight:function(e){e.moveH(1,"word")},delCharBefore:function(e){e.deleteH(-1,"char")},delCharAfter:function(e){e.deleteH(1,"char")},delWordBefore:function(e){e.deleteH(-1,"word")},delWordAfter:function(e){e.deleteH(1,"word")},delGroupBefore:function(e){e.deleteH(-1,"group")},delGroupAfter:function(e){e.deleteH(1,"group")},indentAuto:function(e){e.indentSelection("smart")},indentMore:function(e){e.indentSelection("add")},indentLess:function(e){e.indentSelection("subtract")},insertTab:function(e){e.replaceSelection("\t")},insertSoftTab:function(e){for(var t=[],r=e.listSelections(),n=e.options.tabSize,i=0;i<r.length;i++){var o=r[i].from(),l=Rl(e.getLine(o.line),o.ch,n);t.push(new Array(n-l%n+1).join(" "))}e.replaceSelections(t)},defaultTab:function(e){e.somethingSelected()?e.indentSelection("add"):e.execCommand("insertTab")},transposeChars:function(e){Wt(e,function(){for(var t=e.listSelections(),r=[],n=0;n<t.length;n++){var i=t[n].head,o=Zn(e.doc,i.line).text;if(o)if(i.ch==o.length&&(i=new zo(i.line,i.ch-1)),i.ch>0)i=new zo(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),zo(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var l=Zn(e.doc,i.line-1).text;l&&e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+l.charAt(l.length-1),zo(i.line-1,l.length-1),zo(i.line,1),"+transpose")}r.push(new he(i,i))}e.setSelections(r)})},newlineAndIndent:function(e){Wt(e,function(){for(var t=e.listSelections().length,r=0;r<t;r++){var n=e.listSelections()[r];e.replaceRange(e.doc.lineSeparator(),n.anchor,n.head,"+input"),e.indentLine(n.from().line+1,null,!0)}zr(e)})},toggleOverwrite:function(e){e.toggleOverwrite()}},cl=e.keyMap={};cl.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},cl.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save",
5
- "Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},cl.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars"},cl.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},cl["default"]=Ao?cl.macDefault:cl.pcDefault,e.normalizeKeyMap=function(e){var t={};for(var r in e)if(e.hasOwnProperty(r)){var n=e[r];if(/^(name|fallthrough|(de|at)tach)$/.test(r))continue;if("..."==n){delete e[r];continue}for(var i=Pi(r.split(" "),jr),o=0;o<i.length;o++){var l,s;o==i.length-1?(s=i.join(" "),l=n):(s=i.slice(0,o+1).join(" "),l="...");var a=t[s];if(a){if(a!=l)throw new Error("Inconsistent bindings for "+s)}else t[s]=l}delete e[r]}for(var u in t)e[u]=t[u];return e};var hl=e.lookupKey=function(e,t,r,n){t=Xr(t);var i=t.call?t.call(e,n):t[e];if(i===!1)return"nothing";if("..."===i)return"multi";if(null!=i&&r(i))return"handled";if(t.fallthrough){if("[object Array]"!=Object.prototype.toString.call(t.fallthrough))return hl(e,t.fallthrough,r,n);for(var o=0;o<t.fallthrough.length;o++){var l=hl(e,t.fallthrough[o],r,n);if(l)return l}}},fl=e.isModifierKey=function(e){var t="string"==typeof e?e:is[e.keyCode];return"Ctrl"==t||"Alt"==t||"Shift"==t||"Mod"==t},dl=e.keyName=function(e,t){if(Lo&&34==e.keyCode&&e["char"])return!1;var r=is[e.keyCode],n=r;return null!=n&&!e.altGraphKey&&(e.altKey&&"Alt"!=r&&(n="Alt-"+n),(Ho?e.metaKey:e.ctrlKey)&&"Ctrl"!=r&&(n="Ctrl-"+n),(Ho?e.ctrlKey:e.metaKey)&&"Cmd"!=r&&(n="Cmd-"+n),!t&&e.shiftKey&&"Shift"!=r&&(n="Shift-"+n),n)};e.fromTextArea=function(t,r){function n(){t.value=u.getValue()}if(r=r?zi(r):{},r.value=t.value,!r.tabindex&&t.tabIndex&&(r.tabindex=t.tabIndex),!r.placeholder&&t.placeholder&&(r.placeholder=t.placeholder),null==r.autofocus){var i=ji();r.autofocus=i==t||null!=t.getAttribute("autofocus")&&i==document.body}if(t.form&&(Wl(t.form,"submit",n),!r.leaveSubmitMethodAlone)){var o=t.form,l=o.submit;try{var s=o.submit=function(){n(),o.submit=l,o.submit(),o.submit=s}}catch(a){}}r.finishInit=function(e){e.save=n,e.getTextArea=function(){return t},e.toTextArea=function(){e.toTextArea=isNaN,n(),t.parentNode.removeChild(e.getWrapperElement()),t.style.display="",t.form&&(Ol(t.form,"submit",n),"function"==typeof t.form.submit&&(t.form.submit=l))}},t.style.display="none";var u=e(function(e){t.parentNode.insertBefore(e,t.nextSibling)},r);return u};var pl=e.StringStream=function(e,t){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0};pl.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},eat:function(e){var t=this.string.charAt(this.pos);if("string"==typeof e)var r=t==e;else var r=t&&(e.test?e.test(t):e(t));if(r)return++this.pos,t},eatWhile:function(e){for(var t=this.pos;this.eat(e););return this.pos>t},eatSpace:function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},skipToEnd:function(){this.pos=this.string.length},skipTo:function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},backUp:function(e){this.pos-=e},column:function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=Rl(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?Rl(this.string,this.lineStart,this.tabSize):0)},indentation:function(){return Rl(this.string,null,this.tabSize)-(this.lineStart?Rl(this.string,this.lineStart,this.tabSize):0)},match:function(e,t,r){if("string"!=typeof e){var n=this.string.slice(this.pos).match(e);return n&&n.index>0?null:(n&&t!==!1&&(this.pos+=n[0].length),n)}var i=function(e){return r?e.toLowerCase():e},o=this.string.substr(this.pos,e.length);if(i(o)==i(e))return t!==!1&&(this.pos+=e.length),!0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}}};var gl=0,vl=e.TextMarker=function(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++gl};Wi(vl),vl.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&wt(e),Ni(this,"clear")){var r=this.find();r&&Li(this,"clear",r.from,r.to)}for(var n=null,i=null,o=0;o<this.lines.length;++o){var l=this.lines[o],s=Jr(l.markedSpans,this);e&&!this.collapsed?It(e,ti(l),"text"):e&&(null!=s.to&&(i=ti(l)),null!=s.from&&(n=ti(l))),l.markedSpans=en(l.markedSpans,s),null==s.from&&this.collapsed&&!Cn(this.doc,l)&&e&&ei(l,yt(e.display))}if(e&&this.collapsed&&!e.options.lineWrapping)for(var o=0;o<this.lines.length;++o){var a=yn(this.lines[o]),u=h(a);u>e.display.maxLineLength&&(e.display.maxLine=a,e.display.maxLineLength=u,e.display.maxLineChanged=!0)}null!=n&&e&&this.collapsed&&Et(e,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&We(e.doc)),e&&Li(e,"markerCleared",e,this),t&&Ct(e),this.parent&&this.parent.clear()}},vl.prototype.find=function(e,t){null==e&&"bookmark"==this.type&&(e=1);for(var r,n,i=0;i<this.lines.length;++i){var o=this.lines[i],l=Jr(o.markedSpans,this);if(null!=l.from&&(r=zo(t?o:ti(o),l.from),e==-1))return r;if(null!=l.to&&(n=zo(t?o:ti(o),l.to),1==e))return n}return r&&{from:r,to:n}},vl.prototype.changed=function(){var e=this.find(-1,!0),t=this,r=this.doc.cm;e&&r&&Wt(r,function(){var n=e.line,i=ti(e.line),o=Je(r,i);if(o&&(ot(o),r.curOp.selectionChanged=r.curOp.forceUpdate=!0),r.curOp.updateMaxLine=!0,!Cn(t.doc,n)&&null!=t.height){var l=t.height;t.height=null;var s=Tn(t)-l;s&&ei(n,n.height+s)}})},vl.prototype.attachLine=function(e){if(!this.lines.length&&this.doc.cm){var t=this.doc.cm.curOp;t.maybeHiddenMarkers&&Hi(t.maybeHiddenMarkers,this)!=-1||(t.maybeUnhiddenMarkers||(t.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(e)},vl.prototype.detachLine=function(e){if(this.lines.splice(Hi(this.lines,e),1),!this.lines.length&&this.doc.cm){var t=this.doc.cm.curOp;(t.maybeHiddenMarkers||(t.maybeHiddenMarkers=[])).push(this)}};var gl=0,ml=e.SharedTextMarker=function(e,t){this.markers=e,this.primary=t;for(var r=0;r<e.length;++r)e[r].parent=this};Wi(ml),ml.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var e=0;e<this.markers.length;++e)this.markers[e].clear();Li(this,"clear")}},ml.prototype.find=function(e,t){return this.primary.find(e,t)};var yl=e.LineWidget=function(e,t,r){if(r)for(var n in r)r.hasOwnProperty(n)&&(this[n]=r[n]);this.doc=e,this.node=t};Wi(yl),yl.prototype.clear=function(){var e=this.doc.cm,t=this.line.widgets,r=this.line,n=ti(r);if(null!=n&&t){for(var i=0;i<t.length;++i)t[i]==this&&t.splice(i--,1);t.length||(r.widgets=null);var o=Tn(this);ei(r,Math.max(0,r.height-o)),e&&Wt(e,function(){Ln(e,r,-o),It(e,n,"widget")})}},yl.prototype.changed=function(){var e=this.height,t=this.doc.cm,r=this.line;this.height=null;var n=Tn(this)-e;n&&(ei(r,r.height+n),t&&Wt(t,function(){t.curOp.forceUpdate=!0,Ln(t,r,n)}))};var bl=e.Line=function(e,t,r){this.text=e,cn(this,t),this.height=r?r(this):1};Wi(bl),bl.prototype.lineNo=function(){return ti(this)};var wl={},xl={};Yn.prototype={chunkSize:function(){return this.lines.length},removeInner:function(e,t){for(var r=e,n=e+t;r<n;++r){var i=this.lines[r];this.height-=i.height,Nn(i),Li(i,"delete")}this.lines.splice(e,t)},collapse:function(e){e.push.apply(e,this.lines)},insertInner:function(e,t,r){this.height+=r,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var n=0;n<t.length;++n)t[n].parent=this},iterN:function(e,t,r){for(var n=e+t;e<n;++e)if(r(this.lines[e]))return!0}},_n.prototype={chunkSize:function(){return this.size},removeInner:function(e,t){this.size-=t;for(var r=0;r<this.children.length;++r){var n=this.children[r],i=n.chunkSize();if(e<i){var o=Math.min(t,i-e),l=n.height;if(n.removeInner(e,o),this.height-=l-n.height,i==o&&(this.children.splice(r--,1),n.parent=null),0==(t-=o))break;e=0}else e-=i}if(this.size-t<25&&(this.children.length>1||!(this.children[0]instanceof Yn))){var s=[];this.collapse(s),this.children=[new Yn(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t<this.children.length;++t)this.children[t].collapse(e)},insertInner:function(e,t,r){this.size+=t.length,this.height+=r;for(var n=0;n<this.children.length;++n){var i=this.children[n],o=i.chunkSize();if(e<=o){if(i.insertInner(e,t,r),i.lines&&i.lines.length>50){for(;i.lines.length>50;){var l=i.lines.splice(i.lines.length-25,25),s=new Yn(l);i.height-=s.height,this.children.splice(n+1,0,s),s.parent=this}this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(!(this.children.length<=10)){var e=this;do{var t=e.children.splice(e.children.length-5,5),r=new _n(t);if(e.parent){e.size-=r.size,e.height-=r.height;var n=Hi(e.parent.children,e);e.parent.children.splice(n+1,0,r)}else{var i=new _n(e.children);i.parent=e,e.children=[i,r],e=i}r.parent=e.parent}while(e.children.length>10);e.parent.maybeSpill()}},iterN:function(e,t,r){for(var n=0;n<this.children.length;++n){var i=this.children[n],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e);if(i.iterN(e,l,r))return!0;if(0==(t-=l))break;e=0}else e-=o}}};var Cl=0,Sl=e.Doc=function(e,t,r,n){if(!(this instanceof Sl))return new Sl(e,t,r,n);null==r&&(r=0),_n.call(this,[new Yn([new bl("",null)])]),this.first=r,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.frontier=r;var i=zo(r,0);this.sel=de(i),this.history=new oi(null),this.id=++Cl,this.modeOption=t,this.lineSep=n,this.extend=!1,"string"==typeof e&&(e=this.splitLines(e)),Xn(this,{from:i,to:i,text:e}),ke(this,de(i),Il)};Sl.prototype=Ii(_n.prototype,{constructor:Sl,iter:function(e,t,r){r?this.iterN(e-this.first,t-e,r):this.iterN(this.first,this.first+this.size,e)},insert:function(e,t){for(var r=0,n=0;n<t.length;++n)r+=t[n].height;this.insertInner(e-this.first,t,r)},remove:function(e,t){this.removeInner(e-this.first,t)},getValue:function(e){var t=Jn(this,this.first,this.first+this.size);return e===!1?t:t.join(e||this.lineSeparator())},setValue:Dt(function(e){var t=zo(this.first,0),r=this.first+this.size-1;Tr(this,{from:t,to:zo(r,Zn(this,r).text.length),text:this.splitLines(e),origin:"setValue",full:!0},!0),ke(this,de(t))}),replaceRange:function(e,t,r,n){t=ge(this,t),r=r?ge(this,r):t,Or(this,e,t,r,n)},getRange:function(e,t,r){var n=Qn(this,ge(this,e),ge(this,t));return r===!1?n:n.join(r||this.lineSeparator())},getLine:function(e){var t=this.getLineHandle(e);return t&&t.text},getLineHandle:function(e){if(me(this,e))return Zn(this,e)},getLineNumber:function(e){return ti(e)},getLineHandleVisualStart:function(e){return"number"==typeof e&&(e=Zn(this,e)),yn(e)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(e){return ge(this,e)},getCursor:function(e){var t,r=this.sel.primary();return t=null==e||"head"==e?r.head:"anchor"==e?r.anchor:"end"==e||"to"==e||e===!1?r.to():r.from()},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Dt(function(e,t,r){Se(this,ge(this,"number"==typeof e?zo(e,t||0):e),null,r)}),setSelection:Dt(function(e,t,r){Se(this,ge(this,e),ge(this,t||e),r)}),extendSelection:Dt(function(e,t,r){we(this,ge(this,e),t&&ge(this,t),r)}),extendSelections:Dt(function(e,t){xe(this,ye(this,e),t)}),extendSelectionsBy:Dt(function(e,t){var r=Pi(this.sel.ranges,e);xe(this,ye(this,r),t)}),setSelections:Dt(function(e,t,r){if(e.length){for(var n=0,i=[];n<e.length;n++)i[n]=new he(ge(this,e[n].anchor),ge(this,e[n].head));null==t&&(t=Math.min(e.length-1,this.sel.primIndex)),ke(this,fe(i,t),r)}}),addSelection:Dt(function(e,t,r){var n=this.sel.ranges.slice(0);n.push(new he(ge(this,e),ge(this,t||e))),ke(this,fe(n,n.length-1),r)}),getSelection:function(e){for(var t,r=this.sel.ranges,n=0;n<r.length;n++){var i=Qn(this,r[n].from(),r[n].to());t=t?t.concat(i):i}return e===!1?t:t.join(e||this.lineSeparator())},getSelections:function(e){for(var t=[],r=this.sel.ranges,n=0;n<r.length;n++){var i=Qn(this,r[n].from(),r[n].to());e!==!1&&(i=i.join(e||this.lineSeparator())),t[n]=i}return t},replaceSelection:function(e,t,r){for(var n=[],i=0;i<this.sel.ranges.length;i++)n[i]=e;this.replaceSelections(n,t,r||"+input")},replaceSelections:Dt(function(e,t,r){for(var n=[],i=this.sel,o=0;o<i.ranges.length;o++){var l=i.ranges[o];n[o]={from:l.from(),to:l.to(),text:this.splitLines(e[o]),origin:r}}for(var s=t&&"end"!=t&&Sr(this,n,t),o=n.length-1;o>=0;o--)Tr(this,n[o]);s?Te(this,s):this.cm&&zr(this.cm)}),undo:Dt(function(){Mr(this,"undo")}),redo:Dt(function(){Mr(this,"redo")}),undoSelection:Dt(function(){Mr(this,"undo",!0)}),redoSelection:Dt(function(){Mr(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,r=0,n=0;n<e.done.length;n++)e.done[n].ranges||++t;for(var n=0;n<e.undone.length;n++)e.undone[n].ranges||++r;return{undo:t,redo:r}},clearHistory:function(){this.history=new oi(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(e){return e&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(e){return this.history.generation==(e||this.cleanGeneration)},getHistory:function(){return{done:vi(this.history.done),undone:vi(this.history.undone)}},setHistory:function(e){var t=this.history=new oi(this.history.maxGeneration);t.done=vi(e.done.slice(0),null,!0),t.undone=vi(e.undone.slice(0),null,!0)},addLineClass:Dt(function(e,t,r){return Br(this,e,"gutter"==t?"gutter":"class",function(e){var n="text"==t?"textClass":"background"==t?"bgClass":"gutter"==t?"gutterClass":"wrapClass";if(e[n]){if(Xi(r).test(e[n]))return!1;e[n]+=" "+r}else e[n]=r;return!0})}),removeLineClass:Dt(function(e,t,r){return Br(this,e,"gutter"==t?"gutter":"class",function(e){var n="text"==t?"textClass":"background"==t?"bgClass":"gutter"==t?"gutterClass":"wrapClass",i=e[n];if(!i)return!1;if(null==r)e[n]=null;else{var o=i.match(Xi(r));if(!o)return!1;var l=o.index+o[0].length;e[n]=i.slice(0,o.index)+(o.index&&l!=i.length?" ":"")+i.slice(l)||null}return!0})}),addLineWidget:Dt(function(e,t,r){return kn(this,e,t,r)}),removeLineWidget:function(e){e.clear()},markText:function(e,t,r){return Yr(this,ge(this,e),ge(this,t),r,r&&r.type||"range")},setBookmark:function(e,t){var r={replacedWith:t&&(null==t.nodeType?t.widget:t),insertLeft:t&&t.insertLeft,clearWhenEmpty:!1,shared:t&&t.shared,handleMouseEvents:t&&t.handleMouseEvents};return e=ge(this,e),Yr(this,e,e,r,"bookmark")},findMarksAt:function(e){e=ge(this,e);var t=[],r=Zn(this,e.line).markedSpans;if(r)for(var n=0;n<r.length;++n){var i=r[n];(null==i.from||i.from<=e.ch)&&(null==i.to||i.to>=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,r){e=ge(this,e),t=ge(this,t);var n=[],i=e.line;return this.iter(e.line,t.line+1,function(o){var l=o.markedSpans;if(l)for(var s=0;s<l.length;s++){var a=l[s];i==e.line&&e.ch>a.to||null==a.from&&i!=e.line||i==t.line&&a.from>t.ch||r&&!r(a.marker)||n.push(a.marker.parent||a.marker)}++i}),n},getAllMarks:function(){var e=[];return this.iter(function(t){var r=t.markedSpans;if(r)for(var n=0;n<r.length;++n)null!=r[n].from&&e.push(r[n].marker)}),e},posFromIndex:function(e){var t,r=this.first;return this.iter(function(n){var i=n.text.length+1;return i>e?(t=e,!0):(e-=i,void++r)}),ge(this,zo(r,t))},indexFromPos:function(e){e=ge(this,e);var t=e.ch;return e.line<this.first||e.ch<0?0:(this.iter(this.first,e.line,function(e){t+=e.text.length+1}),t)},copy:function(e){var t=new Sl(Jn(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep);return t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft,t.sel=this.sel,t.extend=!1,e&&(t.history.undoDepth=this.history.undoDepth,t.setHistory(this.getHistory())),t},linkedDoc:function(e){e||(e={});var t=this.first,r=this.first+this.size;null!=e.from&&e.from>t&&(t=e.from),null!=e.to&&e.to<r&&(r=e.to);var n=new Sl(Jn(this,t,r),e.mode||this.modeOption,t,this.lineSep);return e.sharedHist&&(n.history=this.history),(this.linked||(this.linked=[])).push({doc:n,sharedHist:e.sharedHist}),n.linked=[{doc:this,isParent:!0,sharedHist:e.sharedHist}],qr(n,$r(this)),n},unlinkDoc:function(t){if(t instanceof e&&(t=t.doc),this.linked)for(var r=0;r<this.linked.length;++r){var n=this.linked[r];if(n.doc==t){this.linked.splice(r,1),t.unlinkDoc(this),Zr($r(this));break}}if(t.history==this.history){var i=[t.id];$n(t,function(e){i.push(e.id)},!0),t.history=new oi(null),t.history.done=vi(this.history.done,i),t.history.undone=vi(this.history.undone,i)}},iterLinkedDocs:function(e){$n(this,e)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(e){return this.lineSep?e.split(this.lineSep):es(e)},lineSeparator:function(){return this.lineSep||"\n"}}),Sl.prototype.eachLine=Sl.prototype.iter;var Ll="iter insert remove copy getEditor constructor".split(" ");for(var Tl in Sl.prototype)Sl.prototype.hasOwnProperty(Tl)&&Hi(Ll,Tl)<0&&(e.prototype[Tl]=function(e){return function(){return e.apply(this.doc,arguments)}}(Sl.prototype[Tl]));Wi(Sl);var kl=e.e_preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},Ml=e.e_stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},Nl=e.e_stop=function(e){kl(e),Ml(e)},Wl=e.on=function(e,t,r){if(e.addEventListener)e.addEventListener(t,r,!1);else if(e.attachEvent)e.attachEvent("on"+t,r);else{var n=e._handlers||(e._handlers={}),i=n[t]||(n[t]=[]);i.push(r)}},Al=[],Ol=e.off=function(e,t,r){if(e.removeEventListener)e.removeEventListener(t,r,!1);else if(e.detachEvent)e.detachEvent("on"+t,r);else for(var n=Si(e,t,!1),i=0;i<n.length;++i)if(n[i]==r){n.splice(i,1);break}},Dl=e.signal=function(e,t){var r=Si(e,t,!0);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i<r.length;++i)r[i].apply(null,n)},Hl=null,Pl=30,El=e.Pass={toString:function(){return"CodeMirror.Pass"}},Il={scroll:!1},zl={origin:"*mouse"},Fl={origin:"+move"};Ai.prototype.set=function(e,t){clearTimeout(this.id),this.id=setTimeout(t,e)};var Rl=e.countColumn=function(e,t,r,n,i){null==t&&(t=e.search(/[^\s\u00a0]/),t==-1&&(t=e.length));for(var o=n||0,l=i||0;;){var s=e.indexOf("\t",o);if(s<0||s>=t)return l+(t-o);l+=s-o,l+=r-l%r,o=s+1}},Bl=e.findColumn=function(e,t,r){for(var n=0,i=0;;){var o=e.indexOf("\t",n);o==-1&&(o=e.length);var l=o-n;if(o==e.length||i+l>=t)return n+Math.min(l,t-i);if(i+=o-n,i+=r-i%r,n=o+1,i>=t)return n}},Gl=[""],Ul=function(e){e.select()};No?Ul=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:bo&&(Ul=function(e){try{e.select()}catch(t){}});var Vl,Kl=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,jl=e.isWordChar=function(e){return/\w/.test(e)||e>"€"&&(e.toUpperCase()!=e.toLowerCase()||Kl.test(e))},Xl=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;Vl=document.createRange?function(e,t,r,n){var i=document.createRange();return i.setEnd(n||e,r),i.setStart(e,t),i}:function(e,t,r){var n=document.body.createTextRange();try{n.moveToElementText(e.parentNode)}catch(i){return n}return n.collapse(!0),n.moveEnd("character",r),n.moveStart("character",t),n};var Yl=e.contains=function(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do if(11==t.nodeType&&(t=t.host),t==e)return!0;while(t=t.parentNode)};bo&&wo<11&&(ji=function(){try{return document.activeElement}catch(e){return document.body}});var _l,$l,ql=e.rmClass=function(e,t){var r=e.className,n=Xi(t).exec(r);if(n){var i=r.slice(n.index+n[0].length);e.className=r.slice(0,n.index)+(i?n[1]+i:"")}},Zl=e.addClass=function(e,t){var r=e.className;Xi(t).test(r)||(e.className+=(r?" ":"")+t)},Ql=!1,Jl=function(){if(bo&&wo<9)return!1;var e=Ui("div");return"draggable"in e||"dragDrop"in e}(),es=e.splitLines=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,r=[],n=e.length;t<=n;){var i=e.indexOf("\n",t);i==-1&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");l!=-1?(r.push(o.slice(0,l)),t+=l+1):(r.push(o),t=i+1)}return r}:function(e){return e.split(/\r\n?|\n/)},ts=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(t){return!1}}:function(e){try{var t=e.ownerDocument.selection.createRange()}catch(r){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},rs=function(){var e=Ui("div");return"oncopy"in e||(e.setAttribute("oncopy","return;"),"function"==typeof e.oncopy)}(),ns=null,is=e.keyNames={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};!function(){for(var e=0;e<10;e++)is[e+48]=is[e+96]=String(e);for(var e=65;e<=90;e++)is[e]=String.fromCharCode(e);for(var e=1;e<=12;e++)is[e+111]=is[e+63235]="F"+e}();var os,ls=function(){function e(e){return e<=247?r.charAt(e):1424<=e&&e<=1524?"R":1536<=e&&e<=1773?n.charAt(e-1536):1774<=e&&e<=2220?"r":8192<=e&&e<=8203?"w":8204==e?"b":"L"}function t(e,t,r){this.level=e,this.from=t,this.to=r}var r="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",n="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm",i=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,o=/[stwN]/,l=/[LRr]/,s=/[Lb1n]/,a=/[1n]/,u="L";return function(r){if(!i.test(r))return!1;for(var n,c=r.length,h=[],f=0;f<c;++f)h.push(n=e(r.charCodeAt(f)));for(var f=0,d=u;f<c;++f){var n=h[f];"m"==n?h[f]=d:d=n}for(var f=0,p=u;f<c;++f){var n=h[f];"1"==n&&"r"==p?h[f]="n":l.test(n)&&(p=n,"r"==n&&(h[f]="R"))}for(var f=1,d=h[0];f<c-1;++f){var n=h[f];"+"==n&&"1"==d&&"1"==h[f+1]?h[f]="1":","!=n||d!=h[f+1]||"1"!=d&&"n"!=d||(h[f]=d),d=n}for(var f=0;f<c;++f){var n=h[f];if(","==n)h[f]="N";else if("%"==n){for(var g=f+1;g<c&&"%"==h[g];++g);for(var v=f&&"!"==h[f-1]||g<c&&"1"==h[g]?"1":"N",m=f;m<g;++m)h[m]=v;f=g-1}}for(var f=0,p=u;f<c;++f){var n=h[f];"L"==p&&"1"==n?h[f]="L":l.test(n)&&(p=n)}for(var f=0;f<c;++f)if(o.test(h[f])){for(var g=f+1;g<c&&o.test(h[g]);++g);for(var y="L"==(f?h[f-1]:u),b="L"==(g<c?h[g]:u),v=y||b?"L":"R",m=f;m<g;++m)h[m]=v;f=g-1}for(var w,x=[],f=0;f<c;)if(s.test(h[f])){var C=f;for(++f;f<c&&s.test(h[f]);++f);x.push(new t(0,C,f))}else{var S=f,L=x.length;for(++f;f<c&&"L"!=h[f];++f);for(var m=S;m<f;)if(a.test(h[m])){S<m&&x.splice(L,0,new t(1,S,m));var T=m;for(++m;m<f&&a.test(h[m]);++m);x.splice(L,0,new t(2,T,m)),S=m}else++m;S<f&&x.splice(L,0,new t(1,S,f))}return 1==x[0].level&&(w=r.match(/^\s+/))&&(x[0].from=w[0].length,x.unshift(new t(0,0,w[0].length))),1==Di(x).level&&(w=r.match(/\s+$/))&&(Di(x).to-=w[0].length,x.push(new t(0,c-w[0].length,c))),2==x[0].level&&x.unshift(new t(1,x[0].to,x[0].to)),x[0].level!=Di(x).level&&x.push(new t(x[0].level,c,c)),x}}();return e.version="5.10.0",e});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.CodeMirror=t()}(this,function(){"use strict";function e(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}function t(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function r(e,r){return t(e).appendChild(r)}function n(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function i(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do if(11==t.nodeType&&(t=t.host),t==e)return!0;while(t=t.parentNode)}function o(){var e;try{e=document.activeElement}catch(t){e=document.body||null}for(;e&&e.root&&e.root.activeElement;)e=e.root.activeElement;return e}function l(t,r){var n=t.className;e(r).test(n)||(t.className+=(n?" ":"")+r)}function s(t,r){for(var n=t.split(" "),i=0;i<n.length;i++)n[i]&&!e(n[i]).test(r)&&(r+=" "+n[i]);return r}function a(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function u(e,t,r){t||(t={});for(var n in e)!e.hasOwnProperty(n)||r===!1&&t.hasOwnProperty(n)||(t[n]=e[n]);return t}function c(e,t,r,n,i){null==t&&(t=e.search(/[^\s\u00a0]/),t==-1&&(t=e.length));for(var o=n||0,l=i||0;;){var s=e.indexOf("\t",o);if(s<0||s>=t)return l+(t-o);l+=s-o,l+=r-l%r,o=s+1}}function f(){this.id=null}function h(e,t){for(var r=0;r<e.length;++r)if(e[r]==t)return r;return-1}function d(e,t,r){for(var n=0,i=0;;){var o=e.indexOf("\t",n);o==-1&&(o=e.length);var l=o-n;if(o==e.length||i+l>=t)return n+Math.min(l,t-i);if(i+=o-n,i+=r-i%r,n=o+1,i>=t)return n}}function p(e){for(;Al.length<=e;)Al.push(g(Al)+" ");return Al[e]}function g(e){return e[e.length-1]}function v(e,t){for(var r=[],n=0;n<e.length;n++)r[n]=t(e[n],n);return r}function m(e,t,r){for(var n=0,i=r(t);n<e.length&&r(e[n])<=i;)n++;e.splice(n,0,t)}function y(){}function b(e,t){var r;return Object.create?r=Object.create(e):(y.prototype=e,r=new y),t&&u(t,r),r}function w(e){return/\w/.test(e)||e>"€"&&(e.toUpperCase()!=e.toLowerCase()||Ol.test(e))}function x(e,t){return t?!!(t.source.indexOf("\\w")>-1&&w(e))||t.test(e):w(e)}function C(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}function S(e){return e.charCodeAt(0)>=768&&Wl.test(e)}function L(e,t,r){var i=this;this.input=r,i.scrollbarFiller=n("div",null,"CodeMirror-scrollbar-filler"),i.scrollbarFiller.setAttribute("cm-not-content","true"),i.gutterFiller=n("div",null,"CodeMirror-gutter-filler"),i.gutterFiller.setAttribute("cm-not-content","true"),i.lineDiv=n("div",null,"CodeMirror-code"),i.selectionDiv=n("div",null,null,"position: relative; z-index: 1"),i.cursorDiv=n("div",null,"CodeMirror-cursors"),i.measure=n("div",null,"CodeMirror-measure"),i.lineMeasure=n("div",null,"CodeMirror-measure"),i.lineSpace=n("div",[i.measure,i.lineMeasure,i.selectionDiv,i.cursorDiv,i.lineDiv],null,"position: relative; outline: none"),i.mover=n("div",[n("div",[i.lineSpace],"CodeMirror-lines")],null,"position: relative"),i.sizer=n("div",[i.mover],"CodeMirror-sizer"),i.sizerWidth=null,i.heightForcer=n("div",null,null,"position: absolute; height: "+Ll+"px; width: 1px;"),i.gutters=n("div",null,"CodeMirror-gutters"),i.lineGutter=null,i.scroller=n("div",[i.sizer,i.heightForcer,i.gutters],"CodeMirror-scroll"),i.scroller.setAttribute("tabIndex","-1"),i.wrapper=n("div",[i.scrollbarFiller,i.gutterFiller,i.scroller],"CodeMirror"),rl&&nl<8&&(i.gutters.style.zIndex=-1,i.scroller.style.paddingRight=0),il||Jo&&hl||(i.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(i.wrapper):e(i.wrapper)),i.viewFrom=i.viewTo=t.first,i.reportedViewFrom=i.reportedViewTo=t.first,i.view=[],i.renderedView=null,i.externalMeasured=null,i.viewOffset=0,i.lastWrapHeight=i.lastWrapWidth=0,i.updateLineNumbers=null,i.nativeBarWidth=i.barHeight=i.barWidth=0,i.scrollbarsClipped=!1,i.lineNumWidth=i.lineNumInnerWidth=i.lineNumChars=null,i.alignWidgets=!1,i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.maxLine=null,i.maxLineLength=0,i.maxLineChanged=!1,i.wheelDX=i.wheelDY=i.wheelStartX=i.wheelStartY=null,i.shift=!1,i.selForContextMenu=null,i.activeTouch=null,r.init(i)}function T(e,t){if(t-=e.first,t<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(t<o){r=i;break}t-=o}return r.lines[t]}function M(e,t,r){var n=[],i=t.line;return e.iter(t.line,r.line+1,function(e){var o=e.text;i==r.line&&(o=o.slice(0,r.ch)),i==t.line&&(o=o.slice(t.ch)),n.push(o),++i}),n}function k(e,t,r){var n=[];return e.iter(t,r,function(e){n.push(e.text)}),n}function N(e,t){var r=t-e.height;if(r)for(var n=e;n;n=n.parent)n.height+=r}function A(e){if(null==e.parent)return null;for(var t=e.parent,r=h(t.lines,e),n=t.parent;n;t=n,n=n.parent)for(var i=0;n.children[i]!=t;++i)r+=n.children[i].chunkSize();return r+t.first}function O(e,t){var r=e.first;e:do{for(var n=0;n<e.children.length;++n){var i=e.children[n],o=i.height;if(t<o){e=i;continue e}t-=o,r+=i.chunkSize()}return r}while(!e.lines);for(var l=0;l<e.lines.length;++l){var s=e.lines[l],a=s.height;if(t<a)break;t-=a}return r+l}function W(e,t){return t>=e.first&&t<e.first+e.size}function D(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function H(e,t){return this instanceof H?(this.line=e,void(this.ch=t)):new H(e,t)}function P(e,t){return e.line-t.line||e.ch-t.ch}function E(e){return H(e.line,e.ch)}function I(e,t){return P(e,t)<0?t:e}function z(e,t){return P(e,t)<0?e:t}function F(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function R(e,t){if(t.line<e.first)return H(e.first,0);var r=e.first+e.size-1;return t.line>r?H(r,T(e,r).text.length):B(t,T(e,t.line).text.length)}function B(e,t){var r=e.ch;return null==r||r>t?H(e.line,t):r<0?H(e.line,0):e}function G(e,t){for(var r=[],n=0;n<t.length;n++)r[n]=R(e,t[n]);return r}function U(){Dl=!0}function V(){Hl=!0}function K(e,t,r){this.marker=e,this.from=t,this.to=r}function j(e,t){if(e)for(var r=0;r<e.length;++r){var n=e[r];if(n.marker==t)return n}}function X(e,t){for(var r,n=0;n<e.length;++n)e[n]!=t&&(r||(r=[])).push(e[n]);return r}function Y(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}function _(e,t,r){var n;if(e)for(var i=0;i<e.length;++i){var o=e[i],l=o.marker,s=null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t);if(s||o.from==t&&"bookmark"==l.type&&(!r||!o.marker.insertLeft)){var a=null==o.to||(l.inclusiveRight?o.to>=t:o.to>t);(n||(n=[])).push(new K(l,o.from,a?null:o.to))}}return n}function $(e,t,r){var n;if(e)for(var i=0;i<e.length;++i){var o=e[i],l=o.marker,s=null==o.to||(l.inclusiveRight?o.to>=t:o.to>t);if(s||o.from==t&&"bookmark"==l.type&&(!r||o.marker.insertLeft)){var a=null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t);(n||(n=[])).push(new K(l,a?null:o.from-t,null==o.to?null:o.to-t))}}return n}function q(e,t){if(t.full)return null;var r=W(e,t.from.line)&&T(e,t.from.line).markedSpans,n=W(e,t.to.line)&&T(e,t.to.line).markedSpans;if(!r&&!n)return null;var i=t.from.ch,o=t.to.ch,l=0==P(t.from,t.to),s=_(r,i,l),a=$(n,o,l),u=1==t.text.length,c=g(t.text).length+(u?i:0);if(s)for(var f=0;f<s.length;++f){var h=s[f];if(null==h.to){var d=j(a,h.marker);d?u&&(h.to=null==d.to?null:d.to+c):h.to=i}}if(a)for(var p=0;p<a.length;++p){var v=a[p];if(null!=v.to&&(v.to+=c),null==v.from){var m=j(s,v.marker);m||(v.from=c,u&&(s||(s=[])).push(v))}else v.from+=c,u&&(s||(s=[])).push(v)}s&&(s=Z(s)),a&&a!=s&&(a=Z(a));var y=[s];if(!u){var b,w=t.text.length-2;if(w>0&&s)for(var x=0;x<s.length;++x)null==s[x].to&&(b||(b=[])).push(new K(s[x].marker,null,null));for(var C=0;C<w;++C)y.push(b);y.push(a)}return y}function Z(e){for(var t=0;t<e.length;++t){var r=e[t];null!=r.from&&r.from==r.to&&r.marker.clearWhenEmpty!==!1&&e.splice(t--,1)}return e.length?e:null}function Q(e,t,r){var n=null;if(e.iter(t.line,r.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var r=e.markedSpans[t].marker;!r.readOnly||n&&h(n,r)!=-1||(n||(n=[])).push(r)}}),!n)return null;for(var i=[{from:t,to:r}],o=0;o<n.length;++o)for(var l=n[o],s=l.find(0),a=0;a<i.length;++a){var u=i[a];if(!(P(u.to,s.from)<0||P(u.from,s.to)>0)){var c=[a,1],f=P(u.from,s.from),d=P(u.to,s.to);(f<0||!l.inclusiveLeft&&!f)&&c.push({from:u.from,to:s.from}),(d>0||!l.inclusiveRight&&!d)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),a+=c.length-1}}return i}function J(e){var t=e.markedSpans;if(t){for(var r=0;r<t.length;++r)t[r].marker.detachLine(e);e.markedSpans=null}}function ee(e,t){if(t){for(var r=0;r<t.length;++r)t[r].marker.attachLine(e);e.markedSpans=t}}function te(e){return e.inclusiveLeft?-1:0}function re(e){return e.inclusiveRight?1:0}function ne(e,t){var r=e.lines.length-t.lines.length;if(0!=r)return r;var n=e.find(),i=t.find(),o=P(n.from,i.from)||te(e)-te(t);if(o)return-o;var l=P(n.to,i.to)||re(e)-re(t);return l?l:t.id-e.id}function ie(e,t){var r,n=Hl&&e.markedSpans;if(n)for(var i=void 0,o=0;o<n.length;++o)i=n[o],i.marker.collapsed&&null==(t?i.from:i.to)&&(!r||ne(r,i.marker)<0)&&(r=i.marker);return r}function oe(e){return ie(e,!0)}function le(e){return ie(e,!1)}function se(e,t,r,n,i){var o=T(e,t),l=Hl&&o.markedSpans;if(l)for(var s=0;s<l.length;++s){var a=l[s];if(a.marker.collapsed){var u=a.marker.find(0),c=P(u.from,r)||te(a.marker)-te(i),f=P(u.to,n)||re(a.marker)-re(i);if(!(c>=0&&f<=0||c<=0&&f>=0)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?P(u.to,r)>=0:P(u.to,r)>0)||c>=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?P(u.from,n)<=0:P(u.from,n)<0)))return!0}}}function ae(e){for(var t;t=oe(e);)e=t.find(-1,!0).line;return e}function ue(e){for(var t,r;t=le(e);)e=t.find(1,!0).line,(r||(r=[])).push(e);return r}function ce(e,t){var r=T(e,t),n=ae(r);return r==n?t:A(n)}function fe(e,t){if(t>e.lastLine())return t;var r,n=T(e,t);if(!he(e,n))return t;for(;r=le(n);)n=r.find(1,!0).line;return A(n)+1}function he(e,t){var r=Hl&&t.markedSpans;if(r)for(var n=void 0,i=0;i<r.length;++i)if(n=r[i],n.marker.collapsed){if(null==n.from)return!0;if(!n.marker.widgetNode&&0==n.from&&n.marker.inclusiveLeft&&de(e,t,n))return!0}}function de(e,t,r){if(null==r.to){var n=r.marker.find(1,!0);return de(e,n.line,j(n.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==t.text.length)return!0;for(var i=void 0,o=0;o<t.markedSpans.length;++o)if(i=t.markedSpans[o],i.marker.collapsed&&!i.marker.widgetNode&&i.from==r.to&&(null==i.to||i.to!=r.from)&&(i.marker.inclusiveLeft||r.marker.inclusiveRight)&&de(e,t,i))return!0}function pe(e){e=ae(e);for(var t=0,r=e.parent,n=0;n<r.lines.length;++n){var i=r.lines[n];if(i==e)break;t+=i.height}for(var o=r.parent;o;r=o,o=r.parent)for(var l=0;l<o.children.length;++l){var s=o.children[l];if(s==r)break;t+=s.height}return t}function ge(e){if(0==e.height)return 0;for(var t,r=e.text.length,n=e;t=oe(n);){var i=t.find(0,!0);n=i.from.line,r+=i.from.ch-i.to.ch}for(n=e;t=le(n);){var o=t.find(0,!0);r-=n.text.length-o.from.ch,n=o.to.line,r+=n.text.length-o.to.ch}return r}function ve(e){var t=e.display,r=e.doc;t.maxLine=T(r,r.first),t.maxLineLength=ge(t.maxLine),t.maxLineChanged=!0,r.iter(function(e){var r=ge(e);r>t.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)})}function me(e,t,r,n){if(!e)return n(t,r,"ltr");for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<r&&l.to>t||t==r&&l.to==t)&&(n(Math.max(l.from,t),Math.min(l.to,r),1==l.level?"rtl":"ltr"),i=!0)}i||n(t,r,"ltr")}function ye(e){return e.level%2?e.to:e.from}function be(e){return e.level%2?e.from:e.to}function we(e){var t=ke(e);return t?ye(t[0]):0}function xe(e){var t=ke(e);return t?be(g(t)):e.text.length}function Ce(e,t,r){var n=e[0].level;return t==n||r!=n&&t<r}function Se(e,t){var r;Pl=null;for(var n=0;n<e.length;++n){var i=e[n];if(i.from<t&&i.to>t)return n;if(i.from==t||i.to==t){if(null!=r)return Ce(e,i.level,e[r].level)?(i.from!=i.to&&(Pl=r),n):(i.from!=i.to&&(Pl=n),r);r=n}}return r}function Le(e,t,r,n){if(!n)return t+r;do t+=r;while(t>0&&S(e.text.charAt(t)));return t}function Te(e,t,r,n){var i=ke(e);if(!i)return Me(e,t,r,n);for(var o=Se(i,t),l=i[o],s=Le(e,t,l.level%2?-r:r,n);;){if(s>l.from&&s<l.to)return s;if(s==l.from||s==l.to)return Se(i,s)==o?s:(l=i[o+=r],r>0==l.level%2?l.to:l.from);if(l=i[o+=r],!l)return null;s=r>0==l.level%2?Le(e,l.to,-1,n):Le(e,l.from,1,n)}}function Me(e,t,r,n){var i=t+r;if(n)for(;i>0&&S(e.text.charAt(i));)i+=r;return i<0||i>e.text.length?null:i}function ke(e){var t=e.order;return null==t&&(t=e.order=El(e.text)),t}function Ne(e,t){return e._handlers&&e._handlers[t]||Il}function Ae(e,t,r){if(e.removeEventListener)e.removeEventListener(t,r,!1);else if(e.detachEvent)e.detachEvent("on"+t,r);else{var n=e._handlers,i=n&&n[t];if(i){var o=h(i,r);o>-1&&(n[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function Oe(e,t){var r=Ne(e,t);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i<r.length;++i)r[i].apply(null,n)}function We(e,t,r){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),Oe(e,r||t.type,e,t),ze(t)||t.codemirrorIgnore}function De(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var r=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),n=0;n<t.length;++n)h(r,t[n])==-1&&r.push(t[n])}function He(e,t){return Ne(e,t).length>0}function Pe(e){e.prototype.on=function(e,t){zl(this,e,t)},e.prototype.off=function(e,t){Ae(this,e,t)}}function Ee(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Ie(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function ze(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Fe(e){Ee(e),Ie(e)}function Re(e){return e.target||e.srcElement}function Be(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),dl&&e.ctrlKey&&1==t&&(t=3),t}function Ge(e){if(null==Cl){var t=n("span","​");r(e,n("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Cl=t.offsetWidth<=1&&t.offsetHeight>2&&!(rl&&nl<8))}var i=Cl?n("span","​"):n("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return i.setAttribute("cm-text",""),i}function Ue(e){if(null!=Sl)return Sl;var n=r(e,document.createTextNode("AخA")),i=ml(n,0,1).getBoundingClientRect(),o=ml(n,1,2).getBoundingClientRect();return t(e),!(!i||i.left==i.right)&&(Sl=o.right-i.right<3)}function Ve(e){if(null!=Ul)return Ul;var t=r(e,n("span","x")),i=t.getBoundingClientRect(),o=ml(t,0,1).getBoundingClientRect();return Ul=Math.abs(i.left-o.left)>1}function Ke(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Vl[e]=t}function je(e,t){Kl[e]=t}function Xe(e){if("string"==typeof e&&Kl.hasOwnProperty(e))e=Kl[e];else if(e&&"string"==typeof e.name&&Kl.hasOwnProperty(e.name)){var t=Kl[e.name];"string"==typeof t&&(t={name:t}),e=b(t,e),e.name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Xe("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Xe("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Ye(e,t){t=Xe(t);var r=Vl[t.name];if(!r)return Ye(e,"text/plain");var n=r(e,t);if(jl.hasOwnProperty(t.name)){var i=jl[t.name];for(var o in i)i.hasOwnProperty(o)&&(n.hasOwnProperty(o)&&(n["_"+o]=n[o]),n[o]=i[o])}if(n.name=t.name,t.helperType&&(n.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)n[l]=t.modeProps[l];return n}function _e(e,t){var r=jl.hasOwnProperty(e)?jl[e]:jl[e]={};u(t,r)}function $e(e,t){if(t===!0)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}function qe(e,t){for(var r;e.innerMode&&(r=e.innerMode(t),r&&r.mode!=e);)t=r.state,e=r.mode;return r||{mode:e,state:t}}function Ze(e,t,r){return!e.startState||e.startState(t,r)}function Qe(e,t,r,n){var i=[e.state.modeGen],o={};lt(e,t.text,e.doc.mode,r,function(e,t){return i.push(e,t)},o,n);for(var l=function(r){var n=e.state.overlays[r],l=1,s=0;lt(e,t.text,n.mode,!0,function(e,t){for(var r=l;s<e;){var o=i[l];o>e&&i.splice(l,1,e,i[l+1],o),l+=2,s=Math.min(e,o)}if(t)if(n.opaque)i.splice(r,l-r,e,"overlay "+t),l=r+2;else for(;r<l;r+=2){var a=i[r+1];i[r+1]=(a?a+" ":"")+"overlay "+t}},o)},s=0;s<e.state.overlays.length;++s)l(s);return{styles:i,classes:o.bgClass||o.textClass?o:null}}function Je(e,t,r){if(!t.styles||t.styles[0]!=e.state.modeGen){var n=et(e,A(t)),i=Qe(e,t,t.text.length>e.options.maxHighlightLength?$e(e.doc.mode,n):n);t.stateAfter=n,t.styles=i.styles,i.classes?t.styleClasses=i.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.frontier&&e.doc.frontier++}return t.styles}function et(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return!0;var o=st(e,t,r),l=o>n.first&&T(n,o-1).stateAfter;return l=l?$e(n.mode,l):Ze(n.mode),n.iter(o,t,function(r){tt(e,r.text,l);var s=o==t-1||o%5==0||o>=i.viewFrom&&o<i.viewTo;r.stateAfter=s?$e(n.mode,l):null,++o}),r&&(n.frontier=o),l}function tt(e,t,r,n){var i=e.doc.mode,o=new Xl(t,e.options.tabSize);for(o.start=o.pos=n||0,""==t&&rt(i,r);!o.eol();)nt(i,o,r),o.start=o.pos}function rt(e,t){if(e.blankLine)return e.blankLine(t);if(e.innerMode){var r=qe(e,t);return r.mode.blankLine?r.mode.blankLine(r.state):void 0}}function nt(e,t,r,n){for(var i=0;i<10;i++){n&&(n[0]=qe(e,r).mode);var o=e.token(t,r);if(t.pos>t.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}function it(e,t,r,n){var i,o=function(e){return{start:f.start,end:f.pos,string:f.current(),type:i||null,state:e?$e(l.mode,c):c}},l=e.doc,s=l.mode;t=R(l,t);var a,u=T(l,t.line),c=et(e,t.line,r),f=new Xl(u.text,e.options.tabSize);for(n&&(a=[]);(n||f.pos<t.ch)&&!f.eol();)f.start=f.pos,i=nt(s,f,c),n&&a.push(o(!0));return n?a:o()}function ot(e,t){if(e)for(;;){var r=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!r)break;e=e.slice(0,r.index)+e.slice(r.index+r[0].length);var n=r[1]?"bgClass":"textClass";null==t[n]?t[n]=r[2]:new RegExp("(?:^|s)"+r[2]+"(?:$|s)").test(t[n])||(t[n]+=" "+r[2])}return e}function lt(e,t,r,n,i,o,l){var s=r.flattenSpans;null==s&&(s=e.options.flattenSpans);var a,u=0,c=null,f=new Xl(t,e.options.tabSize),h=e.options.addModeClass&&[null];for(""==t&&ot(rt(r,n),o);!f.eol();){if(f.pos>e.options.maxHighlightLength?(s=!1,l&&tt(e,t,n,f.pos),f.pos=t.length,a=null):a=ot(nt(r,f,n,h),o),h){var d=h[0].name;d&&(a="m-"+(a?d+" "+a:d))}if(!s||c!=a){for(;u<f.start;)u=Math.min(f.start,u+5e3),i(u,c);c=a}f.start=f.pos}for(;u<f.pos;){var p=Math.min(f.pos,u+5e3);i(p,c),u=p}}function st(e,t,r){for(var n,i,o=e.doc,l=r?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>l;--s){if(s<=o.first)return o.first;var a=T(o,s-1);if(a.stateAfter&&(!r||s<=o.frontier))return s;var u=c(a.text,null,e.options.tabSize);(null==i||n>u)&&(i=s-1,n=u)}return i}function at(e,t,r){this.text=e,ee(this,t),this.height=r?r(this):1}function ut(e,t,r,n){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),J(e),ee(e,r);var i=n?n(e):1;i!=e.height&&N(e,i)}function ct(e){e.parent=null,J(e)}function ft(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?$l:_l;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function ht(e,t){var r=n("span",null,null,il?"padding-right: .1px":null),i={pre:n("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:(rl||il)&&e.getOption("lineWrapping")};r.setAttribute("role","presentation"),i.pre.setAttribute("role","presentation"),t.measure={};for(var o=0;o<=(t.rest?t.rest.length:0);o++){var l=o?t.rest[o-1]:t.line,a=void 0;i.pos=0,i.addToken=pt,Ue(e.display.measure)&&(a=ke(l))&&(i.addToken=vt(i.addToken,a)),i.map=[];var u=t!=e.display.externalMeasured&&A(l);yt(l,i,Je(e,l,u)),l.styleClasses&&(l.styleClasses.bgClass&&(i.bgClass=s(l.styleClasses.bgClass,i.bgClass||"")),l.styleClasses.textClass&&(i.textClass=s(l.styleClasses.textClass,i.textClass||""))),0==i.map.length&&i.map.push(0,0,i.content.appendChild(Ge(e.display.measure))),0==o?(t.measure.map=i.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(i.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(il){var c=i.content.lastChild;(/\bcm-tab\b/.test(c.className)||c.querySelector&&c.querySelector(".cm-tab"))&&(i.content.className="cm-tab-wrap-hack")}return Oe(e,"renderLine",e,t.line,i.pre),i.pre.className&&(i.textClass=s(i.pre.className,i.textClass||"")),i}function dt(e){var t=n("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function pt(e,t,r,i,o,l,s){if(t){var a,u=e.splitSpaces?gt(t,e.trailingSpace):t,c=e.cm.state.specialChars,f=!1;if(c.test(t)){a=document.createDocumentFragment();for(var h=0;;){c.lastIndex=h;var d=c.exec(t),g=d?d.index-h:t.length-h;if(g){var v=document.createTextNode(u.slice(h,h+g));rl&&nl<9?a.appendChild(n("span",[v])):a.appendChild(v),e.map.push(e.pos,e.pos+g,v),e.col+=g,e.pos+=g}if(!d)break;h+=g+1;var m=void 0;if("\t"==d[0]){var y=e.cm.options.tabSize,b=y-e.col%y;m=a.appendChild(n("span",p(b),"cm-tab")),m.setAttribute("role","presentation"),m.setAttribute("cm-text","\t"),e.col+=b}else"\r"==d[0]||"\n"==d[0]?(m=a.appendChild(n("span","\r"==d[0]?"␍":"␤","cm-invalidchar")),m.setAttribute("cm-text",d[0]),e.col+=1):(m=e.cm.options.specialCharPlaceholder(d[0]),m.setAttribute("cm-text",d[0]),rl&&nl<9?a.appendChild(n("span",[m])):a.appendChild(m),e.col+=1);e.map.push(e.pos,e.pos+1,m),e.pos++}}else e.col+=t.length,a=document.createTextNode(u),e.map.push(e.pos,e.pos+t.length,a),rl&&nl<9&&(f=!0),e.pos+=t.length;if(e.trailingSpace=32==u.charCodeAt(t.length-1),r||i||o||f||s){var w=r||"";i&&(w+=i),o&&(w+=o);var x=n("span",[a],w,s);return l&&(x.title=l),e.content.appendChild(x)}e.content.appendChild(a)}}function gt(e,t){if(e.length>1&&!/ /.test(e))return e;for(var r=t,n="",i=0;i<e.length;i++){var o=e.charAt(i);" "!=o||!r||i!=e.length-1&&32!=e.charCodeAt(i+1)||(o=" "),n+=o,r=" "==o}return n}function vt(e,t){return function(r,n,i,o,l,s,a){i=i?i+" cm-force-border":"cm-force-border";for(var u=r.pos,c=u+n.length;;){for(var f=void 0,h=0;h<t.length&&(f=t[h],!(f.to>u&&f.from<=u));h++);if(f.to>=c)return e(r,n,i,o,l,s,a);e(r,n.slice(0,f.to-u),i,o,null,s,a),o=null,n=n.slice(f.to-u),u=f.to}}}function mt(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function yt(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var l,s,a,u,c,f,h,d=i.length,p=0,g=1,v="",m=0;;){if(m==p){a=u=c=f=s="",h=null,m=1/0;for(var y=[],b=void 0,w=0;w<n.length;++w){var x=n[w],C=x.marker;"bookmark"==C.type&&x.from==p&&C.widgetNode?y.push(C):x.from<=p&&(null==x.to||x.to>p||C.collapsed&&x.to==p&&x.from==p)?(null!=x.to&&x.to!=p&&m>x.to&&(m=x.to,u=""),C.className&&(a+=" "+C.className),C.css&&(s=(s?s+";":"")+C.css),C.startStyle&&x.from==p&&(c+=" "+C.startStyle),C.endStyle&&x.to==m&&(b||(b=[])).push(C.endStyle,x.to),C.title&&!f&&(f=C.title),C.collapsed&&(!h||ne(h.marker,C)<0)&&(h=x)):x.from>p&&m>x.from&&(m=x.from)}if(b)for(var S=0;S<b.length;S+=2)b[S+1]==m&&(u+=" "+b[S]);if(!h||h.from==p)for(var L=0;L<y.length;++L)mt(t,0,y[L]);if(h&&(h.from||0)==p){if(mt(t,(null==h.to?d+1:h.to)-p,h.marker,null==h.from),null==h.to)return;h.to==p&&(h=!1)}}if(p>=d)break;for(var T=Math.min(d,m);;){if(v){var M=p+v.length;if(!h){var k=M>T?v.slice(0,T-p):v;t.addToken(t,k,l?l+a:a,c,p+k.length==m?u:"",f,s)}if(M>=T){v=v.slice(T-p),p=T;break}p=M,c=""}v=i.slice(o,o=r[g++]),l=ft(r[g++],t.cm.options)}}else for(var N=1;N<r.length;N+=2)t.addToken(t,i.slice(o,o=r[N]),ft(r[N+1],t.cm.options))}function bt(e,t,r){this.line=t,this.rest=ue(t),this.size=this.rest?A(g(this.rest))-r+1:1,this.node=this.text=null,this.hidden=he(e,t)}function wt(e,t,r){for(var n,i=[],o=t;o<r;o=n){var l=new bt(e.doc,T(e.doc,o),o);n=o+l.size,i.push(l)}return i}function xt(e){ql?ql.ops.push(e):e.ownsGroup=ql={ops:[e],delayedCallbacks:[]}}function Ct(e){var t=e.delayedCallbacks,r=0;do{for(;r<t.length;r++)t[r].call(null);for(var n=0;n<e.ops.length;n++){var i=e.ops[n];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++].call(null,i.cm)}}while(r<t.length)}function St(e,t){var r=e.ownsGroup;if(r)try{Ct(r)}finally{ql=null,t(r)}}function Lt(e,t){var r=Ne(e,t);if(r.length){var n,i=Array.prototype.slice.call(arguments,2);ql?n=ql.delayedCallbacks:Zl?n=Zl:(n=Zl=[],setTimeout(Tt,0));for(var o=function(e){n.push(function(){return r[e].apply(null,i)})},l=0;l<r.length;++l)o(l)}}function Tt(){var e=Zl;Zl=null;for(var t=0;t<e.length;++t)e[t]()}function Mt(e,t,r,n){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?Ot(e,t):"gutter"==o?Dt(e,t,r,n):"class"==o?Wt(t):"widget"==o&&Ht(e,t,n)}t.changes=null}function kt(e){return e.node==e.text&&(e.node=n("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),rl&&nl<8&&(e.node.style.zIndex=2)),e.node}function Nt(e){var t=e.bgClass?e.bgClass+" "+(e.line.bgClass||""):e.line.bgClass;if(t&&(t+=" CodeMirror-linebackground"),e.background)t?e.background.className=t:(e.background.parentNode.removeChild(e.background),e.background=null);else if(t){var r=kt(e);e.background=r.insertBefore(n("div",null,t),r.firstChild)}}function At(e,t){var r=e.display.externalMeasured;return r&&r.line==t.line?(e.display.externalMeasured=null,t.measure=r.measure,r.built):ht(e,t)}function Ot(e,t){var r=t.text.className,n=At(e,t);t.text==t.node&&(t.node=n.pre),t.text.parentNode.replaceChild(n.pre,t.text),t.text=n.pre,n.bgClass!=t.bgClass||n.textClass!=t.textClass?(t.bgClass=n.bgClass,t.textClass=n.textClass,Wt(t)):r&&(t.text.className=r)}function Wt(e){Nt(e),e.line.wrapClass?kt(e).className=e.line.wrapClass:e.node!=e.text&&(e.node.className="");var t=e.textClass?e.textClass+" "+(e.line.textClass||""):e.line.textClass;e.text.className=t||""}function Dt(e,t,r,i){if(t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null),t.gutterBackground&&(t.node.removeChild(t.gutterBackground),t.gutterBackground=null),t.line.gutterClass){var o=kt(t);t.gutterBackground=n("div",null,"CodeMirror-gutter-background "+t.line.gutterClass,"left: "+(e.options.fixedGutter?i.fixedPos:-i.gutterTotalWidth)+"px; width: "+i.gutterTotalWidth+"px"),o.insertBefore(t.gutterBackground,t.text)}var l=t.line.gutterMarkers;if(e.options.lineNumbers||l){var s=kt(t),a=t.gutter=n("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?i.fixedPos:-i.gutterTotalWidth)+"px");if(e.display.input.setUneditable(a),s.insertBefore(a,t.text),t.line.gutterClass&&(a.className+=" "+t.line.gutterClass),!e.options.lineNumbers||l&&l["CodeMirror-linenumbers"]||(t.lineNumber=a.appendChild(n("div",D(e.options,r),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+i.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),l)for(var u=0;u<e.options.gutters.length;++u){var c=e.options.gutters[u],f=l.hasOwnProperty(c)&&l[c];f&&a.appendChild(n("div",[f],"CodeMirror-gutter-elt","left: "+i.gutterLeft[c]+"px; width: "+i.gutterWidth[c]+"px"))}}}function Ht(e,t,r){t.alignable&&(t.alignable=null);for(var n=t.node.firstChild,i=void 0;n;n=i)i=n.nextSibling,"CodeMirror-linewidget"==n.className&&t.node.removeChild(n);Et(e,t,r)}function Pt(e,t,r,n){var i=At(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),Wt(t),Dt(e,t,r,n),Et(e,t,n),t.node}function Et(e,t,r){if(It(e,t.line,t,r,!0),t.rest)for(var n=0;n<t.rest.length;n++)It(e,t.rest[n],t,r,!1)}function It(e,t,r,i,o){if(t.widgets)for(var l=kt(r),s=0,a=t.widgets;s<a.length;++s){var u=a[s],c=n("div",[u.node],"CodeMirror-linewidget");u.handleMouseEvents||c.setAttribute("cm-ignore-events","true"),zt(u,c,r,i),e.display.input.setUneditable(c),o&&u.above?l.insertBefore(c,r.gutter||r.text):l.appendChild(c),Lt(u,"redraw")}}function zt(e,t,r,n){if(e.noHScroll){(r.alignable||(r.alignable=[])).push(t);var i=n.wrapperWidth;t.style.left=n.fixedPos+"px",e.coverGutter||(i-=n.gutterTotalWidth,t.style.paddingLeft=n.gutterTotalWidth+"px"),t.style.width=i+"px"}e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-n.gutterTotalWidth+"px"))}function Ft(e){if(null!=e.height)return e.height;var t=e.doc.cm;if(!t)return 0;if(!i(document.body,e.node)){var o="position: relative;";e.coverGutter&&(o+="margin-left: -"+t.display.gutters.offsetWidth+"px;"),e.noHScroll&&(o+="width: "+t.display.wrapper.clientWidth+"px;"),r(t.display.measure,n("div",[e.node],null,o))}return e.height=e.node.parentNode.offsetHeight}function Rt(e,t){for(var r=Re(t);r!=e.wrapper;r=r.parentNode)if(!r||1==r.nodeType&&"true"==r.getAttribute("cm-ignore-events")||r.parentNode==e.sizer&&r!=e.mover)return!0}function Bt(e){return e.lineSpace.offsetTop}function Gt(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function Ut(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=r(e.measure,n("pre","x")),i=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,o={left:parseInt(i.paddingLeft),right:parseInt(i.paddingRight)};return isNaN(o.left)||isNaN(o.right)||(e.cachedPaddingH=o),o}function Vt(e){return Ll-e.display.nativeBarWidth}function Kt(e){return e.display.scroller.clientWidth-Vt(e)-e.display.barWidth}function jt(e){return e.display.scroller.clientHeight-Vt(e)-e.display.barHeight}function Xt(e,t,r){var n=e.options.lineWrapping,i=n&&Kt(e);if(!t.measure.heights||n&&t.measure.width!=i){var o=t.measure.heights=[];if(n){t.measure.width=i;for(var l=t.text.firstChild.getClientRects(),s=0;s<l.length-1;s++){var a=l[s],u=l[s+1];Math.abs(a.bottom-u.bottom)>2&&o.push((a.bottom+u.top)/2-r.top)}}o.push(r.bottom-r.top)}}function Yt(e,t,r){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var n=0;n<e.rest.length;n++)if(e.rest[n]==t)return{map:e.measure.maps[n],cache:e.measure.caches[n]};for(var i=0;i<e.rest.length;i++)if(A(e.rest[i])>r)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function _t(e,t){t=ae(t);var n=A(t),i=e.display.externalMeasured=new bt(e.doc,t,n);i.lineN=n;var o=i.built=ht(e,i);return i.text=o.pre,r(e.display.lineMeasure,o.pre),i}function $t(e,t,r,n){return Qt(e,Zt(e,t),r,n)}function qt(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[Sr(e,t)];var r=e.display.externalMeasured;return r&&t>=r.lineN&&t<r.lineN+r.size?r:void 0}function Zt(e,t){var r=A(t),n=qt(e,r);n&&!n.text?n=null:n&&n.changes&&(Mt(e,n,r,yr(e)),e.curOp.forceUpdate=!0),n||(n=_t(e,t));var i=Yt(n,t,r);return{line:t,view:n,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function Qt(e,t,r,n,i){t.before&&(r=-1);var o,l=r+(n||"");return t.cache.hasOwnProperty(l)?o=t.cache[l]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||(Xt(e,t.view,t.rect),t.hasHeights=!0),o=tr(e,t,r,n),o.bogus||(t.cache[l]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}function Jt(e,t,r){for(var n,i,o,l,s,a,u=0;u<e.length;u+=3)if(s=e[u],a=e[u+1],t<s?(i=0,o=1,l="left"):t<a?(i=t-s,o=i+1):(u==e.length-3||t==a&&e[u+3]>t)&&(o=a-s,i=o-1,t>=a&&(l="right")),null!=i){if(n=e[u+2],s==a&&r==(n.insertLeft?"left":"right")&&(l=r),"left"==r&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)n=e[(u-=3)+2],l="left";if("right"==r&&i==a-s)for(;u<e.length-3&&e[u+3]==e[u+4]&&!e[u+5].insertLeft;)n=e[(u+=3)+2],l="right";break}return{node:n,start:i,end:o,collapse:l,coverStart:s,coverEnd:a}}function er(e,t){var r=Ql;if("left"==t)for(var n=0;n<e.length&&(r=e[n]).left==r.right;n++);else for(var i=e.length-1;i>=0&&(r=e[i]).left==r.right;i--);return r}function tr(e,t,r,n){var i,o=Jt(t.map,r,n),l=o.node,s=o.start,a=o.end,u=o.collapse;if(3==l.nodeType){for(var c=0;c<4;c++){for(;s&&S(t.line.text.charAt(o.coverStart+s));)--s;for(;o.coverStart+a<o.coverEnd&&S(t.line.text.charAt(o.coverStart+a));)++a;if(i=rl&&nl<9&&0==s&&a==o.coverEnd-o.coverStart?l.parentNode.getBoundingClientRect():er(ml(l,s,a).getClientRects(),n),
2
+ i.left||i.right||0==s)break;a=s,s-=1,u="right"}rl&&nl<11&&(i=rr(e.display.measure,i))}else{s>0&&(u=n="right");var f;i=e.options.lineWrapping&&(f=l.getClientRects()).length>1?f["right"==n?f.length-1:0]:l.getBoundingClientRect()}if(rl&&nl<9&&!s&&(!i||!i.left&&!i.right)){var h=l.parentNode.getClientRects()[0];i=h?{left:h.left,right:h.left+mr(e.display),top:h.top,bottom:h.bottom}:Ql}for(var d=i.top-t.rect.top,p=i.bottom-t.rect.top,g=(d+p)/2,v=t.view.measure.heights,m=0;m<v.length-1&&!(g<v[m]);m++);var y=m?v[m-1]:0,b=v[m],w={left:("right"==u?i.right:i.left)-t.rect.left,right:("left"==u?i.left:i.right)-t.rect.left,top:y,bottom:b};return i.left||i.right||(w.bogus=!0),e.options.singleCursorHeightPerLine||(w.rtop=d,w.rbottom=p),w}function rr(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!Ve(e))return t;var r=screen.logicalXDPI/screen.deviceXDPI,n=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*r,right:t.right*r,top:t.top*n,bottom:t.bottom*n}}function nr(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function ir(e){e.display.externalMeasure=null,t(e.display.lineMeasure);for(var r=0;r<e.display.view.length;r++)nr(e.display.view[r])}function or(e){ir(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function lr(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function sr(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function ar(e,t,r,n,i){if(!i&&t.widgets)for(var o=0;o<t.widgets.length;++o)if(t.widgets[o].above){var l=Ft(t.widgets[o]);r.top+=l,r.bottom+=l}if("line"==n)return r;n||(n="local");var s=pe(t);if("local"==n?s+=Bt(e.display):s-=e.display.viewOffset,"page"==n||"window"==n){var a=e.display.lineSpace.getBoundingClientRect();s+=a.top+("window"==n?0:sr());var u=a.left+("window"==n?0:lr());r.left+=u,r.right+=u}return r.top+=s,r.bottom+=s,r}function ur(e,t,r){if("div"==r)return t;var n=t.left,i=t.top;if("page"==r)n-=lr(),i-=sr();else if("local"==r||!r){var o=e.display.sizer.getBoundingClientRect();n+=o.left,i+=o.top}var l=e.display.lineSpace.getBoundingClientRect();return{left:n-l.left,top:i-l.top}}function cr(e,t,r,n,i){return n||(n=T(e.doc,t.line)),ar(e,n,$t(e,n,t.ch,i),r)}function fr(e,t,r,n,i,o){function l(t,l){var s=Qt(e,i,t,l?"right":"left",o);return l?s.left=s.right:s.right=s.left,ar(e,n,s,r)}function s(e,t){var r=a[t],n=r.level%2;return e==ye(r)&&t&&r.level<a[t-1].level?(r=a[--t],e=be(r)-(r.level%2?0:1),n=!0):e==be(r)&&t<a.length-1&&r.level<a[t+1].level&&(r=a[++t],e=ye(r)-r.level%2,n=!1),n&&e==r.to&&e>r.from?l(e-1):l(e,n)}n=n||T(e.doc,t.line),i||(i=Zt(e,n));var a=ke(n),u=t.ch;if(!a)return l(u);var c=Se(a,u),f=s(u,c);return null!=Pl&&(f.other=s(u,Pl)),f}function hr(e,t){var r=0;t=R(e.doc,t),e.options.lineWrapping||(r=mr(e.display)*t.ch);var n=T(e.doc,t.line),i=pe(n)+Bt(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function dr(e,t,r,n){var i=H(e,t);return i.xRel=n,r&&(i.outside=!0),i}function pr(e,t,r){var n=e.doc;if(r+=e.display.viewOffset,r<0)return dr(n.first,0,!0,-1);var i=O(n,r),o=n.first+n.size-1;if(i>o)return dr(n.first+n.size-1,T(n,o).text.length,!0,1);t<0&&(t=0);for(var l=T(n,i);;){var s=gr(e,l,i,t,r),a=le(l),u=a&&a.find(0,!0);if(!a||!(s.ch>u.from.ch||s.ch==u.from.ch&&s.xRel>0))return s;i=A(l=u.to.line)}}function gr(e,t,r,n,i){function o(n){var i=fr(e,H(r,n),"line",t,u);return s=!0,l>i.bottom?i.left-a:l<i.top?i.left+a:(s=!1,i.left)}var l=i-pe(t),s=!1,a=2*e.display.wrapper.clientWidth,u=Zt(e,t),c=ke(t),f=t.text.length,h=we(t),d=xe(t),p=o(h),g=s,v=o(d),m=s;if(n>v)return dr(r,d,m,1);for(;;){if(c?d==h||d==Te(t,h,1):d-h<=1){var y=n<p||n-p<=v-n?h:d,b=y==h?g:m,w=n-(y==h?p:v);if(m&&!c&&!/\s/.test(t.text.charAt(y))&&w>0&&y<t.text.length&&u.view.measure.heights.length>1){var x=Qt(e,u,y,"right");l<=x.bottom&&l>=x.top&&Math.abs(n-x.right)<w&&(b=!1,y++,w=n-x.right)}for(;S(t.text.charAt(y));)++y;var C=dr(r,y,b,w<-1?-1:w>1?1:0);return C}var L=Math.ceil(f/2),T=h+L;if(c){T=h;for(var M=0;M<L;++M)T=Te(t,T,1)}var k=o(T);k>n?(d=T,v=k,(m=s)&&(v+=1e3),f=L):(h=T,p=k,g=s,f-=L)}}function vr(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Yl){Yl=n("pre");for(var i=0;i<49;++i)Yl.appendChild(document.createTextNode("x")),Yl.appendChild(n("br"));Yl.appendChild(document.createTextNode("x"))}r(e.measure,Yl);var o=Yl.offsetHeight/50;return o>3&&(e.cachedTextHeight=o),t(e.measure),o||1}function mr(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=n("span","xxxxxxxxxx"),i=n("pre",[t]);r(e.measure,i);var o=t.getBoundingClientRect(),l=(o.right-o.left)/10;return l>2&&(e.cachedCharWidth=l),l||10}function yr(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l)r[e.options.gutters[l]]=o.offsetLeft+o.clientLeft+i,n[e.options.gutters[l]]=o.clientWidth;return{fixedPos:br(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function br(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function wr(e){var t=vr(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/mr(e.display)-3);return function(i){if(he(e.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l<i.widgets.length;l++)i.widgets[l].height&&(o+=i.widgets[l].height);return r?o+(Math.ceil(i.text.length/n)||1)*t:o+t}}function xr(e){var t=e.doc,r=wr(e);t.iter(function(e){var t=r(e);t!=e.height&&N(e,t)})}function Cr(e,t,r,n){var i=e.display;if(!r&&"true"==Re(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(t){return null}var a,u=pr(e,o,l);if(n&&1==u.xRel&&(a=T(e.doc,u.line).text).length==u.ch){var f=c(a,a.length,e.options.tabSize)-a.length;u=H(u.line,Math.max(0,Math.round((o-Ut(e.display).left)/mr(e.display))-f))}return u}function Sr(e,t){if(t>=e.display.viewTo)return null;if(t-=e.display.viewFrom,t<0)return null;for(var r=e.display.view,n=0;n<r.length;n++)if(t-=r[n].size,t<0)return n}function Lr(e){e.display.input.showSelection(e.display.input.prepareSelection())}function Tr(e,t){for(var r=e.doc,n={},i=n.cursors=document.createDocumentFragment(),o=n.selection=document.createDocumentFragment(),l=0;l<r.sel.ranges.length;l++)if(t!==!1||l!=r.sel.primIndex){var s=r.sel.ranges[l];if(!(s.from().line>=e.display.viewTo||s.to().line<e.display.viewFrom)){var a=s.empty();(a||e.options.showCursorWhenSelecting)&&Mr(e,s.head,i),a||kr(e,s,o)}}return n}function Mr(e,t,r){var i=fr(e,t,"div",null,null,!e.options.singleCursorHeightPerLine),o=r.appendChild(n("div"," ","CodeMirror-cursor"));if(o.style.left=i.left+"px",o.style.top=i.top+"px",o.style.height=Math.max(0,i.bottom-i.top)*e.options.cursorHeight+"px",i.other){var l=r.appendChild(n("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));l.style.display="",l.style.left=i.other.left+"px",l.style.top=i.other.top+"px",l.style.height=.85*(i.other.bottom-i.other.top)+"px"}}function kr(e,t,r){function i(e,t,r,i){t<0&&(t=0),t=Math.round(t),i=Math.round(i),a.appendChild(n("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==r?f-e:r)+"px;\n height: "+(i-t)+"px"))}function o(t,r,n){function o(r,n){return cr(e,H(t,r),"div",u,n)}var l,a,u=T(s,t),h=u.text.length;return me(ke(u),r||0,null==n?h:n,function(e,t,s){var u,d,p,g=o(e,"left");if(e==t)u=g,d=p=g.left;else{if(u=o(t-1,"right"),"rtl"==s){var v=g;g=u,u=v}d=g.left,p=u.right}null==r&&0==e&&(d=c),u.top-g.top>3&&(i(d,g.top,null,g.bottom),d=c,g.bottom<u.top&&i(d,g.bottom,null,u.top)),null==n&&t==h&&(p=f),(!l||g.top<l.top||g.top==l.top&&g.left<l.left)&&(l=g),(!a||u.bottom>a.bottom||u.bottom==a.bottom&&u.right>a.right)&&(a=u),d<c+1&&(d=c),i(d,u.top,p-d,u.bottom)}),{start:l,end:a}}var l=e.display,s=e.doc,a=document.createDocumentFragment(),u=Ut(e.display),c=u.left,f=Math.max(l.sizerWidth,Kt(e)-l.sizer.offsetLeft)-u.right,h=t.from(),d=t.to();if(h.line==d.line)o(h.line,h.ch,d.ch);else{var p=T(s,h.line),g=T(s,d.line),v=ae(p)==ae(g),m=o(h.line,h.ch,v?p.text.length+1:null).end,y=o(d.line,v?0:null,d.ch).start;v&&(m.top<y.top-2?(i(m.right,m.top,null,m.bottom),i(c,y.top,y.left,y.bottom)):i(m.right,m.top,y.left-m.right,m.bottom)),m.bottom<y.top&&i(c,m.bottom,null,y.top)}r.appendChild(a)}function Nr(e){if(e.state.focused){var t=e.display;clearInterval(t.blinker);var r=!0;t.cursorDiv.style.visibility="",e.options.cursorBlinkRate>0?t.blinker=setInterval(function(){return t.cursorDiv.style.visibility=(r=!r)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function Ar(e){e.state.focused||(e.display.input.focus(),Wr(e))}function Or(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,Dr(e))},100)}function Wr(e,t){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(Oe(e,"focus",e,t),e.state.focused=!0,l(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),il&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),Nr(e))}function Dr(e,t){e.state.delayingBlurEvent||(e.state.focused&&(Oe(e,"blur",e,t),e.state.focused=!1,wl(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function Hr(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=br(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",l=0;l<r.length;l++)if(!r[l].hidden){e.options.fixedGutter&&(r[l].gutter&&(r[l].gutter.style.left=o),r[l].gutterBackground&&(r[l].gutterBackground.style.left=o));var s=r[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=n+i+"px")}}function Pr(e){if(!e.options.lineNumbers)return!1;var t=e.doc,r=D(e.options,t.first+t.size-1),i=e.display;if(r.length!=i.lineNumChars){var o=i.measure.appendChild(n("div",[n("div",r)],"CodeMirror-linenumber CodeMirror-gutter-elt")),l=o.firstChild.offsetWidth,s=o.offsetWidth-l;return i.lineGutter.style.width="",i.lineNumInnerWidth=Math.max(l,i.lineGutter.offsetWidth-s)+1,i.lineNumWidth=i.lineNumInnerWidth+s,i.lineNumChars=i.lineNumInnerWidth?r.length:-1,i.lineGutter.style.width=i.lineNumWidth+"px",Mn(e),!0}return!1}function Er(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=0;n<t.view.length;n++){var i=t.view[n],o=void 0;if(!i.hidden){if(rl&&nl<8){var l=i.node.offsetTop+i.node.offsetHeight;o=l-r,r=l}else{var s=i.node.getBoundingClientRect();o=s.bottom-s.top}var a=i.line.height-o;if(o<2&&(o=vr(t)),(a>.001||a<-.001)&&(N(i.line,o),Ir(i.line),i.rest))for(var u=0;u<i.rest.length;u++)Ir(i.rest[u])}}}function Ir(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t)e.widgets[t].height=e.widgets[t].node.parentNode.offsetHeight}function zr(e,t,r){var n=r&&null!=r.top?Math.max(0,r.top):e.scroller.scrollTop;n=Math.floor(n-Bt(e));var i=r&&null!=r.bottom?r.bottom:n+e.wrapper.clientHeight,o=O(t,n),l=O(t,i);if(r&&r.ensure){var s=r.ensure.from.line,a=r.ensure.to.line;s<o?(o=s,l=O(t,pe(T(t,s))+e.wrapper.clientHeight)):Math.min(a,t.lastLine())>=l&&(o=O(t,pe(T(t,a))-e.wrapper.clientHeight),l=a)}return{from:o,to:Math.max(l,o+1)}}function Fr(e,t){Math.abs(e.doc.scrollTop-t)<2||(e.doc.scrollTop=t,Jo||Ln(e,{top:t}),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t),e.display.scrollbars.setScrollTop(t),Jo&&Ln(e),bn(e,100))}function Rr(e,t,r){(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)||(t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),e.doc.scrollLeft=t,Hr(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Br(e){var t=e.wheelDeltaX,r=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==r&&e.detail&&e.axis==e.VERTICAL_AXIS?r=e.detail:null==r&&(r=e.wheelDelta),{x:t,y:r}}function Gr(e){var t=Br(e);return t.x*=es,t.y*=es,t}function Ur(e,t){var r=Br(t),n=r.x,i=r.y,o=e.display,l=o.scroller,s=l.scrollWidth>l.clientWidth,a=l.scrollHeight>l.clientHeight;if(n&&s||i&&a){if(i&&dl&&il)e:for(var u=t.target,c=o.view;u!=l;u=u.parentNode)for(var f=0;f<c.length;f++)if(c[f].node==u){e.display.currentWheelTarget=u;break e}if(n&&!Jo&&!sl&&null!=es)return i&&a&&Fr(e,Math.max(0,Math.min(l.scrollTop+i*es,l.scrollHeight-l.clientHeight))),Rr(e,Math.max(0,Math.min(l.scrollLeft+n*es,l.scrollWidth-l.clientWidth))),(!i||i&&a)&&Ee(t),void(o.wheelStartX=null);if(i&&null!=es){var h=i*es,d=e.doc.scrollTop,p=d+o.wrapper.clientHeight;h<0?d=Math.max(0,d+h-50):p=Math.min(e.doc.height,p+h+50),Ln(e,{top:d,bottom:p})}Jl<20&&(null==o.wheelStartX?(o.wheelStartX=l.scrollLeft,o.wheelStartY=l.scrollTop,o.wheelDX=n,o.wheelDY=i,setTimeout(function(){if(null!=o.wheelStartX){var e=l.scrollLeft-o.wheelStartX,t=l.scrollTop-o.wheelStartY,r=t&&o.wheelDY&&t/o.wheelDY||e&&o.wheelDX&&e/o.wheelDX;o.wheelStartX=o.wheelStartY=null,r&&(es=(es*Jl+r)/(Jl+1),++Jl)}},200)):(o.wheelDX+=n,o.wheelDY+=i))}}function Vr(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Gt(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+Vt(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}function Kr(e,t){t||(t=Vr(e));var r=e.display.barWidth,n=e.display.barHeight;jr(e,t);for(var i=0;i<4&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&Er(e),jr(e,Vr(e)),r=e.display.barWidth,n=e.display.barHeight}function jr(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",r.heightForcer.style.borderBottom=n.bottom+"px solid transparent",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}function Xr(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&wl(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new ns[e.options.scrollbarStyle](function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),zl(t,"mousedown",function(){e.state.focused&&setTimeout(function(){return e.display.input.focus()},0)}),t.setAttribute("cm-not-content","true")},function(t,r){"horizontal"==r?Rr(e,t):Fr(e,t)},e),e.display.scrollbars.addClass&&l(e.display.wrapper,e.display.scrollbars.addClass)}function Yr(e,t){if(!We(e,"scrollCursorIntoView")){var r=e.display,i=r.sizer.getBoundingClientRect(),o=null;if(t.top+i.top<0?o=!0:t.bottom+i.top>(window.innerHeight||document.documentElement.clientHeight)&&(o=!1),null!=o&&!cl){var l=n("div","​",null,"position: absolute;\n top: "+(t.top-r.viewOffset-Bt(e.display))+"px;\n height: "+(t.bottom-t.top+Vt(e)+r.barHeight)+"px;\n left: "+t.left+"px; width: 2px;");e.display.lineSpace.appendChild(l),l.scrollIntoView(o),e.display.lineSpace.removeChild(l)}}}function _r(e,t,r,n){null==n&&(n=0);for(var i,o=0;o<5;o++){var l=!1;i=fr(e,t);var s=r&&r!=t?fr(e,r):i,a=qr(e,Math.min(i.left,s.left),Math.min(i.top,s.top)-n,Math.max(i.left,s.left),Math.max(i.bottom,s.bottom)+n),u=e.doc.scrollTop,c=e.doc.scrollLeft;if(null!=a.scrollTop&&(Fr(e,a.scrollTop),Math.abs(e.doc.scrollTop-u)>1&&(l=!0)),null!=a.scrollLeft&&(Rr(e,a.scrollLeft),Math.abs(e.doc.scrollLeft-c)>1&&(l=!0)),!l)break}return i}function $r(e,t,r,n,i){var o=qr(e,t,r,n,i);null!=o.scrollTop&&Fr(e,o.scrollTop),null!=o.scrollLeft&&Rr(e,o.scrollLeft)}function qr(e,t,r,n,i){var o=e.display,l=vr(e.display);r<0&&(r=0);var s=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:o.scroller.scrollTop,a=jt(e),u={};i-r>a&&(i=r+a);var c=e.doc.height+Gt(o),f=r<l,h=i>c-l;if(r<s)u.scrollTop=f?0:r;else if(i>s+a){var d=Math.min(r,(h?c:i)-a);d!=s&&(u.scrollTop=d)}var p=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:o.scroller.scrollLeft,g=Kt(e)-(e.options.fixedGutter?o.gutters.offsetWidth:0),v=n-t>g;return v&&(n=t+g),t<10?u.scrollLeft=0:t<p?u.scrollLeft=Math.max(0,t-(v?0:10)):n>g+p-3&&(u.scrollLeft=n+(v?0:10)-g),u}function Zr(e,t,r){null==t&&null==r||Jr(e),null!=t&&(e.curOp.scrollLeft=(null==e.curOp.scrollLeft?e.doc.scrollLeft:e.curOp.scrollLeft)+t),null!=r&&(e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+r)}function Qr(e){Jr(e);var t=e.getCursor(),r=t,n=t;e.options.lineWrapping||(r=t.ch?H(t.line,t.ch-1):t,n=H(t.line,t.ch+1)),e.curOp.scrollToPos={from:r,to:n,margin:e.options.cursorScrollMargin,isCursor:!0}}function Jr(e){var t=e.curOp.scrollToPos;if(t){e.curOp.scrollToPos=null;var r=hr(e,t.from),n=hr(e,t.to),i=qr(e,Math.min(r.left,n.left),Math.min(r.top,n.top)-t.margin,Math.max(r.right,n.right),Math.max(r.bottom,n.bottom)+t.margin);e.scrollTo(i.scrollLeft,i.scrollTop)}}function en(e){e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++is},xt(e.curOp)}function tn(e){var t=e.curOp;St(t,function(e){for(var t=0;t<e.ops.length;t++)e.ops[t].cm.curOp=null;rn(e)})}function rn(e){for(var t=e.ops,r=0;r<t.length;r++)nn(t[r]);for(var n=0;n<t.length;n++)on(t[n]);for(var i=0;i<t.length;i++)ln(t[i]);for(var o=0;o<t.length;o++)sn(t[o]);for(var l=0;l<t.length;l++)an(t[l])}function nn(e){var t=e.cm,r=t.display;xn(t),e.updateMaxLine&&ve(t),e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<r.viewFrom||e.scrollToPos.to.line>=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new os(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function on(e){e.updatedDisplay=e.mustUpdate&&Cn(e.cm,e.update)}function ln(e){var t=e.cm,r=t.display;e.updatedDisplay&&Er(t),e.barMeasure=Vr(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=$t(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+Vt(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Kt(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection(e.focus))}function sn(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&Rr(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1);var r=e.focus&&e.focus==o()&&(!document.hasFocus||document.hasFocus());e.preparedSelection&&t.display.input.showSelection(e.preparedSelection,r),(e.updatedDisplay||e.startHeight!=t.doc.height)&&Kr(t,e.barMeasure),e.updatedDisplay&&kn(t,e.barMeasure),e.selectionChanged&&Nr(t),t.state.focused&&e.updateInput&&t.display.input.reset(e.typing),r&&Ar(e.cm)}function an(e){var t=e.cm,r=t.display,n=t.doc;if(e.updatedDisplay&&Sn(t,e.update),null==r.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(r.wheelStartX=r.wheelStartY=null),null==e.scrollTop||r.scroller.scrollTop==e.scrollTop&&!e.forceScroll||(n.scrollTop=Math.max(0,Math.min(r.scroller.scrollHeight-r.scroller.clientHeight,e.scrollTop)),r.scrollbars.setScrollTop(n.scrollTop),r.scroller.scrollTop=n.scrollTop),null==e.scrollLeft||r.scroller.scrollLeft==e.scrollLeft&&!e.forceScroll||(n.scrollLeft=Math.max(0,Math.min(r.scroller.scrollWidth-r.scroller.clientWidth,e.scrollLeft)),r.scrollbars.setScrollLeft(n.scrollLeft),r.scroller.scrollLeft=n.scrollLeft,Hr(t)),e.scrollToPos){var i=_r(t,R(n,e.scrollToPos.from),R(n,e.scrollToPos.to),e.scrollToPos.margin);e.scrollToPos.isCursor&&t.state.focused&&Yr(t,i)}var o=e.maybeHiddenMarkers,l=e.maybeUnhiddenMarkers;if(o)for(var s=0;s<o.length;++s)o[s].lines.length||Oe(o[s],"hide");if(l)for(var a=0;a<l.length;++a)l[a].lines.length&&Oe(l[a],"unhide");r.wrapper.offsetHeight&&(n.scrollTop=t.display.scroller.scrollTop),e.changeObjs&&Oe(t,"changes",t,e.changeObjs),e.update&&e.update.finish()}function un(e,t){if(e.curOp)return t();en(e);try{return t()}finally{tn(e)}}function cn(e,t){return function(){if(e.curOp)return t.apply(e,arguments);en(e);try{return t.apply(e,arguments)}finally{tn(e)}}}function fn(e){return function(){if(this.curOp)return e.apply(this,arguments);en(this);try{return e.apply(this,arguments)}finally{tn(this)}}}function hn(e){return function(){var t=this.cm;if(!t||t.curOp)return e.apply(this,arguments);en(t);try{return e.apply(this,arguments)}finally{tn(t)}}}function dn(e,t,r,n){null==t&&(t=e.doc.first),null==r&&(r=e.doc.first+e.doc.size),n||(n=0);var i=e.display;if(n&&r<i.viewTo&&(null==i.updateLineNumbers||i.updateLineNumbers>t)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Hl&&ce(e.doc,t)<i.viewTo&&gn(e);else if(r<=i.viewFrom)Hl&&fe(e.doc,r+n)>i.viewFrom?gn(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)gn(e);else if(t<=i.viewFrom){var o=vn(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):gn(e)}else if(r>=i.viewTo){var l=vn(e,t,t,-1);l?(i.view=i.view.slice(0,l.index),i.viewTo=l.lineN):gn(e)}else{var s=vn(e,t,t,-1),a=vn(e,r,r+n,1);s&&a?(i.view=i.view.slice(0,s.index).concat(wt(e,s.lineN,a.lineN)).concat(i.view.slice(a.index)),i.viewTo+=n):gn(e)}var u=i.externalMeasured;u&&(r<u.lineN?u.lineN+=n:t<u.lineN+u.size&&(i.externalMeasured=null))}function pn(e,t,r){e.curOp.viewChanged=!0;var n=e.display,i=e.display.externalMeasured;if(i&&t>=i.lineN&&t<i.lineN+i.size&&(n.externalMeasured=null),!(t<n.viewFrom||t>=n.viewTo)){var o=n.view[Sr(e,t)];if(null!=o.node){var l=o.changes||(o.changes=[]);h(l,r)==-1&&l.push(r)}}}function gn(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function vn(e,t,r,n){var i,o=Sr(e,t),l=e.display.view;if(!Hl||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var s=e.display.viewFrom,a=0;a<o;a++)s+=l[a].size;if(s!=t){if(n>0){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,r+=i}for(;ce(e.doc,r)!=r;){if(o==(n<0?0:l.length-1))return null;r+=n*l[o-(n<0?1:0)].size,o+=n}return{index:o,lineN:r}}function mn(e,t,r){var n=e.display,i=n.view;0==i.length||t>=n.viewTo||r<=n.viewFrom?(n.view=wt(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=wt(e,t,n.viewFrom).concat(n.view):n.viewFrom<t&&(n.view=n.view.slice(Sr(e,t))),n.viewFrom=t,n.viewTo<r?n.view=n.view.concat(wt(e,n.viewTo,r)):n.viewTo>r&&(n.view=n.view.slice(0,Sr(e,r)))),n.viewTo=r}function yn(e){for(var t=e.display.view,r=0,n=0;n<t.length;n++){var i=t[n];i.hidden||i.node&&!i.changes||++r}return r}function bn(e,t){e.doc.mode.startState&&e.doc.frontier<e.display.viewTo&&e.state.highlight.set(t,a(wn,e))}function wn(e){var t=e.doc;if(t.frontier<t.first&&(t.frontier=t.first),!(t.frontier>=e.display.viewTo)){var r=+new Date+e.options.workTime,n=$e(t.mode,et(e,t.frontier)),i=[];t.iter(t.frontier,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(t.frontier>=e.display.viewFrom){var l=o.styles,s=o.text.length>e.options.maxHighlightLength,a=Qe(e,o,s?$e(t.mode,n):n,!0);o.styles=a.styles;var u=o.styleClasses,c=a.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var f=!l||l.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),h=0;!f&&h<l.length;++h)f=l[h]!=o.styles[h];f&&i.push(t.frontier),o.stateAfter=s?n:$e(t.mode,n)}else o.text.length<=e.options.maxHighlightLength&&tt(e,o.text,n),o.stateAfter=t.frontier%5==0?$e(t.mode,n):null;if(++t.frontier,+new Date>r)return bn(e,e.options.workDelay),!0}),i.length&&un(e,function(){for(var t=0;t<i.length;t++)pn(e,i[t],"text")})}}function xn(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=Vt(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=Vt(e)+"px",t.scrollbarsClipped=!0)}function Cn(e,r){var n=e.display,i=e.doc;if(r.editorIsHidden)return gn(e),!1;if(!r.force&&r.visible.from>=n.viewFrom&&r.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==yn(e))return!1;Pr(e)&&(gn(e),r.dims=yr(e));var l=i.first+i.size,s=Math.max(r.visible.from-e.options.viewportMargin,i.first),a=Math.min(l,r.visible.to+e.options.viewportMargin);n.viewFrom<s&&s-n.viewFrom<20&&(s=Math.max(i.first,n.viewFrom)),n.viewTo>a&&n.viewTo-a<20&&(a=Math.min(l,n.viewTo)),Hl&&(s=ce(e.doc,s),a=fe(e.doc,a));var u=s!=n.viewFrom||a!=n.viewTo||n.lastWrapHeight!=r.wrapperHeight||n.lastWrapWidth!=r.wrapperWidth;mn(e,s,a),n.viewOffset=pe(T(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var c=yn(e);if(!u&&0==c&&!r.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var f=o();return c>4&&(n.lineDiv.style.display="none"),Tn(e,n.updateLineNumbers,r.dims),c>4&&(n.lineDiv.style.display=""),n.renderedView=n.view,f&&o()!=f&&f.offsetHeight&&f.focus(),t(n.cursorDiv),t(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,u&&(n.lastWrapHeight=r.wrapperHeight,n.lastWrapWidth=r.wrapperWidth,bn(e,400)),n.updateLineNumbers=null,!0}function Sn(e,t){for(var r=t.viewport,n=!0;(n&&e.options.lineWrapping&&t.oldDisplayWidth!=Kt(e)||(r&&null!=r.top&&(r={top:Math.min(e.doc.height+Gt(e.display)-jt(e),r.top)}),t.visible=zr(e.display,e.doc,r),!(t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)))&&Cn(e,t);n=!1){Er(e);var i=Vr(e);Lr(e),Kr(e,i),kn(e,i)}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function Ln(e,t){var r=new os(e,t);if(Cn(e,r)){Er(e),Sn(e,r);var n=Vr(e);Lr(e),Kr(e,n),kn(e,n),r.finish()}}function Tn(e,r,n){function i(t){var r=t.nextSibling;return il&&dl&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var o=e.display,l=e.options.lineNumbers,s=o.lineDiv,a=s.firstChild,u=o.view,c=o.viewFrom,f=0;f<u.length;f++){var d=u[f];if(d.hidden);else if(d.node&&d.node.parentNode==s){for(;a!=d.node;)a=i(a);var p=l&&null!=r&&r<=c&&d.lineNumber;d.changes&&(h(d.changes,"gutter")>-1&&(p=!1),Mt(e,d,c,n)),p&&(t(d.lineNumber),d.lineNumber.appendChild(document.createTextNode(D(e.options,c)))),a=d.node.nextSibling}else{var g=Pt(e,d,c,n);s.insertBefore(g,a)}c+=d.size}for(;a;)a=i(a)}function Mn(e){var t=e.display.gutters.offsetWidth;e.display.sizer.style.marginLeft=t+"px"}function kn(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Vt(e)+"px"}function Nn(e){var r=e.display.gutters,i=e.options.gutters;t(r);for(var o=0;o<i.length;++o){var l=i[o],s=r.appendChild(n("div",null,"CodeMirror-gutter "+l));"CodeMirror-linenumbers"==l&&(e.display.lineGutter=s,s.style.width=(e.display.lineNumWidth||1)+"px")}r.style.display=o?"":"none",Mn(e)}function An(e){var t=h(e.gutters,"CodeMirror-linenumbers");t==-1&&e.lineNumbers?e.gutters=e.gutters.concat(["CodeMirror-linenumbers"]):t>-1&&!e.lineNumbers&&(e.gutters=e.gutters.slice(0),e.gutters.splice(t,1))}function On(e,t){this.ranges=e,this.primIndex=t}function Wn(e,t){this.anchor=e,this.head=t}function Dn(e,t){var r=e[t];e.sort(function(e,t){return P(e.from(),t.from())}),t=h(e,r);for(var n=1;n<e.length;n++){var i=e[n],o=e[n-1];if(P(o.to(),i.from())>=0){var l=z(o.from(),i.from()),s=I(o.to(),i.to()),a=o.empty()?i.from()==i.head:o.from()==o.head;n<=t&&--t,e.splice(--n,2,new Wn(a?s:l,a?l:s))}}return new On(e,t)}function Hn(e,t){return new On([new Wn(e,t||e)],0)}function Pn(e){return e.text?H(e.from.line+e.text.length-1,g(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function En(e,t){if(P(e,t.from)<0)return e;if(P(e,t.to)<=0)return Pn(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=Pn(t).ch-t.to.ch),H(r,n)}function In(e,t){for(var r=[],n=0;n<e.sel.ranges.length;n++){var i=e.sel.ranges[n];r.push(new Wn(En(i.anchor,t),En(i.head,t)))}return Dn(r,e.sel.primIndex)}function zn(e,t,r){return e.line==t.line?H(r.line,e.ch-t.ch+r.ch):H(r.line+(e.line-t.line),e.ch)}function Fn(e,t,r){for(var n=[],i=H(e.first,0),o=i,l=0;l<t.length;l++){var s=t[l],a=zn(s.from,i,o),u=zn(Pn(s),i,o);if(i=s.to,o=u,"around"==r){var c=e.sel.ranges[l],f=P(c.head,c.anchor)<0;n[l]=new Wn(f?u:a,f?a:u)}else n[l]=new Wn(a,a)}return new On(n,e.sel.primIndex)}function Rn(e){e.doc.mode=Ye(e.options,e.doc.modeOption),Bn(e)}function Bn(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.frontier=e.doc.first,bn(e,100),e.state.modeGen++,e.curOp&&dn(e)}function Gn(e,t){return 0==t.from.ch&&0==t.to.ch&&""==g(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function Un(e,t,r,n){function i(e){return r?r[e]:null}function o(e,r,i){ut(e,r,i,n),Lt(e,"change",e,t)}function l(e,t){for(var r=[],o=e;o<t;++o)r.push(new at(u[o],i(o),n));return r}var s=t.from,a=t.to,u=t.text,c=T(e,s.line),f=T(e,a.line),h=g(u),d=i(u.length-1),p=a.line-s.line;if(t.full)e.insert(0,l(0,u.length)),e.remove(u.length,e.size-u.length);else if(Gn(e,t)){var v=l(0,u.length-1);o(f,f.text,d),p&&e.remove(s.line,p),v.length&&e.insert(s.line,v)}else if(c==f)if(1==u.length)o(c,c.text.slice(0,s.ch)+h+c.text.slice(a.ch),d);else{var m=l(1,u.length-1);m.push(new at(h+c.text.slice(a.ch),d,n)),o(c,c.text.slice(0,s.ch)+u[0],i(0)),e.insert(s.line+1,m)}else if(1==u.length)o(c,c.text.slice(0,s.ch)+u[0]+f.text.slice(a.ch),i(0)),e.remove(s.line+1,p);else{o(c,c.text.slice(0,s.ch)+u[0],i(0)),o(f,h+f.text.slice(a.ch),d);var y=l(1,u.length-1);p>1&&e.remove(s.line+1,p-1),e.insert(s.line+1,y)}Lt(e,"change",e,t)}function Vn(e,t,r){function n(e,i,o){if(e.linked)for(var l=0;l<e.linked.length;++l){var s=e.linked[l];if(s.doc!=i){var a=o&&s.sharedHist;r&&!a||(t(s.doc,a),n(s.doc,e,a))}}}n(e,null,!0)}function Kn(e,t){if(t.cm)throw new Error("This document is already in use.");e.doc=t,t.cm=e,xr(e),Rn(e),e.options.lineWrapping||ve(e),e.options.mode=t.modeOption,dn(e)}function jn(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function Xn(e,t){var r={from:E(t.from),to:Pn(t),text:M(e,t.from,t.to)};return Jn(e,r,t.from.line,t.to.line+1),Vn(e,function(e){return Jn(e,r,t.from.line,t.to.line+1)},!0),r}function Yn(e){for(;e.length;){var t=g(e);if(!t.ranges)break;e.pop()}}function _n(e,t){return t?(Yn(e.done),g(e.done)):e.done.length&&!g(e.done).ranges?g(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),g(e.done)):void 0}function $n(e,t,r,n){var i=e.history;i.undone.length=0;var o,l,s=+new Date;if((i.lastOp==n||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&e.cm&&i.lastModTime>s-e.cm.options.historyEventDelay||"*"==t.origin.charAt(0)))&&(o=_n(i,i.lastOp==n)))l=g(o.changes),0==P(t.from,t.to)&&0==P(t.from,l.to)?l.to=Pn(t):o.changes.push(Xn(e,t));else{var a=g(i.done);for(a&&a.ranges||Qn(e.sel,i.done),
3
+ o={changes:[Xn(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,l||Oe(e,"historyAdded")}function qn(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}function Zn(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||qn(e,o,g(i.done),t))?i.done[i.done.length-1]=t:Qn(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&n.clearRedo!==!1&&Yn(i.undone)}function Qn(e,t){var r=g(t);r&&r.ranges&&r.equals(e)||t.push(e)}function Jn(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o})}function ei(e){if(!e)return null;for(var t,r=0;r<e.length;++r)e[r].marker.explicitlyCleared?t||(t=e.slice(0,r)):t&&t.push(e[r]);return t?t.length?t:null:e}function ti(e,t){var r=t["spans_"+e.id];if(!r)return null;for(var n=[],i=0;i<t.text.length;++i)n.push(ei(r[i]));return n}function ri(e,t){var r=ti(e,t),n=q(e,t);if(!r)return n;if(!n)return r;for(var i=0;i<r.length;++i){var o=r[i],l=n[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(r[i]=l)}return r}function ni(e,t,r){for(var n=[],i=0;i<e.length;++i){var o=e[i];if(o.ranges)n.push(r?On.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];n.push({changes:s});for(var a=0;a<l.length;++a){var u=l[a],c=void 0;if(s.push({from:u.from,to:u.to,text:u.text}),t)for(var f in u)(c=f.match(/^spans_(\d+)$/))&&h(t,Number(c[1]))>-1&&(g(s)[f]=u[f],delete u[f])}}}return n}function ii(e,t,r,n){if(e.cm&&e.cm.display.shift||e.extend){var i=t.anchor;if(n){var o=P(r,i)<0;o!=P(n,i)<0?(i=r,r=n):o!=P(r,n)<0&&(r=n)}return new Wn(i,r)}return new Wn(n||r,r)}function oi(e,t,r,n){fi(e,new On([ii(e,e.sel.primary(),t,r)],0),n)}function li(e,t,r){for(var n=[],i=0;i<e.sel.ranges.length;i++)n[i]=ii(e,e.sel.ranges[i],t[i],null);var o=Dn(n,e.sel.primIndex);fi(e,o,r)}function si(e,t,r,n){var i=e.sel.ranges.slice(0);i[t]=r,fi(e,Dn(i,e.sel.primIndex),n)}function ai(e,t,r,n){fi(e,Hn(t,r),n)}function ui(e,t,r){var n={ranges:t.ranges,update:function(t){var r=this;this.ranges=[];for(var n=0;n<t.length;n++)r.ranges[n]=new Wn(R(e,t[n].anchor),R(e,t[n].head))},origin:r&&r.origin};return Oe(e,"beforeSelectionChange",e,n),e.cm&&Oe(e.cm,"beforeSelectionChange",e.cm,n),n.ranges!=t.ranges?Dn(n.ranges,n.ranges.length-1):t}function ci(e,t,r){var n=e.history.done,i=g(n);i&&i.ranges?(n[n.length-1]=t,hi(e,t,r)):fi(e,t,r)}function fi(e,t,r){hi(e,t,r),Zn(e,e.sel,e.cm?e.cm.curOp.id:NaN,r)}function hi(e,t,r){(He(e,"beforeSelectionChange")||e.cm&&He(e.cm,"beforeSelectionChange"))&&(t=ui(e,t,r));var n=r&&r.bias||(P(t.primary().head,e.sel.primary().head)<0?-1:1);di(e,gi(e,t,n,!0)),r&&r.scroll===!1||!e.cm||Qr(e.cm)}function di(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=e.cm.curOp.selectionChanged=!0,De(e.cm)),Lt(e,"cursorActivity",e))}function pi(e){di(e,gi(e,e.sel,null,!1),Ml)}function gi(e,t,r,n){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=t.ranges.length==e.sel.ranges.length&&e.sel.ranges[o],a=mi(e,l.anchor,s&&s.anchor,r,n),u=mi(e,l.head,s&&s.head,r,n);(i||a!=l.anchor||u!=l.head)&&(i||(i=t.ranges.slice(0,o)),i[o]=new Wn(a,u))}return i?Dn(i,t.primIndex):t}function vi(e,t,r,n,i){var o=T(e,t.line);if(o.markedSpans)for(var l=0;l<o.markedSpans.length;++l){var s=o.markedSpans[l],a=s.marker;if((null==s.from||(a.inclusiveLeft?s.from<=t.ch:s.from<t.ch))&&(null==s.to||(a.inclusiveRight?s.to>=t.ch:s.to>t.ch))){if(i&&(Oe(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(r){var u=a.find(n<0?1:-1),c=void 0;if((n<0?a.inclusiveRight:a.inclusiveLeft)&&(u=yi(e,u,-n,u&&u.line==t.line?o:null)),u&&u.line==t.line&&(c=P(u,r))&&(n<0?c<0:c>0))return vi(e,u,t,n,i)}var f=a.find(n<0?-1:1);return(n<0?a.inclusiveLeft:a.inclusiveRight)&&(f=yi(e,f,n,f.line==t.line?o:null)),f?vi(e,f,t,n,i):null}}return t}function mi(e,t,r,n,i){var o=n||1,l=vi(e,t,r,o,i)||!i&&vi(e,t,r,o,!0)||vi(e,t,r,-o,i)||!i&&vi(e,t,r,-o,!0);return l?l:(e.cantEdit=!0,H(e.first,0))}function yi(e,t,r,n){return r<0&&0==t.ch?t.line>e.first?R(e,H(t.line-1)):null:r>0&&t.ch==(n||T(e,t.line)).text.length?t.line<e.first+e.size-1?H(t.line+1,0):null:new H(t.line,t.ch+r)}function bi(e){e.setSelection(H(e.firstLine(),0),H(e.lastLine()),Ml)}function wi(e,t,r){var n={canceled:!1,from:t.from,to:t.to,text:t.text,origin:t.origin,cancel:function(){return n.canceled=!0}};return r&&(n.update=function(t,r,i,o){t&&(n.from=R(e,t)),r&&(n.to=R(e,r)),i&&(n.text=i),void 0!==o&&(n.origin=o)}),Oe(e,"beforeChange",e,n),e.cm&&Oe(e.cm,"beforeChange",e.cm,n),n.canceled?null:{from:n.from,to:n.to,text:n.text,origin:n.origin}}function xi(e,t,r){if(e.cm){if(!e.cm.curOp)return cn(e.cm,xi)(e,t,r);if(e.cm.state.suppressEdits)return}if(!(He(e,"beforeChange")||e.cm&&He(e.cm,"beforeChange"))||(t=wi(e,t,!0))){var n=Dl&&!r&&Q(e,t.from,t.to);if(n)for(var i=n.length-1;i>=0;--i)Ci(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text});else Ci(e,t)}}function Ci(e,t){if(1!=t.text.length||""!=t.text[0]||0!=P(t.from,t.to)){var r=In(e,t);$n(e,t,r,e.cm?e.cm.curOp.id:NaN),Ti(e,t,r,q(e,t));var n=[];Vn(e,function(e,r){r||h(n,e.history)!=-1||(Oi(e.history,t),n.push(e.history)),Ti(e,t,null,q(e,t))})}}function Si(e,t,r){if(!e.cm||!e.cm.state.suppressEdits||r){for(var n,i=e.history,o=e.sel,l="undo"==t?i.done:i.undone,s="undo"==t?i.undone:i.done,a=0;a<l.length&&(n=l[a],r?!n.ranges||n.equals(e.sel):n.ranges);a++);if(a!=l.length){for(i.lastOrigin=i.lastSelOrigin=null;n=l.pop(),n.ranges;){if(Qn(n,s),r&&!n.equals(e.sel))return void fi(e,n,{clearRedo:!1});o=n}var u=[];Qn(o,s),s.push({changes:u,generation:i.generation}),i.generation=n.generation||++i.maxGeneration;for(var c=He(e,"beforeChange")||e.cm&&He(e.cm,"beforeChange"),f=function(r){var i=n.changes[r];if(i.origin=t,c&&!wi(e,i,!1))return l.length=0,{};u.push(Xn(e,i));var o=r?In(e,i):g(l);Ti(e,i,o,ri(e,i)),!r&&e.cm&&e.cm.scrollIntoView({from:i.from,to:Pn(i)});var s=[];Vn(e,function(e,t){t||h(s,e.history)!=-1||(Oi(e.history,i),s.push(e.history)),Ti(e,i,null,ri(e,i))})},d=n.changes.length-1;d>=0;--d){var p=f(d);if(p)return p.v}}}}function Li(e,t){if(0!=t&&(e.first+=t,e.sel=new On(v(e.sel.ranges,function(e){return new Wn(H(e.anchor.line+t,e.anchor.ch),H(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){dn(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;n<r.viewTo;n++)pn(e.cm,n,"gutter")}}function Ti(e,t,r,n){if(e.cm&&!e.cm.curOp)return cn(e.cm,Ti)(e,t,r,n);if(t.to.line<e.first)return void Li(e,t.text.length-1-(t.to.line-t.from.line));if(!(t.from.line>e.lastLine())){if(t.from.line<e.first){var i=t.text.length-1-(e.first-t.from.line);Li(e,i),t={from:H(e.first,0),to:H(t.to.line+i,t.to.ch),text:[g(t.text)],origin:t.origin}}var o=e.lastLine();t.to.line>o&&(t={from:t.from,to:H(o,T(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=M(e,t.from,t.to),r||(r=In(e,t)),e.cm?Mi(e.cm,t,n):Un(e,t,n),hi(e,r,Ml)}}function Mi(e,t,r){var n=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=A(ae(T(n,o.line))),n.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0,!0})),n.sel.contains(t.from,t.to)>-1&&De(e),Un(n,t,r,wr(e)),e.options.lineWrapping||(n.iter(a,o.line+t.text.length,function(e){var t=ge(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0)),n.frontier=Math.min(n.frontier,o.line),bn(e,400);var u=t.text.length-(l.line-o.line)-1;t.full?dn(e):o.line!=l.line||1!=t.text.length||Gn(e.doc,t)?dn(e,o.line,l.line+1,u):pn(e,o.line,"text");var c=He(e,"changes"),f=He(e,"change");if(f||c){var h={from:o,to:l,text:t.text,removed:t.removed,origin:t.origin};f&&Lt(e,"change",e,h),c&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(h)}e.display.selForContextMenu=null}function ki(e,t,r,n,i){if(n||(n=r),P(n,r)<0){var o=n;n=r,r=o}"string"==typeof t&&(t=e.splitLines(t)),xi(e,{from:r,to:n,text:t,origin:i})}function Ni(e,t,r,n){r<e.line?e.line+=n:t<e.line&&(e.line=t,e.ch=0)}function Ai(e,t,r,n){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||(o=e[i]=o.deepCopy(),o.copied=!0);for(var s=0;s<o.ranges.length;s++)Ni(o.ranges[s].anchor,t,r,n),Ni(o.ranges[s].head,t,r,n)}else{for(var a=0;a<o.changes.length;++a){var u=o.changes[a];if(r<u.from.line)u.from=H(u.from.line+n,u.from.ch),u.to=H(u.to.line+n,u.to.ch);else if(t<=u.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function Oi(e,t){var r=t.from.line,n=t.to.line,i=t.text.length-(n-r)-1;Ai(e.done,r,n,i),Ai(e.undone,r,n,i)}function Wi(e,t,r,n){var i=t,o=t;return"number"==typeof t?o=T(e,F(e,t)):i=A(t),null==i?null:(n(o,i)&&e.cm&&pn(e.cm,i,r),o)}function Di(e){var t=this;this.lines=e,this.parent=null;for(var r=0,n=0;n<e.length;++n)e[n].parent=t,r+=e[n].height;this.height=r}function Hi(e){var t=this;this.children=e;for(var r=0,n=0,i=0;i<e.length;++i){var o=e[i];r+=o.chunkSize(),n+=o.height,o.parent=t}this.size=r,this.height=n,this.parent=null}function Pi(e,t,r){var n=this;if(r)for(var i in r)r.hasOwnProperty(i)&&(n[i]=r[i]);this.doc=e,this.node=t}function Ei(e,t,r){pe(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&Zr(e,null,r)}function Ii(e,t,r,n){var i=new Pi(e,r,n),o=e.cm;return o&&i.noHScroll&&(o.display.alignWidgets=!0),Wi(e,t,"widget",function(t){var r=t.widgets||(t.widgets=[]);if(null==i.insertAt?r.push(i):r.splice(Math.min(r.length-1,Math.max(0,i.insertAt)),0,i),i.line=t,o&&!he(e,t)){var n=pe(t)<e.scrollTop;N(t,t.height+Ft(i)),n&&Zr(o,null,i.height),o.curOp.forceUpdate=!0}return!0}),i}function zi(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++ls}function Fi(e,t,r,i,o){if(i&&i.shared)return Bi(e,t,r,i,o);if(e.cm&&!e.cm.curOp)return cn(e.cm,Fi)(e,t,r,i,o);var l=new zi(e,o),s=P(t,r);if(i&&u(i,l,!1),s>0||0==s&&l.clearWhenEmpty!==!1)return l;if(l.replacedWith&&(l.collapsed=!0,l.widgetNode=n("span",[l.replacedWith],"CodeMirror-widget"),l.widgetNode.setAttribute("role","presentation"),i.handleMouseEvents||l.widgetNode.setAttribute("cm-ignore-events","true"),i.insertLeft&&(l.widgetNode.insertLeft=!0)),l.collapsed){if(se(e,t.line,t,r,l)||t.line!=r.line&&se(e,r.line,t,r,l))throw new Error("Inserting collapsed marker partially overlapping an existing one");V()}l.addToHistory&&$n(e,{from:t,to:r,origin:"markText"},e.sel,NaN);var a,c=t.line,f=e.cm;if(e.iter(c,r.line+1,function(e){f&&l.collapsed&&!f.options.lineWrapping&&ae(e)==f.display.maxLine&&(a=!0),l.collapsed&&c!=t.line&&N(e,0),Y(e,new K(l,c==t.line?t.ch:null,c==r.line?r.ch:null)),++c}),l.collapsed&&e.iter(t.line,r.line+1,function(t){he(e,t)&&N(t,0)}),l.clearOnEnter&&zl(l,"beforeCursorEnter",function(){return l.clear()}),l.readOnly&&(U(),(e.history.done.length||e.history.undone.length)&&e.clearHistory()),l.collapsed&&(l.id=++ls,l.atomic=!0),f){if(a&&(f.curOp.updateMaxLine=!0),l.collapsed)dn(f,t.line,r.line+1);else if(l.className||l.title||l.startStyle||l.endStyle||l.css)for(var h=t.line;h<=r.line;h++)pn(f,h,"text");l.atomic&&pi(f.doc),Lt(f,"markerAdded",f,l)}return l}function Ri(e,t){var r=this;this.markers=e,this.primary=t;for(var n=0;n<e.length;++n)e[n].parent=r}function Bi(e,t,r,n,i){n=u(n),n.shared=!1;var o=[Fi(e,t,r,n,i)],l=o[0],s=n.widgetNode;return Vn(e,function(e){s&&(n.widgetNode=s.cloneNode(!0)),o.push(Fi(e,R(e,t),R(e,r),n,i));for(var a=0;a<e.linked.length;++a)if(e.linked[a].isParent)return;l=g(o)}),new Ri(o,l)}function Gi(e){return e.findMarks(H(e.first,0),e.clipPos(H(e.lastLine())),function(e){return e.parent})}function Ui(e,t){for(var r=0;r<t.length;r++){var n=t[r],i=n.find(),o=e.clipPos(i.from),l=e.clipPos(i.to);if(P(o,l)){var s=Fi(e,o,l,n.primary,n.primary.type);n.markers.push(s),s.parent=n}}}function Vi(e){for(var t=function(t){var r=e[t],n=[r.primary.doc];Vn(r.primary.doc,function(e){return n.push(e)});for(var i=0;i<r.markers.length;i++){var o=r.markers[i];h(n,o.doc)==-1&&(o.parent=null,r.markers.splice(i--,1))}},r=0;r<e.length;r++)t(r)}function Ki(e){var t=this;if(Yi(t),!We(t,e)&&!Rt(t.display,e)){Ee(e),rl&&(us=+new Date);var r=Cr(t,e,!0),n=e.dataTransfer.files;if(r&&!t.isReadOnly())if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),l=0,s=function(e,n){if(!t.options.allowDropFileTypes||h(t.options.allowDropFileTypes,e.type)!=-1){var s=new FileReader;s.onload=cn(t,function(){var e=s.result;if(/[\x00-\x08\x0e-\x1f]{2}/.test(e)&&(e=""),o[n]=e,++l==i){r=R(t.doc,r);var a={from:r,to:r,text:t.doc.splitLines(o.join(t.doc.lineSeparator())),origin:"paste"};xi(t.doc,a),ci(t.doc,Hn(r,Pn(a)))}}),s.readAsText(e)}},a=0;a<i;++a)s(n[a],a);else{if(t.state.draggingText&&t.doc.sel.contains(r)>-1)return t.state.draggingText(e),void setTimeout(function(){return t.display.input.focus()},20);try{var u=e.dataTransfer.getData("Text");if(u){var c;if(t.state.draggingText&&!t.state.draggingText.copy&&(c=t.listSelections()),hi(t.doc,Hn(r,r)),c)for(var f=0;f<c.length;++f)ki(t.doc,"",c[f].anchor,c[f].head,"drag");t.replaceSelection(u,"around","paste"),t.display.input.focus()}}catch(e){}}}}function ji(e,t){if(rl&&(!e.state.draggingText||+new Date-us<100))return void Fe(t);if(!We(e,t)&&!Rt(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.effectAllowed="copyMove",t.dataTransfer.setDragImage&&!al)){var r=n("img",null,null,"position: fixed; left: 0; top: 0;");r.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",sl&&(r.width=r.height=1,e.display.wrapper.appendChild(r),r._top=r.offsetTop),t.dataTransfer.setDragImage(r,0,0),sl&&r.parentNode.removeChild(r)}}function Xi(e,t){var i=Cr(e,t);if(i){var o=document.createDocumentFragment();Mr(e,i,o),e.display.dragCursor||(e.display.dragCursor=n("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),r(e.display.dragCursor,o)}}function Yi(e){e.display.dragCursor&&(e.display.lineSpace.removeChild(e.display.dragCursor),e.display.dragCursor=null)}function _i(e){if(document.body.getElementsByClassName)for(var t=document.body.getElementsByClassName("CodeMirror"),r=0;r<t.length;r++){var n=t[r].CodeMirror;n&&e(n)}}function $i(){cs||(qi(),cs=!0)}function qi(){var e;zl(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,_i(Zi)},100))}),zl(window,"blur",function(){return _i(Dr)})}function Zi(e){var t=e.display;t.lastWrapHeight==t.wrapper.clientHeight&&t.lastWrapWidth==t.wrapper.clientWidth||(t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize())}function Qi(e){var t=e.split(/-(?!$)/);e=t[t.length-1];for(var r,n,i,o,l=0;l<t.length-1;l++){var s=t[l];if(/^(cmd|meta|m)$/i.test(s))o=!0;else if(/^a(lt)?$/i.test(s))r=!0;else if(/^(c|ctrl|control)$/i.test(s))n=!0;else{if(!/^s(hift)?$/i.test(s))throw new Error("Unrecognized modifier name: "+s);i=!0}}return r&&(e="Alt-"+e),n&&(e="Ctrl-"+e),o&&(e="Cmd-"+e),i&&(e="Shift-"+e),e}function Ji(e){var t={};for(var r in e)if(e.hasOwnProperty(r)){var n=e[r];if(/^(name|fallthrough|(de|at)tach)$/.test(r))continue;if("..."==n){delete e[r];continue}for(var i=v(r.split(" "),Qi),o=0;o<i.length;o++){var l=void 0,s=void 0;o==i.length-1?(s=i.join(" "),l=n):(s=i.slice(0,o+1).join(" "),l="...");var a=t[s];if(a){if(a!=l)throw new Error("Inconsistent bindings for "+s)}else t[s]=l}delete e[r]}for(var u in t)e[u]=t[u];return e}function eo(e,t,r,n){t=no(t);var i=t.call?t.call(e,n):t[e];if(i===!1)return"nothing";if("..."===i)return"multi";if(null!=i&&r(i))return"handled";if(t.fallthrough){if("[object Array]"!=Object.prototype.toString.call(t.fallthrough))return eo(e,t.fallthrough,r,n);for(var o=0;o<t.fallthrough.length;o++){var l=eo(e,t.fallthrough[o],r,n);if(l)return l}}}function to(e){var t="string"==typeof e?e:fs[e.keyCode];return"Ctrl"==t||"Alt"==t||"Shift"==t||"Mod"==t}function ro(e,t){if(sl&&34==e.keyCode&&e["char"])return!1;var r=fs[e.keyCode],n=r;return null!=n&&!e.altGraphKey&&(e.altKey&&"Alt"!=r&&(n="Alt-"+n),(yl?e.metaKey:e.ctrlKey)&&"Ctrl"!=r&&(n="Ctrl-"+n),(yl?e.ctrlKey:e.metaKey)&&"Cmd"!=r&&(n="Cmd-"+n),!t&&e.shiftKey&&"Shift"!=r&&(n="Shift-"+n),n)}function no(e){return"string"==typeof e?gs[e]:e}function io(e,t){for(var r=e.doc.sel.ranges,n=[],i=0;i<r.length;i++){for(var o=t(r[i]);n.length&&P(o.from,g(n).to)<=0;){var l=n.pop();if(P(l.from,o.from)<0){o.from=l.from;break}}n.push(o)}un(e,function(){for(var t=n.length-1;t>=0;t--)ki(e.doc,"",n[t].from,n[t].to,"+delete");Qr(e)})}function oo(e,t){var r=T(e.doc,t),n=ae(r);n!=r&&(t=A(n));var i=ke(n),o=i?i[0].level%2?xe(n):we(n):0;return H(t,o)}function lo(e,t){for(var r,n=T(e.doc,t);r=le(n);)n=r.find(1,!0).line,t=null;var i=ke(n),o=i?i[0].level%2?we(n):xe(n):n.text.length;return H(null==t?A(n):t,o)}function so(e,t){var r=oo(e,t.line),n=T(e.doc,r.line),i=ke(n);if(!i||0==i[0].level){var o=Math.max(0,n.text.search(/\S/)),l=t.line==r.line&&t.ch<=o&&t.ch;return H(r.line,l?0:o)}return r}function ao(e,t,r){if("string"==typeof t&&(t=ys[t],!t))return!1;e.display.input.ensurePolled();var n=e.display.shift,i=!1;try{e.isReadOnly()&&(e.state.suppressEdits=!0),r&&(e.display.shift=!1),i=t(e)!=Tl}finally{e.display.shift=n,e.state.suppressEdits=!1}return i}function uo(e,t,r){for(var n=0;n<e.state.keyMaps.length;n++){var i=eo(t,e.state.keyMaps[n],r,e);if(i)return i}return e.options.extraKeys&&eo(t,e.options.extraKeys,r,e)||eo(t,e.options.keyMap,r,e)}function co(e,t,r,n){var i=e.state.keySeq;if(i){if(to(t))return"handled";bs.set(50,function(){e.state.keySeq==i&&(e.state.keySeq=null,e.display.input.reset())}),t=i+" "+t}var o=uo(e,t,n);return"multi"==o&&(e.state.keySeq=t),"handled"==o&&Lt(e,"keyHandled",e,t,r),"handled"!=o&&"multi"!=o||(Ee(r),Nr(e)),i&&!o&&/\'$/.test(t)?(Ee(r),!0):!!o}function fo(e,t){var r=ro(t,!0);return!!r&&(t.shiftKey&&!e.state.keySeq?co(e,"Shift-"+r,t,function(t){return ao(e,t,!0)})||co(e,r,t,function(t){if("string"==typeof t?/^go[A-Z]/.test(t):t.motion)return ao(e,t)}):co(e,r,t,function(t){return ao(e,t)}))}function ho(e,t,r){return co(e,"'"+r+"'",t,function(t){return ao(e,t,!0)})}function po(e){var t=this;if(t.curOp.focus=o(),!We(t,e)){rl&&nl<11&&27==e.keyCode&&(e.returnValue=!1);var r=e.keyCode;t.display.shift=16==r||e.shiftKey;var n=fo(t,e);sl&&(ws=n?r:null,!n&&88==r&&!Gl&&(dl?e.metaKey:e.ctrlKey)&&t.replaceSelection("",null,"cut")),18!=r||/\bCodeMirror-crosshair\b/.test(t.display.lineDiv.className)||go(t)}}function go(e){function t(e){18!=e.keyCode&&e.altKey||(wl(r,"CodeMirror-crosshair"),Ae(document,"keyup",t),Ae(document,"mouseover",t))}var r=e.display.lineDiv;l(r,"CodeMirror-crosshair"),zl(document,"keyup",t),zl(document,"mouseover",t)}function vo(e){16==e.keyCode&&(this.doc.sel.shift=!1),We(this,e)}function mo(e){var t=this;if(!(Rt(t.display,e)||We(t,e)||e.ctrlKey&&!e.altKey||dl&&e.metaKey)){var r=e.keyCode,n=e.charCode;if(sl&&r==ws)return ws=null,void Ee(e);if(!sl||e.which&&!(e.which<10)||!fo(t,e)){var i=String.fromCharCode(null==n?r:n);"\b"!=i&&(ho(t,e,i)||t.display.input.onKeyPress(e))}}}function yo(e){var t=this,r=t.display;if(!(We(t,e)||r.activeTouch&&r.input.supportsTouch())){if(r.input.ensurePolled(),r.shift=e.shiftKey,Rt(r,e))return void(il||(r.scroller.draggable=!1,setTimeout(function(){return r.scroller.draggable=!0},100)));if(!So(t,e)){var n=Cr(t,e);switch(window.focus(),Be(e)){case 1:t.state.selectingText?t.state.selectingText(e):n?bo(t,e,n):Re(e)==r.scroller&&Ee(e);break;case 2:il&&(t.state.lastMiddleDown=+new Date),n&&oi(t.doc,n),setTimeout(function(){return r.input.focus()},20),Ee(e);break;case 3:bl?Lo(t,e):Or(t)}}}}function bo(e,t,r){rl?setTimeout(a(Ar,e),0):e.curOp.focus=o();var n,i=+new Date;ms&&ms.time>i-400&&0==P(ms.pos,r)?n="triple":vs&&vs.time>i-400&&0==P(vs.pos,r)?(n="double",ms={time:i,pos:r}):(n="single",vs={time:i,pos:r});var l,s=e.doc.sel,u=dl?t.metaKey:t.ctrlKey;e.options.dragDrop&&Fl&&!e.isReadOnly()&&"single"==n&&(l=s.contains(r))>-1&&(P((l=s.ranges[l]).from(),r)<0||r.xRel>0)&&(P(l.to(),r)>0||r.xRel<0)?wo(e,t,r,u):xo(e,t,r,n,u)}function wo(e,t,r,n){var i=e.display,o=+new Date,l=cn(e,function(s){il&&(i.scroller.draggable=!1),e.state.draggingText=!1,Ae(document,"mouseup",l),Ae(i.scroller,"drop",l),Math.abs(t.clientX-s.clientX)+Math.abs(t.clientY-s.clientY)<10&&(Ee(s),!n&&+new Date-200<o&&oi(e.doc,r),il||rl&&9==nl?setTimeout(function(){document.body.focus(),i.input.focus()},20):i.input.focus())});il&&(i.scroller.draggable=!0),e.state.draggingText=l,l.copy=dl?t.altKey:t.ctrlKey,i.scroller.dragDrop&&i.scroller.dragDrop(),zl(document,"mouseup",l),zl(i.scroller,"drop",l)}function xo(e,t,r,n,i){function l(t){if(0!=P(b,t))if(b=t,"rect"==n){for(var i=[],o=e.options.tabSize,l=c(T(f,r.line).text,r.ch,o),s=c(T(f,t.line).text,t.ch,o),a=Math.min(l,s),u=Math.max(l,s),v=Math.min(r.line,t.line),m=Math.min(e.lastLine(),Math.max(r.line,t.line));v<=m;v++){var y=T(f,v).text,w=d(y,a,o);a==u?i.push(new Wn(H(v,w),H(v,w))):y.length>w&&i.push(new Wn(H(v,w),H(v,d(y,u,o))))}i.length||i.push(new Wn(r,r)),fi(f,Dn(g.ranges.slice(0,p).concat(i),p),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var x=h,C=x.anchor,S=t;if("single"!=n){var L;L="double"==n?e.findWordAt(t):new Wn(H(t.line,0),R(f,H(t.line+1,0))),P(L.anchor,C)>0?(S=L.head,C=z(x.from(),L.anchor)):(S=L.anchor,C=I(x.to(),L.head))}var M=g.ranges.slice(0);M[p]=new Wn(R(f,C),S),fi(f,Dn(M,p),kl)}}function s(t){var r=++x,i=Cr(e,t,!0,"rect"==n);if(i)if(0!=P(i,b)){e.curOp.focus=o(),l(i);var a=zr(u,f);(i.line>=a.to||i.line<a.from)&&setTimeout(cn(e,function(){x==r&&s(t)}),150)}else{var c=t.clientY<w.top?-20:t.clientY>w.bottom?20:0;c&&setTimeout(cn(e,function(){x==r&&(u.scroller.scrollTop+=c,s(t))}),50)}}function a(t){e.state.selectingText=!1,x=1/0,Ee(t),u.input.focus(),Ae(document,"mousemove",C),Ae(document,"mouseup",S),f.history.lastSelOrigin=null}var u=e.display,f=e.doc;Ee(t);var h,p,g=f.sel,v=g.ranges;if(i&&!t.shiftKey?(p=f.sel.contains(r),h=p>-1?v[p]:new Wn(r,r)):(h=f.sel.primary(),p=f.sel.primIndex),pl?t.shiftKey&&t.metaKey:t.altKey)n="rect",i||(h=new Wn(r,r)),r=Cr(e,t,!0,!0),p=-1;else if("double"==n){var m=e.findWordAt(r);h=e.display.shift||f.extend?ii(f,h,m.anchor,m.head):m}else if("triple"==n){var y=new Wn(H(r.line,0),R(f,H(r.line+1,0)));h=e.display.shift||f.extend?ii(f,h,y.anchor,y.head):y}else h=ii(f,h,r);i?p==-1?(p=v.length,fi(f,Dn(v.concat([h]),p),{scroll:!1,origin:"*mouse"})):v.length>1&&v[p].empty()&&"single"==n&&!t.shiftKey?(fi(f,Dn(v.slice(0,p).concat(v.slice(p+1)),0),{scroll:!1,origin:"*mouse"}),g=f.sel):si(f,p,h,kl):(p=0,fi(f,new On([h],0),kl),g=f.sel);var b=r,w=u.wrapper.getBoundingClientRect(),x=0,C=cn(e,function(e){Be(e)?s(e):a(e)}),S=cn(e,a);e.state.selectingText=S,zl(document,"mousemove",C),zl(document,"mouseup",S)}function Co(e,t,r,n){var i,o;try{i=t.clientX,o=t.clientY}catch(t){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;n&&Ee(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!He(e,r))return ze(t);o-=s.top-l.viewOffset;for(var a=0;a<e.options.gutters.length;++a){var u=l.gutters.childNodes[a];if(u&&u.getBoundingClientRect().right>=i){var c=O(e.doc,o),f=e.options.gutters[a];return Oe(e,r,e,c,f,t),ze(t)}}}function So(e,t){return Co(e,t,"gutterClick",!0)}function Lo(e,t){Rt(e.display,t)||To(e,t)||We(e,t,"contextmenu")||e.display.input.onContextMenu(t)}function To(e,t){return!!He(e,"gutterContextMenu")&&Co(e,t,"gutterContextMenu",!1)}function Mo(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),or(e)}function ko(e){function t(t,n,i,o){e.defaults[t]=n,i&&(r[t]=o?function(e,t,r){r!=xs&&i(e,t,r)}:i)}var r=e.optionHandlers;e.defineOption=t,e.Init=xs,t("value","",function(e,t){return e.setValue(t)},!0),t("mode",null,function(e,t){e.doc.modeOption=t,Rn(e)},!0),t("indentUnit",2,Rn,!0),t("indentWithTabs",!1),t("smartIndent",!0),t("tabSize",4,function(e){Bn(e),or(e),dn(e)},!0),t("lineSeparator",null,function(e,t){if(e.doc.lineSep=t,t){var r=[],n=e.doc.first;e.doc.iter(function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(o==-1)break;i=o+t.length,r.push(H(n,o))}n++});for(var i=r.length-1;i>=0;i--)ki(e.doc,t,r[i],H(r[i].line,r[i].ch+t.length))}}),t("specialChars",/[\u0000-\u001f\u007f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g,function(e,t,r){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),r!=xs&&e.refresh()}),t("specialCharPlaceholder",dt,function(e){return e.refresh()},!0),t("electricChars",!0),t("inputStyle",hl?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),t("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),t("rtlMoveVisually",!gl),t("wholeLineUpdateBefore",!0),t("theme","default",function(e){Mo(e),No(e)},!0),t("keyMap","default",function(e,t,r){var n=no(t),i=r!=xs&&no(r);i&&i.detach&&i.detach(e,n),n.attach&&n.attach(e,i||null)}),t("extraKeys",null),t("lineWrapping",!1,Oo,!0),t("gutters",[],function(e){An(e.options),No(e)},!0),t("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?br(e.display)+"px":"0",e.refresh()},!0),t("coverGutterNextToScrollbar",!1,function(e){return Kr(e)},!0),t("scrollbarStyle","native",function(e){Xr(e),Kr(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),t("lineNumbers",!1,function(e){An(e.options),No(e)},!0),t("firstLineNumber",1,No,!0),t("lineNumberFormatter",function(e){return e},No,!0),t("showCursorWhenSelecting",!1,Lr,!0),t("resetSelectionOnContextMenu",!0),t("lineWiseCopyCut",!0),t("readOnly",!1,function(e,t){"nocursor"==t?(Dr(e),e.display.input.blur(),e.display.disabled=!0):e.display.disabled=!1,e.display.input.readOnlyChanged(t)}),t("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),t("dragDrop",!0,Ao),t("allowDropFileTypes",null),t("cursorBlinkRate",530),t("cursorScrollMargin",0),t("cursorHeight",1,Lr,!0),t("singleCursorHeightPerLine",!0,Lr,!0),t("workTime",100),t("workDelay",100),t("flattenSpans",!0,Bn,!0),t("addModeClass",!1,Bn,!0),t("pollInterval",100),t("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),t("historyEventDelay",1250),t("viewportMargin",10,function(e){return e.refresh()},!0),t("maxHighlightLength",1e4,Bn,!0),t("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),t("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),t("autofocus",null)}function No(e){Nn(e),dn(e),Hr(e)}function Ao(e,t,r){var n=r&&r!=xs;if(!t!=!n){var i=e.display.dragFunctions,o=t?zl:Ae;o(e.display.scroller,"dragstart",i.start),o(e.display.scroller,"dragenter",i.enter),o(e.display.scroller,"dragover",i.over),o(e.display.scroller,"dragleave",i.leave),o(e.display.scroller,"drop",i.drop)}}function Oo(e){e.options.lineWrapping?(l(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(wl(e.display.wrapper,"CodeMirror-wrap"),ve(e)),xr(e),dn(e),or(e),setTimeout(function(){return Kr(e)},100)}function Wo(e,t){var r=this;if(!(this instanceof Wo))return new Wo(e,t);this.options=t=t?u(t):{},u(Cs,t,!1),An(t);var n=t.value;"string"==typeof n&&(n=new as(n,t.mode,null,t.lineSeparator)),this.doc=n;var i=new Wo.inputStyles[t.inputStyle](this),o=this.display=new L(e,n,i);o.wrapper.CodeMirror=this,Nn(this),Mo(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Xr(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,selectingText:!1,draggingText:!1,highlight:new f,keySeq:null,specialChars:null},t.autofocus&&!hl&&o.input.focus(),rl&&nl<11&&setTimeout(function(){return r.display.input.reset(!0)},20),Do(this),$i(),en(this),this.curOp.forceUpdate=!0,Kn(this,n),t.autofocus&&!hl||this.hasFocus()?setTimeout(a(Wr,this),20):Dr(this);for(var l in Ss)Ss.hasOwnProperty(l)&&Ss[l](r,t[l],xs);Pr(this),t.finishInit&&t.finishInit(this);for(var s=0;s<Ls.length;++s)Ls[s](r);tn(this),il&&t.lineWrapping&&"optimizelegibility"==getComputedStyle(o.lineDiv).textRendering&&(o.lineDiv.style.textRendering="auto")}function Do(e){function t(){i.activeTouch&&(o=setTimeout(function(){return i.activeTouch=null},1e3),l=i.activeTouch,l.end=+new Date)}function r(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}function n(e,t){if(null==t.left)return!0;var r=t.left-e.left,n=t.top-e.top;return r*r+n*n>400}var i=e.display;zl(i.scroller,"mousedown",cn(e,yo)),rl&&nl<11?zl(i.scroller,"dblclick",cn(e,function(t){if(!We(e,t)){var r=Cr(e,t);if(r&&!So(e,t)&&!Rt(e.display,t)){Ee(t);var n=e.findWordAt(r);oi(e.doc,n.anchor,n.head)}}})):zl(i.scroller,"dblclick",function(t){return We(e,t)||Ee(t)}),bl||zl(i.scroller,"contextmenu",function(t){return Lo(e,t)});var o,l={end:0};zl(i.scroller,"touchstart",function(t){if(!We(e,t)&&!r(t)){i.input.ensurePolled(),clearTimeout(o);var n=+new Date;i.activeTouch={start:n,moved:!1,prev:n-l.end<=300?l:null},1==t.touches.length&&(i.activeTouch.left=t.touches[0].pageX,i.activeTouch.top=t.touches[0].pageY)}}),zl(i.scroller,"touchmove",function(){i.activeTouch&&(i.activeTouch.moved=!0)}),zl(i.scroller,"touchend",function(r){var o=i.activeTouch;if(o&&!Rt(i,r)&&null!=o.left&&!o.moved&&new Date-o.start<300){var l,s=e.coordsChar(i.activeTouch,"page");l=!o.prev||n(o,o.prev)?new Wn(s,s):!o.prev.prev||n(o,o.prev.prev)?e.findWordAt(s):new Wn(H(s.line,0),R(e.doc,H(s.line+1,0))),e.setSelection(l.anchor,l.head),e.focus(),Ee(r)}t()}),zl(i.scroller,"touchcancel",t),zl(i.scroller,"scroll",function(){i.scroller.clientHeight&&(Fr(e,i.scroller.scrollTop),Rr(e,i.scroller.scrollLeft,!0),Oe(e,"scroll",e))}),zl(i.scroller,"mousewheel",function(t){return Ur(e,t)}),zl(i.scroller,"DOMMouseScroll",function(t){return Ur(e,t)}),zl(i.wrapper,"scroll",function(){return i.wrapper.scrollTop=i.wrapper.scrollLeft=0}),i.dragFunctions={enter:function(t){We(e,t)||Fe(t)},over:function(t){We(e,t)||(Xi(e,t),Fe(t))},start:function(t){return ji(e,t)},drop:cn(e,Ki),leave:function(t){We(e,t)||Yi(e)}};var s=i.input.getField();zl(s,"keyup",function(t){return vo.call(e,t)}),zl(s,"keydown",cn(e,po)),zl(s,"keypress",cn(e,mo)),zl(s,"focus",function(t){return Wr(e,t)}),zl(s,"blur",function(t){return Dr(e,t)})}function Ho(e,t,r,n){var i,o=e.doc;null==r&&(r="add"),"smart"==r&&(o.mode.indent?i=et(e,t):r="prev");var l=e.options.tabSize,s=T(o,t),a=c(s.text,null,l);s.stateAfter&&(s.stateAfter=null);var u,f=s.text.match(/^\s*/)[0];if(n||/\S/.test(s.text)){if("smart"==r&&(u=o.mode.indent(i,s.text.slice(f.length),s.text),u==Tl||u>150)){if(!n)return;r="prev"}}else u=0,r="not";"prev"==r?u=t>o.first?c(T(o,t-1).text,null,l):0:"add"==r?u=a+e.options.indentUnit:"subtract"==r?u=a-e.options.indentUnit:"number"==typeof r&&(u=a+r),u=Math.max(0,u);var h="",d=0;if(e.options.indentWithTabs)for(var g=Math.floor(u/l);g;--g)d+=l,h+="\t";if(d<u&&(h+=p(u-d)),h!=f)return ki(o,h,H(t,0),H(t,f.length),"+input"),s.stateAfter=null,!0;for(var v=0;v<o.sel.ranges.length;v++){var m=o.sel.ranges[v];if(m.head.line==t&&m.head.ch<f.length){var y=H(t,f.length);si(o,v,new Wn(y,y));break}}}function Po(e){Ts=e}function Eo(e,t,r,n,i){var o=e.doc;e.display.shift=!1,n||(n=o.sel);var l=e.state.pasteIncoming||"paste"==i,s=Rl(t),a=null;if(l&&n.ranges.length>1)if(Ts&&Ts.text.join("\n")==t){if(n.ranges.length%Ts.text.length==0){a=[];for(var u=0;u<Ts.text.length;u++)a.push(o.splitLines(Ts.text[u]))}}else s.length==n.ranges.length&&(a=v(s,function(e){return[e]}));for(var c,f=n.ranges.length-1;f>=0;f--){var h=n.ranges[f],d=h.from(),p=h.to();h.empty()&&(r&&r>0?d=H(d.line,d.ch-r):e.state.overwrite&&!l?p=H(p.line,Math.min(T(o,p.line).text.length,p.ch+g(s).length)):Ts&&Ts.lineWise&&Ts.text.join("\n")==t&&(d=p=H(d.line,0))),c=e.curOp.updateInput;var m={from:d,to:p,
4
+ text:a?a[f%a.length]:s,origin:i||(l?"paste":e.state.cutIncoming?"cut":"+input")};xi(e.doc,m),Lt(e,"inputRead",e,m)}t&&!l&&zo(e,t),Qr(e),e.curOp.updateInput=c,e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=!1}function Io(e,t){var r=e.clipboardData&&e.clipboardData.getData("Text");if(r)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||un(t,function(){return Eo(t,r,0,null,"paste")}),!0}function zo(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var r=e.doc.sel,n=r.ranges.length-1;n>=0;n--){var i=r.ranges[n];if(!(i.head.ch>100||n&&r.ranges[n-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s<o.electricChars.length;s++)if(t.indexOf(o.electricChars.charAt(s))>-1){l=Ho(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(T(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=Ho(e,i.head.line,"smart"));l&&Lt(e,"electricInput",e,i.head.line)}}}function Fo(e){for(var t=[],r=[],n=0;n<e.doc.sel.ranges.length;n++){var i=e.doc.sel.ranges[n].head.line,o={anchor:H(i,0),head:H(i+1,0)};r.push(o),t.push(e.getRange(o.anchor,o.head))}return{text:t,ranges:r}}function Ro(e,t){e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),e.setAttribute("spellcheck",!!t)}function Bo(){var e=n("textarea",null,null,"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"),t=n("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return il?e.style.width="1000px":e.setAttribute("wrap","off"),fl&&(e.style.border="1px solid black"),Ro(e),t}function Go(e){var t=e.optionHandlers,r=e.helpers={};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,r){var n=this.options,i=n[e];n[e]==r&&"mode"!=e||(n[e]=r,t.hasOwnProperty(e)&&cn(this,t[e])(this,r,i),Oe(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](no(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,r=0;r<t.length;++r)if(t[r]==e||t[r].name==e)return t.splice(r,1),!0},addOverlay:fn(function(t,r){var n=t.token?t:e.getMode(this.options,t);if(n.startState)throw new Error("Overlays may not be stateful.");m(this.state.overlays,{mode:n,modeSpec:t,opaque:r&&r.opaque,priority:r&&r.priority||0},function(e){return e.priority}),this.state.modeGen++,dn(this)}),removeOverlay:fn(function(e){for(var t=this,r=this.state.overlays,n=0;n<r.length;++n){var i=r[n].modeSpec;if(i==e||"string"==typeof e&&i.name==e)return r.splice(n,1),t.state.modeGen++,void dn(t)}}),indentLine:fn(function(e,t,r){"string"!=typeof t&&"number"!=typeof t&&(t=null==t?this.options.smartIndent?"smart":"prev":t?"add":"subtract"),W(this.doc,e)&&Ho(this,e,t,r)}),indentSelection:fn(function(e){for(var t=this,r=this.doc.sel.ranges,n=-1,i=0;i<r.length;i++){var o=r[i];if(o.empty())o.head.line>n&&(Ho(t,o.head.line,e,!0),n=o.head.line,i==t.doc.sel.primIndex&&Qr(t));else{var l=o.from(),s=o.to(),a=Math.max(n,l.line);n=Math.min(t.lastLine(),s.line-(s.ch?0:1))+1;for(var u=a;u<n;++u)Ho(t,u,e);var c=t.doc.sel.ranges;0==l.ch&&r.length==c.length&&c[i].from().ch>0&&si(t.doc,i,new Wn(l,c[i].to()),Ml)}}}),getTokenAt:function(e,t){return it(this,e,t)},getLineTokens:function(e,t){return it(this,H(e),t,!0)},getTokenTypeAt:function(e){e=R(this.doc,e);var t,r=Je(this,T(this.doc,e.line)),n=0,i=(r.length-1)/2,o=e.ch;if(0==o)t=r[2];else for(;;){var l=n+i>>1;if((l?r[2*l-1]:0)>=o)i=l;else{if(!(r[2*l+1]<o)){t=r[2*l+2];break}n=l+1}}var s=t?t.indexOf("overlay "):-1;return s<0?t:0==s?null:t.slice(0,s-1)},getModeAt:function(t){var r=this.doc.mode;return r.innerMode?e.innerMode(r,this.getTokenAt(t).state).mode:r},getHelper:function(e,t){return this.getHelpers(e,t)[0]},getHelpers:function(e,t){var n=this,i=[];if(!r.hasOwnProperty(t))return i;var o=r[t],l=this.getModeAt(e);if("string"==typeof l[t])o[l[t]]&&i.push(o[l[t]]);else if(l[t])for(var s=0;s<l[t].length;s++){var a=o[l[t][s]];a&&i.push(a)}else l.helperType&&o[l.helperType]?i.push(o[l.helperType]):o[l.name]&&i.push(o[l.name]);for(var u=0;u<o._global.length;u++){var c=o._global[u];c.pred(l,n)&&h(i,c.val)==-1&&i.push(c.val)}return i},getStateAfter:function(e,t){var r=this.doc;return e=F(r,null==e?r.first+r.size-1:e),et(this,e+1,t)},cursorCoords:function(e,t){var r,n=this.doc.sel.primary();return r=null==e?n.head:"object"==typeof e?R(this.doc,e):e?n.from():n.to(),fr(this,r,t||"page")},charCoords:function(e,t){return cr(this,R(this.doc,e),t||"page")},coordsChar:function(e,t){return e=ur(this,e,t||"page"),pr(this,e.left,e.top)},lineAtHeight:function(e,t){return e=ur(this,{top:e,left:0},t||"page").top,O(this.doc,e+this.display.viewOffset)},heightAtLine:function(e,t,r){var n,i=!1;if("number"==typeof e){var o=this.doc.first+this.doc.size-1;e<this.doc.first?e=this.doc.first:e>o&&(e=o,i=!0),n=T(this.doc,e)}else n=e;return ar(this,n,{top:0,left:0},t||"page",r).top+(i?this.doc.height-pe(n):0)},defaultTextHeight:function(){return vr(this.display)},defaultCharWidth:function(){return mr(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,r,n,i){var o=this.display;e=fr(this,R(this.doc,e));var l=e.bottom,s=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),o.sizer.appendChild(t),"over"==n)l=e.top;else if("above"==n||"near"==n){var a=Math.max(o.wrapper.clientHeight,this.doc.height),u=Math.max(o.sizer.clientWidth,o.lineSpace.clientWidth);("above"==n||e.bottom+t.offsetHeight>a)&&e.top>t.offsetHeight?l=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=a&&(l=e.bottom),s+t.offsetWidth>u&&(s=u-t.offsetWidth)}t.style.top=l+"px",t.style.left=t.style.right="","right"==i?(s=o.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?s=0:"middle"==i&&(s=(o.sizer.clientWidth-t.offsetWidth)/2),t.style.left=s+"px"),r&&$r(this,s,l,s+t.offsetWidth,l+t.offsetHeight)},triggerOnKeyDown:fn(po),triggerOnKeyPress:fn(mo),triggerOnKeyUp:vo,execCommand:function(e){if(ys.hasOwnProperty(e))return ys[e].call(null,this)},triggerElectric:fn(function(e){zo(this,e)}),findPosH:function(e,t,r,n){var i=this,o=1;t<0&&(o=-1,t=-t);for(var l=R(this.doc,e),s=0;s<t&&(l=Uo(i.doc,l,o,r,n),!l.hitSide);++s);return l},moveH:fn(function(e,t){var r=this;this.extendSelectionsBy(function(n){return r.display.shift||r.doc.extend||n.empty()?Uo(r.doc,n.head,e,t,r.options.rtlMoveVisually):e<0?n.from():n.to()},Nl)}),deleteH:fn(function(e,t){var r=this.doc.sel,n=this.doc;r.somethingSelected()?n.replaceSelection("",null,"+delete"):io(this,function(r){var i=Uo(n,r.head,e,t,!1);return e<0?{from:i,to:r.head}:{from:r.head,to:i}})}),findPosV:function(e,t,r,n){var i=this,o=1,l=n;t<0&&(o=-1,t=-t);for(var s=R(this.doc,e),a=0;a<t;++a){var u=fr(i,s,"div");if(null==l?l=u.left:u.left=l,s=Vo(i,u,o,r),s.hitSide)break}return s},moveV:fn(function(e,t){var r=this,n=this.doc,i=[],o=!this.display.shift&&!n.extend&&n.sel.somethingSelected();if(n.extendSelectionsBy(function(l){if(o)return e<0?l.from():l.to();var s=fr(r,l.head,"div");null!=l.goalColumn&&(s.left=l.goalColumn),i.push(s.left);var a=Vo(r,s,e,t);return"page"==t&&l==n.sel.primary()&&Zr(r,null,cr(r,a,"div").top-s.top),a},Nl),i.length)for(var l=0;l<n.sel.ranges.length;l++)n.sel.ranges[l].goalColumn=i[l]}),findWordAt:function(e){var t=this.doc,r=T(t,e.line).text,n=e.ch,i=e.ch;if(r){var o=this.getHelper(e,"wordChars");(e.xRel<0||i==r.length)&&n?--n:++i;for(var l=r.charAt(n),s=x(l,o)?function(e){return x(e,o)}:/\s/.test(l)?function(e){return/\s/.test(e)}:function(e){return!/\s/.test(e)&&!x(e)};n>0&&s(r.charAt(n-1));)--n;for(;i<r.length&&s(r.charAt(i));)++i}return new Wn(H(e.line,n),H(e.line,i))},toggleOverwrite:function(e){null!=e&&e==this.state.overwrite||((this.state.overwrite=!this.state.overwrite)?l(this.display.cursorDiv,"CodeMirror-overwrite"):wl(this.display.cursorDiv,"CodeMirror-overwrite"),Oe(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==o()},isReadOnly:function(){return!(!this.options.readOnly&&!this.doc.cantEdit)},scrollTo:fn(function(e,t){null==e&&null==t||Jr(this),null!=e&&(this.curOp.scrollLeft=e),null!=t&&(this.curOp.scrollTop=t)}),getScrollInfo:function(){var e=this.display.scroller;return{left:e.scrollLeft,top:e.scrollTop,height:e.scrollHeight-Vt(this)-this.display.barHeight,width:e.scrollWidth-Vt(this)-this.display.barWidth,clientHeight:jt(this),clientWidth:Kt(this)}},scrollIntoView:fn(function(e,t){if(null==e?(e={from:this.doc.sel.primary().head,to:null},null==t&&(t=this.options.cursorScrollMargin)):"number"==typeof e?e={from:H(e,0),to:null}:null==e.from&&(e={from:e,to:null}),e.to||(e.to=e.from),e.margin=t||0,null!=e.from.line)Jr(this),this.curOp.scrollToPos=e;else{var r=qr(this,Math.min(e.from.left,e.to.left),Math.min(e.from.top,e.to.top)-e.margin,Math.max(e.from.right,e.to.right),Math.max(e.from.bottom,e.to.bottom)+e.margin);this.scrollTo(r.scrollLeft,r.scrollTop)}}),setSize:fn(function(e,t){var r=this,n=function(e){return"number"==typeof e||/^\d+$/.test(String(e))?e+"px":e};null!=e&&(this.display.wrapper.style.width=n(e)),null!=t&&(this.display.wrapper.style.height=n(t)),this.options.lineWrapping&&ir(this);var i=this.display.viewFrom;this.doc.iter(i,this.display.viewTo,function(e){if(e.widgets)for(var t=0;t<e.widgets.length;t++)if(e.widgets[t].noHScroll){pn(r,i,"widget");break}++i}),this.curOp.forceUpdate=!0,Oe(this,"refresh",this)}),operation:function(e){return un(this,e)},refresh:fn(function(){var e=this.display.cachedTextHeight;dn(this),this.curOp.forceUpdate=!0,or(this),this.scrollTo(this.doc.scrollLeft,this.doc.scrollTop),Mn(this),(null==e||Math.abs(e-vr(this.display))>.5)&&xr(this),Oe(this,"refresh",this)}),swapDoc:fn(function(e){var t=this.doc;return t.cm=null,Kn(this,e),or(this),this.display.input.reset(),this.scrollTo(e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,Lt(this,"swapDoc",this,t),t}),getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Pe(e),e.registerHelper=function(t,n,i){r.hasOwnProperty(t)||(r[t]=e[t]={_global:[]}),r[t][n]=i},e.registerGlobalHelper=function(t,n,i,o){e.registerHelper(t,n,o),r[t]._global.push({pred:i,val:o})}}function Uo(e,t,r,n,i){function o(){var t=s+r;return!(t<e.first||t>=e.first+e.size)&&(s=t,c=T(e,t))}function l(e){var t=(i?Te:Me)(c,a,r,!0);if(null==t){if(e||!o())return!1;a=i?(r<0?xe:we)(c):r<0?c.text.length:0}else a=t;return!0}var s=t.line,a=t.ch,u=r,c=T(e,s);if("char"==n)l();else if("column"==n)l(!0);else if("word"==n||"group"==n)for(var f=null,h="group"==n,d=e.cm&&e.cm.getHelper(t,"wordChars"),p=!0;!(r<0)||l(!p);p=!1){var g=c.text.charAt(a)||"\n",v=x(g,d)?"w":h&&"\n"==g?"n":!h||/\s/.test(g)?null:"p";if(!h||p||v||(v="s"),f&&f!=v){r<0&&(r=1,l());break}if(v&&(f=v),r>0&&!l(!p))break}var m=mi(e,H(s,a),t,u,!0);return P(t,m)||(m.hitSide=!0),m}function Vo(e,t,r,n){var i,o=e.doc,l=t.left;if("page"==n){var s=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),a=Math.max(s-.5*vr(e.display),3);i=(r>0?t.bottom:t.top)+r*a}else"line"==n&&(i=r>0?t.bottom+3:t.top-3);for(var u;u=pr(e,l,i),u.outside;){if(r<0?i<=0:i>=o.height){u.hitSide=!0;break}i+=5*r}return u}function Ko(e,t){var r=qt(e,t.line);if(!r||r.hidden)return null;var n=T(e.doc,t.line),i=Yt(r,n,t.line),o=ke(n),l="left";if(o){var s=Se(o,t.ch);l=s%2?"right":"left"}var a=Jt(i.map,t.ch,l);return a.offset="right"==a.collapse?a.end:a.start,a}function jo(e,t){return t&&(e.bad=!0),e}function Xo(e,t,r,n,i){function o(e){return function(t){return t.id==e}}function l(t){if(1==t.nodeType){var r=t.getAttribute("cm-text");if(null!=r)return void(s+=""==r?t.textContent.replace(/\u200b/g,""):r);var c,f=t.getAttribute("cm-marker");if(f){var h=e.findMarks(H(n,0),H(i+1,0),o(+f));return void(h.length&&(c=h[0].find())&&(s+=M(e.doc,c.from,c.to).join(u)))}if("false"==t.getAttribute("contenteditable"))return;for(var d=0;d<t.childNodes.length;d++)l(t.childNodes[d]);/^(pre|div|p)$/i.test(t.nodeName)&&(a=!0)}else if(3==t.nodeType){var p=t.nodeValue;if(!p)return;a&&(s+=u,a=!1),s+=p}}for(var s="",a=!1,u=e.doc.lineSeparator();l(t),t!=r;)t=t.nextSibling;return s}function Yo(e,t,r){var n;if(t==e.display.lineDiv){if(n=e.display.lineDiv.childNodes[r],!n)return jo(e.clipPos(H(e.display.viewTo-1)),!0);t=null,r=0}else for(n=t;;n=n.parentNode){if(!n||n==e.display.lineDiv)return null;if(n.parentNode&&n.parentNode==e.display.lineDiv)break}for(var i=0;i<e.display.view.length;i++){var o=e.display.view[i];if(o.node==n)return _o(o,t,r)}}function _o(e,t,r){function n(t,r,n){for(var i=-1;i<(f?f.length:0);i++)for(var o=i<0?c.map:f[i],l=0;l<o.length;l+=3){var s=o[l+2];if(s==t||s==r){var a=A(i<0?e.line:e.rest[i]),u=o[l]+n;return(n<0||s!=t)&&(u=o[l+(n?1:0)]),H(a,u)}}}var o=e.text.firstChild,l=!1;if(!t||!i(o,t))return jo(H(A(e.line),0),!0);if(t==o&&(l=!0,t=o.childNodes[r],r=0,!t)){var s=e.rest?g(e.rest):e.line;return jo(H(A(s),s.text.length),l)}var a=3==t.nodeType?t:null,u=t;for(a||1!=t.childNodes.length||3!=t.firstChild.nodeType||(a=t.firstChild,r&&(r=a.nodeValue.length));u.parentNode!=o;)u=u.parentNode;var c=e.measure,f=c.maps,h=n(a,u,r);if(h)return jo(h,l);for(var d=u.nextSibling,p=a?a.nodeValue.length-r:0;d;d=d.nextSibling){if(h=n(d,d.firstChild,0))return jo(H(h.line,h.ch-p),l);p+=d.textContent.length}for(var v=u.previousSibling,m=r;v;v=v.previousSibling){if(h=n(v,v.firstChild,-1))return jo(H(h.line,h.ch+m),l);m+=v.textContent.length}}function $o(e,t){function r(){e.value=c.getValue()}if(t=t?u(t):{},t.value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var n=o();t.autofocus=n==e||null!=e.getAttribute("autofocus")&&n==document.body}var i;if(e.form&&(zl(e.form,"submit",r),!t.leaveSubmitMethodAlone)){var l=e.form;i=l.submit;try{var s=l.submit=function(){r(),l.submit=i,l.submit(),l.submit=s}}catch(a){}}t.finishInit=function(t){t.save=r,t.getTextArea=function(){return e},t.toTextArea=function(){t.toTextArea=isNaN,r(),e.parentNode.removeChild(t.getWrapperElement()),e.style.display="",e.form&&(Ae(e.form,"submit",r),"function"==typeof e.form.submit&&(e.form.submit=i))}},e.style.display="none";var c=Wo(function(t){return e.parentNode.insertBefore(t,e.nextSibling)},t);return c}function qo(e){e.off=Ae,e.on=zl,e.wheelEventPixels=Gr,e.Doc=as,e.splitLines=Rl,e.countColumn=c,e.findColumn=d,e.isWordChar=w,e.Pass=Tl,e.signal=Oe,e.Line=at,e.changeEnd=Pn,e.scrollbarModel=ns,e.Pos=H,e.cmpPos=P,e.modes=Vl,e.mimeModes=Kl,e.resolveMode=Xe,e.getMode=Ye,e.modeExtensions=jl,e.extendMode=_e,e.copyState=$e,e.startState=Ze,e.innerMode=qe,e.commands=ys,e.keyMap=gs,e.keyName=ro,e.isModifierKey=to,e.lookupKey=eo,e.normalizeKeyMap=Ji,e.StringStream=Xl,e.SharedTextMarker=Ri,e.TextMarker=zi,e.LineWidget=Pi,e.e_preventDefault=Ee,e.e_stopPropagation=Ie,e.e_stop=Fe,e.addClass=l,e.contains=i,e.rmClass=wl,e.keyNames=fs}var Zo=navigator.userAgent,Qo=navigator.platform,Jo=/gecko\/\d/i.test(Zo),el=/MSIE \d/.test(Zo),tl=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(Zo),rl=el||tl,nl=rl&&(el?document.documentMode||6:tl[1]),il=/WebKit\//.test(Zo),ol=il&&/Qt\/\d+\.\d+/.test(Zo),ll=/Chrome\//.test(Zo),sl=/Opera\//.test(Zo),al=/Apple Computer/.test(navigator.vendor),ul=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(Zo),cl=/PhantomJS/.test(Zo),fl=/AppleWebKit/.test(Zo)&&/Mobile\/\w+/.test(Zo),hl=fl||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(Zo),dl=fl||/Mac/.test(Qo),pl=/\bCrOS\b/.test(Zo),gl=/win/i.test(Qo),vl=sl&&Zo.match(/Version\/(\d*\.\d*)/);vl&&(vl=Number(vl[1])),vl&&vl>=15&&(sl=!1,il=!0);var ml,yl=dl&&(ol||sl&&(null==vl||vl<12.11)),bl=Jo||rl&&nl>=9,wl=function(t,r){var n=t.className,i=e(r).exec(n);if(i){var o=n.slice(i.index+i[0].length);t.className=n.slice(0,i.index)+(o?i[1]+o:"")}};ml=document.createRange?function(e,t,r,n){var i=document.createRange();return i.setEnd(n||e,r),i.setStart(e,t),i}:function(e,t,r){var n=document.body.createTextRange();try{n.moveToElementText(e.parentNode)}catch(i){return n}return n.collapse(!0),n.moveEnd("character",r),n.moveStart("character",t),n};var xl=function(e){e.select()};fl?xl=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:rl&&(xl=function(e){try{e.select()}catch(t){}}),f.prototype.set=function(e,t){clearTimeout(this.id),this.id=setTimeout(t,e)};var Cl,Sl,Ll=30,Tl={toString:function(){return"CodeMirror.Pass"}},Ml={scroll:!1},kl={origin:"*mouse"},Nl={origin:"+move"},Al=[""],Ol=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,Wl=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/,Dl=!1,Hl=!1,Pl=null,El=function(){function e(e){return e<=247?r.charAt(e):1424<=e&&e<=1524?"R":1536<=e&&e<=1785?n.charAt(e-1536):1774<=e&&e<=2220