Code Snippets - Version 1.9

Version Description

  • Add and remove network capabilities as super admins are added and removed
  • Updated MP6 icon implementation
  • Replaced buggy trim <?php and ?> functionality with a much more reliable regex method (#)
  • Added French translation thanks to translator oWEB
  • Fixed snippet failing to save when code contains % character, props to nikan06 (#)
  • Added 'Save & Deactivate' button to the edit snippet page (#)
  • Removed edit and install capabilities (now only uses the manage capability)
  • Fixed HTML breaking in export files (#)
  • Make the title of each snippet on the manage page a clickable link to edit the snippet (#)
  • Added nonce to edit snippet page
  • Hide row actions on manage snippet page by default
  • Removed screenshots from plugin
  • Improved CodeMirror implementation
  • Added a fallback MP6 icon
  • Use the proper WordPress database APIs all of the time
  • Rewritten export functionality
  • Fixed incorrect export filename
  • Updated CodeMirror to version 3.19
  • Removed CodeMirror bundled with plugin
  • Updated WordPress.org plugin banner
  • Fixed CodeMirror incompatibility with the WP Editor plugin
  • Fixed CodeMirror incompatibility with the Debug Bar Console plugin
Download this release

Release Info

Developer bungeshea
Plugin Icon Code Snippets
Version 1.9
Comparing to
See all releases

Code changes from version 1.8.1.1 to 1.9

admin/messages/single.php CHANGED
@@ -21,6 +21,10 @@ elseif ( isset( $_REQUEST['activated'], $_REQUEST['added'] ) && $_REQUEST['activ
21
 
22
  printf ( $_f, __( 'Snippet <strong>added</strong> and <strong>activated</strong>.', 'code-snippets' ), 'updated' );
23
 
 
 
 
 
24
  elseif ( isset( $_REQUEST['updated'] ) && $_REQUEST['updated'] ) :
25
 
26
  printf ( $_f, __( 'Snippet <strong>updated</strong>.', 'code-snippets' ), 'updated' );
21
 
22
  printf ( $_f, __( 'Snippet <strong>added</strong> and <strong>activated</strong>.', 'code-snippets' ), 'updated' );
23
 
24
+ elseif ( isset( $_REQUEST['deactivated'], $_REQUEST['updated'] ) && $_REQUEST['deactivated'] && $_REQUEST['updated'] ) :
25
+
26
+ printf ( $_f, __( 'Snippet <strong>updated</strong> and <strong>deactivated</strong>.', 'code-snippets' ), 'updated' );
27
+
28
  elseif ( isset( $_REQUEST['updated'] ) && $_REQUEST['updated'] ) :
29
 
30
  printf ( $_f, __( 'Snippet <strong>updated</strong>.', 'code-snippets' ), 'updated' );
admin/views/single.php CHANGED
@@ -61,16 +61,60 @@ $code_snippets->admin->get_messages( 'single' );
61
 
62
  <textarea id="snippet_code" name="snippet_code" rows="20" spellcheck="false" style="font-family: monospace; width: 100%;"><?php echo esc_textarea( $snippet->code ); ?></textarea>
63
 
64
- <?php do_action( 'code_snippets/admin/single', $snippet ); ?>
 
 
 
 
 
 
 
 
65
 
66
  <p class="submit">
67
  <?php
 
 
 
68
  submit_button( null, 'primary', 'save_snippet', false );
69
 
 
 
70
  if ( ! $snippet->active ) {
71
- echo '&nbsp;&nbsp;&nbsp;';
72
- submit_button( __( 'Save Changes &amp; Activate', 'code-snippets' ), 'secondary', 'save_snippet_activate', false );
 
 
 
 
 
 
 
 
73
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  ?>
75
  </p>
76
 
61
 
62
  <textarea id="snippet_code" name="snippet_code" rows="20" spellcheck="false" style="font-family: monospace; width: 100%;"><?php echo esc_textarea( $snippet->code ); ?></textarea>
63
 
64
+ <?php
65
+
66
+ /* Allow addon plugins (and us!) to add fields and content to this page */
67
+ do_action( 'code_snippets/admin/single', $snippet );
68
+
69
+ /* Add a nonce for security */
70
+ wp_nonce_field( 'save_snippet' );
71
+
72
+ ?>
73
 
74
  <p class="submit">
75
  <?php
76
+
77
+ /* Save Snippet button */
78
+
79
  submit_button( null, 'primary', 'save_snippet', false );
80
 
81
+ /* Save Snippet & Activate/Deactivate button */
82
+
83
  if ( ! $snippet->active ) {
84
+ submit_button(
85
+ __( 'Save Changes &amp; Activate', 'code-snippets' ),
86
+ 'secondary', 'save_snippet_activate', false
87
+ );
88
+
89
+ } else {
90
+ submit_button(
91
+ __( 'Save Changes &amp; Deactivate', 'code-snippets' ),
92
+ 'secondary', 'save_snippet_deactivate', false
93
+ );
94
  }
95
+
96
+ if ( 0 !== $snippet->id ) {
97
+
98
+ /* Export button */
99
+
100
+ submit_button( __( 'Export', 'code-snippets' ), 'secondary', 'export_snippet', false );
101
+
102
+ /* Delete button */
103
+
104
+ $confirm_delete_js = esc_js(
105
+ sprintf (
106
+ 'return confirm("%s");',
107
+ __( "You are about to permanently delete this snippet.\n'Cancel' to stop, 'OK' to delete.", 'code-snippets' )
108
+ )
109
+ );
110
+
111
+ submit_button(
112
+ __( 'Delete', 'code-snippets' ),
113
+ 'secondary', 'delete_snippet', false,
114
+ sprintf ( 'onclick="%s"', $confirm_delete_js )
115
+ );
116
+ }
117
+
118
  ?>
119
  </p>
120
 
assets/config.rb CHANGED
@@ -8,7 +8,7 @@ images_dir = "assets/images"
8
  javascripts_dir = "assets/js"
9
 
10
  # You can select your preferred output style here (can be overridden via the command line):
11
- output_style = :compressed # or :expanded or :nested or :compact
12
 
13
  # Enable relative paths to assets via compass helper functions.
14
  relative_assets = true
8
  javascripts_dir = "assets/js"
9
 
10
  # You can select your preferred output style here (can be overridden via the command line):
11
+ # output_style = :compressed or :expanded or :nested or :compact
12
 
13
  # Enable relative paths to assets via compass helper functions.
14
  relative_assets = true
assets/css/admin-single.css CHANGED
@@ -1 +1 @@
1
- h3{margin:1em 0}label{cursor:auto}.CodeMirror{min-height:300px;height:auto;border:1px solid #eee;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}.admin-color-mp6 .CodeMirror{width:100%;border-color:#dfdfdf;background-color:#fff}.CodeMirror-scroll{overflow-x:auto;overflow-y:hidden}.CodeMirror-sizer{min-height:300px !important}
1
+ .CodeMirror{font-family:monospace;height:300px}.CodeMirror-scroll{overflow:auto}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999}.CodeMirror div.CodeMirror-cursor{border-left:1px solid #000;z-index:3}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor{width:auto;border:0;background:#7e7;z-index:1}.cm-tab{display:inline-block}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable{color:#000}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-property,.cm-s-default .cm-operator{color:#000}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-error{color:red}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-invalidchar{color:red}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{line-height:1;position:relative;overflow:hidden;background:#fff;color:#000}.CodeMirror-scroll{margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;padding-right:30px;height:100%;outline:none;position:relative;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}.CodeMirror-sizer{position:relative}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;padding-bottom:30px;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;padding-bottom:30px;margin-bottom:-32px;display:inline-block;*zoom:1;*display:inline}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text}.CodeMirror pre{border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-code pre{border-right:30px solid transparent;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.CodeMirror-wrap .CodeMirror-code pre{border-right:none;width:auto}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-wrap .CodeMirror-scroll{overflow-x:hidden}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-measure pre{position:static}.CodeMirror div.CodeMirror-cursor{position:absolute;visibility:hidden;border-right:none;width:0}.CodeMirror-focused div.CodeMirror-cursor{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}@media print{.CodeMirror div.CodeMirror-cursor{visibility:hidden}}h3{margin:1em 0}label{cursor:auto}label[for="snippet_description"] h3 div{position:absolute}.mp6 label[for="snippet_description"] h3 div{position:initial}.submit .button{margin-right:.5em}.CodeMirror{min-height:300px;height:auto;border:1px solid #eee;border-radius:3px}.mp6 .CodeMirror{width:100%;border-color:#dfdfdf;background-color:#fff}.CodeMirror-scroll{overflow-x:auto;overflow-y:hidden}.CodeMirror-sizer{min-height:300px!important}
assets/css/menu-icon-mp6.css CHANGED
@@ -1 +1 @@
1
- #toplevel_page_snippets div.wp-menu-image{background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQoNCjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDRwdCIgd2lkdGg9IjQ4cHQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDQ4IDQ0Ij4NCg0KCTxwYXRoIGNsYXNzPSJzbmlwcGV0cy1pY29uLXN2ZyIgZD0iTTMyLjcyLDEuODFjMy4xNy0yLjI3LDkuNzEtMS4xNiwxMC4zMiwzLjEzLTIuOCwzLjcyLTYuNDksNi42NS05LjY0LDEwLjA2LDQuODIsMC41MywxMC4xNi0xLjIyLDE0LjYsMS4xNnYxLjU1Yy0wLjM3LDMuMTEtMi4zNSw2LjE0LTUuNDksNi45Ny02Ljc5LDEuMjktMTQuMDQtMS4wMi0yMC42MiwxLjI1LDIuNjYsMS42Nyw1LjU2LDMuNzQsNi4wNyw3LjEsMS4yNCw1LjEyLTIuOTEsMTAuNDMtOC4wOCwxMC44LTUuMjcsMC41LTEwLjM3LTQuNDUtOS42Ni05Ljc5LDAuMzYtNC42Niw0LjczLTcuMjIsNy40Ni0xMC40OSwxLjE1LTAuOTgsMS4wMi0zLjE2LTAuNzMtMy4zNy0zLjc4LTAuNTctNy43NSwwLjQzLTExLjQyLTAuODktMy4wNi0xLjItNC45OS00LjE5LTUuNTMtNy4zNXYtMi4xNWMwLjgzLTUuODcsNy43OC05Ljc0LDEzLjA4LTYuNzksNC41OSwyLjE3LDUuNzcsNy44Myw0LjIxLDEyLjMyLDAuNTgtMC4yMSwxLjc1LTAuNjEsMi4zNC0wLjgyLDQuNTctNCw4LjM4LTguODQsMTMuMDktMTIuNjl6IE03LjMzLDcuNGMyLjQ4LTEuMjcsNS43OSwwLjgxLDUuNjksMy42MSwwLjEzLDMuMDYtMy44OCw1LjE3LTYuMjgsMy4yMy0yLjU4LTEuNDktMi4xNS01Ljc3LDAuNTktNi44NHogTTE3LjM2LDMxLjM4YzIuODEtMS43OCw2Ljc0LDEuNDUsNS42Niw0LjU2LTAuNjgsMi44My00LjY4LDMuOS02LjY1LDEuNzQtMS45My0xLjc3LTEuNC01LjIxLDAuOTktNi4zeiIgZmlsbC1ydWxlPSJldmVub2RkIiBmaWxsPSIjOTk5OTk5Ii8+DQoNCjwvc3ZnPg0K') !important;background-position:center center !important;background-size:20px 20px;background-repeat:no-repeat;margin-top:2px}#toplevel_page_snippets div.wp-menu-image:before{display:none}
1
+ .mp6.no-svg #toplevel_page_snippets div.wp-menu-image:before{content:'\f106'}.mp6.svg #toplevel_page_snippets div.wp-menu-image{background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQoNCjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDRwdCIgd2lkdGg9IjQ4cHQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDQ4IDQ0Ij4NCg0KCTxwYXRoIGNsYXNzPSJzbmlwcGV0cy1pY29uLXN2ZyIgZD0iTTMyLjcyLDEuODFjMy4xNy0yLjI3LDkuNzEtMS4xNiwxMC4zMiwzLjEzLTIuOCwzLjcyLTYuNDksNi42NS05LjY0LDEwLjA2LDQuODIsMC41MywxMC4xNi0xLjIyLDE0LjYsMS4xNnYxLjU1Yy0wLjM3LDMuMTEtMi4zNSw2LjE0LTUuNDksNi45Ny02Ljc5LDEuMjktMTQuMDQtMS4wMi0yMC42MiwxLjI1LDIuNjYsMS42Nyw1LjU2LDMuNzQsNi4wNyw3LjEsMS4yNCw1LjEyLTIuOTEsMTAuNDMtOC4wOCwxMC44LTUuMjcsMC41LTEwLjM3LTQuNDUtOS42Ni05Ljc5LDAuMzYtNC42Niw0LjczLTcuMjIsNy40Ni0xMC40OSwxLjE1LTAuOTgsMS4wMi0zLjE2LTAuNzMtMy4zNy0zLjc4LTAuNTctNy43NSwwLjQzLTExLjQyLTAuODktMy4wNi0xLjItNC45OS00LjE5LTUuNTMtNy4zNXYtMi4xNWMwLjgzLTUuODcsNy43OC05Ljc0LDEzLjA4LTYuNzksNC41OSwyLjE3LDUuNzcsNy44Myw0LjIxLDEyLjMyLDAuNTgtMC4yMSwxLjc1LTAuNjEsMi4zNC0wLjgyLDQuNTctNCw4LjM4LTguODQsMTMuMDktMTIuNjl6IE03LjMzLDcuNGMyLjQ4LTEuMjcsNS43OSwwLjgxLDUuNjksMy42MSwwLjEzLDMuMDYtMy44OCw1LjE3LTYuMjgsMy4yMy0yLjU4LTEuNDktMi4xNS01Ljc3LDAuNTktNi44NHogTTE3LjM2LDMxLjM4YzIuODEtMS43OCw2Ljc0LDEuNDUsNS42Niw0LjU2LTAuNjgsMi44My00LjY4LDMuOS02LjY1LDEuNzQtMS45My0xLjc3LTEuNC01LjIxLDAuOTktNi4zeiIgZmlsbC1ydWxlPSJldmVub2RkIiBmaWxsPSIjOTk5OTk5Ii8+DQoNCjwvc3ZnPg0K') !important;background-position:center center!important;-webkit-background-size:20px 20px;background-size:20px 20px;background-repeat:no-repeat}.mp6.svg #toplevel_page_snippets div.wp-menu-image:before{display:none}
assets/css/screen-icon.css CHANGED
@@ -1 +1 @@
1
- #icon-snippets.icon32{background:url('../images/screen-icon.png?1373856319') no-repeat scroll transparent}
1
+ #icon-snippets.icon32{background:url('../images/screen-icon.png?1377954941') no-repeat}
assets/css/table-mp6.css CHANGED
@@ -1 +1 @@
1
- .snippets th,.snippets td{color:#000}.snippets tr{background:#fff}.snippets .row-actions-visible{color:#ddd}.snippets tfoot th{border-top:none !important}.snippets tfoot th.check-column{padding:13px 0 0 3px}.snippets thead th.check-column,.snippets tfoot th.check-column,.snippets .inactive th.check-column{padding-left:5px}.snippets .column-description p{color:#333}.snippets .inactive a{color:#579}.snippets .inactive .column-name strong{color:#333;font-weight:400}.snippets .inactive td,.snippets .inactive th,.snippets .active td,.snippets .active th{-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1);padding:10px 9px;border:none}.snippets .active td,.snippets .active th{background-color:rgba(120,200,230,0.06)}.snippets .active th.check-column{border-left:2px solid #2ea2cc}.snippets tr.active+tr.inactive th,.snippets tr.active+tr.inactive td{-webkit-box-shadow:inset 0px 1px 0 rgba(0,0,0,0.02),inset 0 -1px 0 #e1e1e1;-moz-box-shadow:inset 0px 1px 0 rgba(0,0,0,0.02),inset 0 -1px 0 #e1e1e1;box-shadow:inset 0px 1px 0 rgba(0,0,0,0.02),inset 0 -1px 0 #e1e1e1;border-top:1px solid rgba(0,0,0,0.03)}.snippets a.delete:hover,.snippets #all-snippets-table a.delete:hover,.snippets #search-snippets-table a.delete:hover{border-bottom:1px solid #f00;color:#f00}#wpbody-content .snippets .column-name{white-space:nowrap}
1
+ .snippets th,.snippets td{color:#000}.snippets tr{background:#fff}.snippets .row-actions{color:#ddd}.snippets tfoot th{border-top:none!important}.snippets tfoot th.check-column{padding:13px 0 0 3px}.snippets thead th.check-column,.snippets tfoot th.check-column,.snippets .inactive th.check-column{padding-left:5px}.snippets .column-description p{color:#333}.snippets .inactive a{color:#579}.snippets .inactive td,.snippets .inactive th,.snippets .active td,.snippets .active th{-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.1);box-shadow:inset 0 -1px 0 rgba(0,0,0,.1);padding:10px 9px;border:none}.snippets .active td,.snippets .active th{background-color:rgba(120,200,230,.06)}.snippets .active th.check-column{border-left:2px solid #2ea2cc}.snippets tr.active+tr.inactive th,.snippets tr.active+tr.inactive td{-webkit-box-shadow:inset 0 1px 0 rgba(0,0,0,.02),inset 0 -1px 0 #e1e1e1;box-shadow:inset 0 1px 0 rgba(0,0,0,.02),inset 0 -1px 0 #e1e1e1;border-top:1px solid rgba(0,0,0,.03)}.snippets a.delete:hover,.snippets #all-snippets-table a.delete:hover,.snippets #search-snippets-table a.delete:hover{border-bottom:1px solid red;color:red}#wpbody-content .snippets .column-name{white-space:nowrap}
assets/css/table.css CHANGED
@@ -1 +1 @@
1
- .snippets .delete a{color:#21759b}.snippets .inactive th,.snippets .inactive td{background-color:#f4f4f4}.snippets .inactive a{color:#557799}.snippets .inactive a:hover,#all-snippets-table .snippets .inactive a:hover,#search-snippets-table .snippets .inactive a:hover{color:#d54e21}.snippets .active th,.snippets .active td{color:#000}#wpbody-content .snippets tr{background-color:#fcfcfc}#wpbody-content .snippets .column-name{white-space:nowrap}#wpbody-content .snippets .manage-column.column-id.sortable{min-width:44px}
1
+ .snippets .delete a{color:#21759b}.snippets .inactive th,.snippets .inactive td{background-color:#f4f4f4}.snippets .inactive a{color:#579}.snippets .inactive a:hover,#all-snippets-table .snippets .inactive a:hover,#search-snippets-table .snippets .inactive a:hover{color:#d54e21}.snippets .active th,.snippets .active td{color:#000}#wpbody-content .snippets tr{background-color:#fcfcfc}#wpbody-content .snippets .column-name{white-space:nowrap}#wpbody-content .snippets .manage-column.column-id.sortable{min-width:44px}
assets/images/menu-icon-mp6-active.svg DELETED
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
-
3
- <svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="44pt" width="48pt" version="1.1" viewBox="0 0 48 44">
4
-
5
- <path class="snippets-icon-svg" d="M32.72,1.81c3.17-2.27,9.71-1.16,10.32,3.13-2.8,3.72-6.49,6.65-9.64,10.06,4.82,0.53,10.16-1.22,14.6,1.16v1.55c-0.37,3.11-2.35,6.14-5.49,6.97-6.79,1.29-14.04-1.02-20.62,1.25,2.66,1.67,5.56,3.74,6.07,7.1,1.24,5.12-2.91,10.43-8.08,10.8-5.27,0.5-10.37-4.45-9.66-9.79,0.36-4.66,4.73-7.22,7.46-10.49,1.15-0.98,1.02-3.16-0.73-3.37-3.78-0.57-7.75,0.43-11.42-0.89-3.06-1.2-4.99-4.19-5.53-7.35v-2.15c0.83-5.87,7.78-9.74,13.08-6.79,4.59,2.17,5.77,7.83,4.21,12.32,0.58-0.21,1.75-0.61,2.34-0.82,4.57-4,8.38-8.84,13.09-12.69z M7.33,7.4c2.48-1.27,5.79,0.81,5.69,3.61,0.13,3.06-3.88,5.17-6.28,3.23-2.58-1.49-2.15-5.77,0.59-6.84z M17.36,31.38c2.81-1.78,6.74,1.45,5.66,4.56-0.68,2.83-4.68,3.9-6.65,1.74-1.93-1.77-1.4-5.21,0.99-6.3z" fill-rule="evenodd" fill="#fff"/>
6
-
7
- </svg>
 
 
 
 
 
 
 
assets/images/menu-icon-mp6-hover.svg DELETED
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
-
3
- <svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="44pt" width="48pt" version="1.1" viewBox="0 0 48 44">
4
-
5
- <path class="snippets-icon-svg" d="M32.72,1.81c3.17-2.27,9.71-1.16,10.32,3.13-2.8,3.72-6.49,6.65-9.64,10.06,4.82,0.53,10.16-1.22,14.6,1.16v1.55c-0.37,3.11-2.35,6.14-5.49,6.97-6.79,1.29-14.04-1.02-20.62,1.25,2.66,1.67,5.56,3.74,6.07,7.1,1.24,5.12-2.91,10.43-8.08,10.8-5.27,0.5-10.37-4.45-9.66-9.79,0.36-4.66,4.73-7.22,7.46-10.49,1.15-0.98,1.02-3.16-0.73-3.37-3.78-0.57-7.75,0.43-11.42-0.89-3.06-1.2-4.99-4.19-5.53-7.35v-2.15c0.83-5.87,7.78-9.74,13.08-6.79,4.59,2.17,5.77,7.83,4.21,12.32,0.58-0.21,1.75-0.61,2.34-0.82,4.57-4,8.38-8.84,13.09-12.69z M7.33,7.4c2.48-1.27,5.79,0.81,5.69,3.61,0.13,3.06-3.88,5.17-6.28,3.23-2.58-1.49-2.15-5.77,0.59-6.84z M17.36,31.38c2.81-1.78,6.74,1.45,5.66,4.56-0.68,2.83-4.68,3.9-6.65,1.74-1.93-1.77-1.4-5.21,0.99-6.3z" fill-rule="evenodd" fill="#2ea2cc"/>
6
-
7
- </svg>
 
 
 
 
 
 
 
assets/js/admin-single.dev.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Loads CodeMirror on the snippet editor
3
+ */
4
+ (function() {
5
+
6
+ // import 'codemirror/lib/codemirror.js'
7
+ // import 'codemirror/mode/clike/clike.js'
8
+ // import 'codemirror/mode/php/php.js'
9
+ // import 'codemirror/addon/search/searchcursor.js'
10
+ // import 'codemirror/addon/search/search.js'
11
+ // import 'codemirror/addon/edit/matchbrackets.js'
12
+
13
+ var atts = {
14
+ lineNumbers: true,
15
+ matchBrackets: true,
16
+ lineWrapping: true,
17
+ mode: "text/x-php",
18
+ indentUnit: 4,
19
+ indentWithTabs: true,
20
+ enterMode: "keep",
21
+ tabMode: "shift"
22
+ };
23
+
24
+ var editor = CodeMirror.fromTextArea(document.getElementById("snippet_code"), atts);
25
+
26
+ })();
assets/js/admin-single.js CHANGED
@@ -1,14 +1,6790 @@
1
  /**
2
  * Loads CodeMirror on the snippet editor
3
  */
 
4
 
5
- var editor = CodeMirror.fromTextArea(document.getElementById("snippet_code"), {
6
- lineNumbers: true,
7
- matchBrackets: true,
8
- lineWrapping: true,
9
- mode: "text/x-php",
10
- indentUnit: 4,
11
- indentWithTabs: true,
12
- enterMode: "keep",
13
- tabMode: "shift"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /**
2
  * Loads CodeMirror on the snippet editor
3
  */
4
+ (function() {
5
 
6
+ // CodeMirror is the only global var we claim
7
+ window.CodeMirror = (function() {
8
+ "use strict";
9
+
10
+ // BROWSER SNIFFING
11
+
12
+ // Crude, but necessary to handle a number of hard-to-feature-detect
13
+ // bugs and behavior differences.
14
+ var gecko = /gecko\/\d/i.test(navigator.userAgent);
15
+ var ie = /MSIE \d/.test(navigator.userAgent);
16
+ var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
17
+ var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
18
+ var webkit = /WebKit\//.test(navigator.userAgent);
19
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
20
+ var chrome = /Chrome\//.test(navigator.userAgent);
21
+ var opera = /Opera\//.test(navigator.userAgent);
22
+ var safari = /Apple Computer/.test(navigator.vendor);
23
+ var khtml = /KHTML\//.test(navigator.userAgent);
24
+ var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
25
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
26
+ var phantom = /PhantomJS/.test(navigator.userAgent);
27
+
28
+ var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
29
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
30
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
31
+ var mac = ios || /Mac/.test(navigator.platform);
32
+ var windows = /win/i.test(navigator.platform);
33
+
34
+ var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
35
+ if (opera_version) opera_version = Number(opera_version[1]);
36
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
37
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
38
+ var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
39
+ var captureMiddleClick = gecko || (ie && !ie_lt9);
40
+
41
+ // Optimize some code when these features are not used
42
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
43
+
44
+ // CONSTRUCTOR
45
+
46
+ function CodeMirror(place, options) {
47
+ if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
48
+
49
+ this.options = options = options || {};
50
+ // Determine effective options based on given values and defaults.
51
+ for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
52
+ options[opt] = defaults[opt];
53
+ setGuttersForLineNumbers(options);
54
+
55
+ var docStart = typeof options.value == "string" ? 0 : options.value.first;
56
+ var display = this.display = makeDisplay(place, docStart);
57
+ display.wrapper.CodeMirror = this;
58
+ updateGutters(this);
59
+ if (options.autofocus && !mobile) focusInput(this);
60
+
61
+ this.state = {keyMaps: [],
62
+ overlays: [],
63
+ modeGen: 0,
64
+ overwrite: false, focused: false,
65
+ suppressEdits: false, pasteIncoming: false,
66
+ draggingText: false,
67
+ highlight: new Delayed()};
68
+
69
+ themeChanged(this);
70
+ if (options.lineWrapping)
71
+ this.display.wrapper.className += " CodeMirror-wrap";
72
+
73
+ var doc = options.value;
74
+ if (typeof doc == "string") doc = new Doc(options.value, options.mode);
75
+ operation(this, attachDoc)(this, doc);
76
+
77
+ // Override magic textarea content restore that IE sometimes does
78
+ // on our hidden textarea on reload
79
+ if (ie) setTimeout(bind(resetInput, this, true), 20);
80
+
81
+ registerEventHandlers(this);
82
+ // IE throws unspecified error in certain cases, when
83
+ // trying to access activeElement before onload
84
+ var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
85
+ if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
86
+ else onBlur(this);
87
+
88
+ operation(this, function() {
89
+ for (var opt in optionHandlers)
90
+ if (optionHandlers.propertyIsEnumerable(opt))
91
+ optionHandlers[opt](this, options[opt], Init);
92
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
93
+ })();
94
+ }
95
+
96
+ // DISPLAY CONSTRUCTOR
97
+
98
+ function makeDisplay(place, docStart) {
99
+ var d = {};
100
+
101
+ var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
102
+ if (webkit) input.style.width = "1000px";
103
+ else input.setAttribute("wrap", "off");
104
+ // if border: 0; -- iOS fails to open keyboard (issue #1287)
105
+ if (ios) input.style.border = "1px solid black";
106
+ input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
107
+
108
+ // Wraps and hides input textarea
109
+ d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
110
+ // The actual fake scrollbars.
111
+ d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
112
+ d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
113
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
114
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
115
+ // DIVs containing the selection and the actual code
116
+ d.lineDiv = elt("div", null, "CodeMirror-code");
117
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
118
+ // Blinky cursor, and element used to ensure cursor fits at the end of a line
119
+ d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
120
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
121
+ d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
122
+ // Used to measure text size
123
+ d.measure = elt("div", null, "CodeMirror-measure");
124
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
125
+ d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
126
+ null, "position: relative; outline: none");
127
+ // Moved around its parent to cover visible view
128
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
129
+ // Set to the height of the text, causes scrolling
130
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
131
+ // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
132
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
133
+ // Will contain the gutters, if any
134
+ d.gutters = elt("div", null, "CodeMirror-gutters");
135
+ d.lineGutter = null;
136
+ // Provides scrolling
137
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
138
+ d.scroller.setAttribute("tabIndex", "-1");
139
+ // The element in which the editor lives.
140
+ d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
141
+ d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
142
+ // Work around IE7 z-index bug
143
+ if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
144
+ if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
145
+
146
+ // Needed to hide big blue blinking cursor on Mobile Safari
147
+ if (ios) input.style.width = "0px";
148
+ if (!webkit) d.scroller.draggable = true;
149
+ // Needed to handle Tab key in KHTML
150
+ if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
151
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
152
+ else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
153
+
154
+ // Current visible range (may be bigger than the view window).
155
+ d.viewOffset = d.lastSizeC = 0;
156
+ d.showingFrom = d.showingTo = docStart;
157
+
158
+ // Used to only resize the line number gutter when necessary (when
159
+ // the amount of lines crosses a boundary that makes its width change)
160
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
161
+ // See readInput and resetInput
162
+ d.prevInput = "";
163
+ // Set to true when a non-horizontal-scrolling widget is added. As
164
+ // an optimization, widget aligning is skipped when d is false.
165
+ d.alignWidgets = false;
166
+ // Flag that indicates whether we currently expect input to appear
167
+ // (after some event like 'keypress' or 'input') and are polling
168
+ // intensively.
169
+ d.pollingFast = false;
170
+ // Self-resetting timeout for the poller
171
+ d.poll = new Delayed();
172
+
173
+ d.cachedCharWidth = d.cachedTextHeight = null;
174
+ d.measureLineCache = [];
175
+ d.measureLineCachePos = 0;
176
+
177
+ // Tracks when resetInput has punted to just putting a short
178
+ // string instead of the (large) selection.
179
+ d.inaccurateSelection = false;
180
+
181
+ // Tracks the maximum line length so that the horizontal scrollbar
182
+ // can be kept static when scrolling.
183
+ d.maxLine = null;
184
+ d.maxLineLength = 0;
185
+ d.maxLineChanged = false;
186
+
187
+ // Used for measuring wheel scrolling granularity
188
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
189
+
190
+ return d;
191
+ }
192
+
193
+ // STATE UPDATES
194
+
195
+ // Used to get the editor into a consistent state again when options change.
196
+
197
+ function loadMode(cm) {
198
+ cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
199
+ cm.doc.iter(function(line) {
200
+ if (line.stateAfter) line.stateAfter = null;
201
+ if (line.styles) line.styles = null;
202
+ });
203
+ cm.doc.frontier = cm.doc.first;
204
+ startWorker(cm, 100);
205
+ cm.state.modeGen++;
206
+ if (cm.curOp) regChange(cm);
207
+ }
208
+
209
+ function wrappingChanged(cm) {
210
+ if (cm.options.lineWrapping) {
211
+ cm.display.wrapper.className += " CodeMirror-wrap";
212
+ cm.display.sizer.style.minWidth = "";
213
+ } else {
214
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
215
+ computeMaxLength(cm);
216
+ }
217
+ estimateLineHeights(cm);
218
+ regChange(cm);
219
+ clearCaches(cm);
220
+ setTimeout(function(){updateScrollbars(cm);}, 100);
221
+ }
222
+
223
+ function estimateHeight(cm) {
224
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
225
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
226
+ return function(line) {
227
+ if (lineIsHidden(cm.doc, line))
228
+ return 0;
229
+ else if (wrapping)
230
+ return (Math.ceil(line.text.length / perLine) || 1) * th;
231
+ else
232
+ return th;
233
+ };
234
+ }
235
+
236
+ function estimateLineHeights(cm) {
237
+ var doc = cm.doc, est = estimateHeight(cm);
238
+ doc.iter(function(line) {
239
+ var estHeight = est(line);
240
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
241
+ });
242
+ }
243
+
244
+ function keyMapChanged(cm) {
245
+ var map = keyMap[cm.options.keyMap], style = map.style;
246
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
247
+ (style ? " cm-keymap-" + style : "");
248
+ cm.state.disableInput = map.disableInput;
249
+ }
250
+
251
+ function themeChanged(cm) {
252
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
253
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
254
+ clearCaches(cm);
255
+ }
256
+
257
+ function guttersChanged(cm) {
258
+ updateGutters(cm);
259
+ regChange(cm);
260
+ setTimeout(function(){alignHorizontally(cm);}, 20);
261
+ }
262
+
263
+ function updateGutters(cm) {
264
+ var gutters = cm.display.gutters, specs = cm.options.gutters;
265
+ removeChildren(gutters);
266
+ for (var i = 0; i < specs.length; ++i) {
267
+ var gutterClass = specs[i];
268
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
269
+ if (gutterClass == "CodeMirror-linenumbers") {
270
+ cm.display.lineGutter = gElt;
271
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
272
+ }
273
+ }
274
+ gutters.style.display = i ? "" : "none";
275
+ }
276
+
277
+ function lineLength(doc, line) {
278
+ if (line.height == 0) return 0;
279
+ var len = line.text.length, merged, cur = line;
280
+ while (merged = collapsedSpanAtStart(cur)) {
281
+ var found = merged.find();
282
+ cur = getLine(doc, found.from.line);
283
+ len += found.from.ch - found.to.ch;
284
+ }
285
+ cur = line;
286
+ while (merged = collapsedSpanAtEnd(cur)) {
287
+ var found = merged.find();
288
+ len -= cur.text.length - found.from.ch;
289
+ cur = getLine(doc, found.to.line);
290
+ len += cur.text.length - found.to.ch;
291
+ }
292
+ return len;
293
+ }
294
+
295
+ function computeMaxLength(cm) {
296
+ var d = cm.display, doc = cm.doc;
297
+ d.maxLine = getLine(doc, doc.first);
298
+ d.maxLineLength = lineLength(doc, d.maxLine);
299
+ d.maxLineChanged = true;
300
+ doc.iter(function(line) {
301
+ var len = lineLength(doc, line);
302
+ if (len > d.maxLineLength) {
303
+ d.maxLineLength = len;
304
+ d.maxLine = line;
305
+ }
306
+ });
307
+ }
308
+
309
+ // Make sure the gutters options contains the element
310
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
311
+ function setGuttersForLineNumbers(options) {
312
+ var found = indexOf(options.gutters, "CodeMirror-linenumbers");
313
+ if (found == -1 && options.lineNumbers) {
314
+ options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
315
+ } else if (found > -1 && !options.lineNumbers) {
316
+ options.gutters = options.gutters.slice(0);
317
+ options.gutters.splice(found, 1);
318
+ }
319
+ }
320
+
321
+ // SCROLLBARS
322
+
323
+ // Re-synchronize the fake scrollbars with the actual size of the
324
+ // content. Optionally force a scrollTop.
325
+ function updateScrollbars(cm) {
326
+ var d = cm.display, docHeight = cm.doc.height;
327
+ var totalHeight = docHeight + paddingVert(d);
328
+ d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
329
+ d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
330
+ var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
331
+ var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
332
+ var needsV = scrollHeight > (d.scroller.clientHeight + 1);
333
+ if (needsV) {
334
+ d.scrollbarV.style.display = "block";
335
+ d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
336
+ d.scrollbarV.firstChild.style.height =
337
+ (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
338
+ } else {
339
+ d.scrollbarV.style.display = "";
340
+ d.scrollbarV.firstChild.style.height = "0";
341
+ }
342
+ if (needsH) {
343
+ d.scrollbarH.style.display = "block";
344
+ d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
345
+ d.scrollbarH.firstChild.style.width =
346
+ (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
347
+ } else {
348
+ d.scrollbarH.style.display = "";
349
+ d.scrollbarH.firstChild.style.width = "0";
350
+ }
351
+ if (needsH && needsV) {
352
+ d.scrollbarFiller.style.display = "block";
353
+ d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
354
+ } else d.scrollbarFiller.style.display = "";
355
+ if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
356
+ d.gutterFiller.style.display = "block";
357
+ d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
358
+ d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
359
+ } else d.gutterFiller.style.display = "";
360
+
361
+ if (mac_geLion && scrollbarWidth(d.measure) === 0) {
362
+ d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
363
+ d.scrollbarV.style.pointerEvents = d.scrollbarH.style.pointerEvents = "none";
364
+ }
365
+ }
366
+
367
+ function visibleLines(display, doc, viewPort) {
368
+ var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
369
+ if (typeof viewPort == "number") top = viewPort;
370
+ else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
371
+ top = Math.floor(top - paddingTop(display));
372
+ var bottom = Math.ceil(top + height);
373
+ return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
374
+ }
375
+
376
+ // LINE NUMBERS
377
+
378
+ function alignHorizontally(cm) {
379
+ var display = cm.display;
380
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
381
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
382
+ var gutterW = display.gutters.offsetWidth, l = comp + "px";
383
+ for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
384
+ for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
385
+ }
386
+ if (cm.options.fixedGutter)
387
+ display.gutters.style.left = (comp + gutterW) + "px";
388
+ }
389
+
390
+ function maybeUpdateLineNumberWidth(cm) {
391
+ if (!cm.options.lineNumbers) return false;
392
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
393
+ if (last.length != display.lineNumChars) {
394
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
395
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
396
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
397
+ display.lineGutter.style.width = "";
398
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
399
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
400
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
401
+ display.lineGutter.style.width = display.lineNumWidth + "px";
402
+ return true;
403
+ }
404
+ return false;
405
+ }
406
+
407
+ function lineNumberFor(options, i) {
408
+ return String(options.lineNumberFormatter(i + options.firstLineNumber));
409
+ }
410
+ function compensateForHScroll(display) {
411
+ return getRect(display.scroller).left - getRect(display.sizer).left;
412
+ }
413
+
414
+ // DISPLAY DRAWING
415
+
416
+ function updateDisplay(cm, changes, viewPort, forced) {
417
+ var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
418
+ var visible = visibleLines(cm.display, cm.doc, viewPort);
419
+ for (var first = true;; first = false) {
420
+ var oldWidth = cm.display.scroller.clientWidth;
421
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
422
+ updated = true;
423
+ changes = [];
424
+ updateSelection(cm);
425
+ updateScrollbars(cm);
426
+ if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {
427
+ forced = true;
428
+ continue;
429
+ }
430
+ forced = false;
431
+
432
+ // Clip forced viewport to actual scrollable area
433
+ if (viewPort)
434
+ viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
435
+ typeof viewPort == "number" ? viewPort : viewPort.top);
436
+ visible = visibleLines(cm.display, cm.doc, viewPort);
437
+ if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
438
+ break;
439
+ }
440
+
441
+ if (updated) {
442
+ signalLater(cm, "update", cm);
443
+ if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
444
+ signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
445
+ }
446
+ return updated;
447
+ }
448
+
449
+ // Uses a set of changes plus the current scroll position to
450
+ // determine which DOM updates have to be made, and makes the
451
+ // updates.
452
+ function updateDisplayInner(cm, changes, visible, forced) {
453
+ var display = cm.display, doc = cm.doc;
454
+ if (!display.wrapper.clientWidth) {
455
+ display.showingFrom = display.showingTo = doc.first;
456
+ display.viewOffset = 0;
457
+ return;
458
+ }
459
+
460
+ // Bail out if the visible area is already rendered and nothing changed.
461
+ if (!forced && changes.length == 0 &&
462
+ visible.from > display.showingFrom && visible.to < display.showingTo)
463
+ return;
464
+
465
+ if (maybeUpdateLineNumberWidth(cm))
466
+ changes = [{from: doc.first, to: doc.first + doc.size}];
467
+ var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
468
+ display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
469
+
470
+ // Used to determine which lines need their line numbers updated
471
+ var positionsChangedFrom = Infinity;
472
+ if (cm.options.lineNumbers)
473
+ for (var i = 0; i < changes.length; ++i)
474
+ if (changes[i].diff && changes[i].from < positionsChangedFrom) { positionsChangedFrom = changes[i].from; }
475
+
476
+ var end = doc.first + doc.size;
477
+ var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
478
+ var to = Math.min(end, visible.to + cm.options.viewportMargin);
479
+ if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
480
+ if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
481
+ if (sawCollapsedSpans) {
482
+ from = lineNo(visualLine(doc, getLine(doc, from)));
483
+ while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
484
+ }
485
+
486
+ // Create a range of theoretically intact lines, and punch holes
487
+ // in that using the change info.
488
+ var intact = [{from: Math.max(display.showingFrom, doc.first),
489
+ to: Math.min(display.showingTo, end)}];
490
+ if (intact[0].from >= intact[0].to) intact = [];
491
+ else intact = computeIntact(intact, changes);
492
+ // When merged lines are present, we might have to reduce the
493
+ // intact ranges because changes in continued fragments of the
494
+ // intact lines do require the lines to be redrawn.
495
+ if (sawCollapsedSpans)
496
+ for (var i = 0; i < intact.length; ++i) {
497
+ var range = intact[i], merged;
498
+ while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
499
+ var newTo = merged.find().from.line;
500
+ if (newTo > range.from) range.to = newTo;
501
+ else { intact.splice(i--, 1); break; }
502
+ }
503
+ }
504
+
505
+ // Clip off the parts that won't be visible
506
+ var intactLines = 0;
507
+ for (var i = 0; i < intact.length; ++i) {
508
+ var range = intact[i];
509
+ if (range.from < from) range.from = from;
510
+ if (range.to > to) range.to = to;
511
+ if (range.from >= range.to) intact.splice(i--, 1);
512
+ else intactLines += range.to - range.from;
513
+ }
514
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
515
+ updateViewOffset(cm);
516
+ return;
517
+ }
518
+ intact.sort(function(a, b) {return a.from - b.from;});
519
+
520
+ // Avoid crashing on IE's "unspecified error" when in iframes
521
+ try {
522
+ var focused = document.activeElement;
523
+ } catch(e) {}
524
+ if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
525
+ patchDisplay(cm, from, to, intact, positionsChangedFrom);
526
+ display.lineDiv.style.display = "";
527
+ if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
528
+
529
+ var different = from != display.showingFrom || to != display.showingTo ||
530
+ display.lastSizeC != display.wrapper.clientHeight;
531
+ // This is just a bogus formula that detects when the editor is
532
+ // resized or the font size changes.
533
+ if (different) {
534
+ display.lastSizeC = display.wrapper.clientHeight;
535
+ startWorker(cm, 400);
536
+ }
537
+ display.showingFrom = from; display.showingTo = to;
538
+
539
+ updateHeightsInViewport(cm);
540
+ updateViewOffset(cm);
541
+
542
+ return true;
543
+ }
544
+
545
+ function updateHeightsInViewport(cm) {
546
+ var display = cm.display;
547
+ var prevBottom = display.lineDiv.offsetTop;
548
+ for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
549
+ if (ie_lt8) {
550
+ var bot = node.offsetTop + node.offsetHeight;
551
+ height = bot - prevBottom;
552
+ prevBottom = bot;
553
+ } else {
554
+ var box = getRect(node);
555
+ height = box.bottom - box.top;
556
+ }
557
+ var diff = node.lineObj.height - height;
558
+ if (height < 2) height = textHeight(display);
559
+ if (diff > .001 || diff < -.001) {
560
+ updateLineHeight(node.lineObj, height);
561
+ var widgets = node.lineObj.widgets;
562
+ if (widgets) for (var i = 0; i < widgets.length; ++i)
563
+ widgets[i].height = widgets[i].node.offsetHeight;
564
+ }
565
+ }
566
+ }
567
+
568
+ function updateViewOffset(cm) {
569
+ var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
570
+ // Position the mover div to align with the current virtual scroll position
571
+ cm.display.mover.style.top = off + "px";
572
+ }
573
+
574
+ function computeIntact(intact, changes) {
575
+ for (var i = 0, l = changes.length || 0; i < l; ++i) {
576
+ var change = changes[i], intact2 = [], diff = change.diff || 0;
577
+ for (var j = 0, l2 = intact.length; j < l2; ++j) {
578
+ var range = intact[j];
579
+ if (change.to <= range.from && change.diff) {
580
+ intact2.push({from: range.from + diff, to: range.to + diff});
581
+ } else if (change.to <= range.from || change.from >= range.to) {
582
+ intact2.push(range);
583
+ } else {
584
+ if (change.from > range.from)
585
+ intact2.push({from: range.from, to: change.from});
586
+ if (change.to < range.to)
587
+ intact2.push({from: change.to + diff, to: range.to + diff});
588
+ }
589
+ }
590
+ intact = intact2;
591
+ }
592
+ return intact;
593
+ }
594
+
595
+ function getDimensions(cm) {
596
+ var d = cm.display, left = {}, width = {};
597
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
598
+ left[cm.options.gutters[i]] = n.offsetLeft;
599
+ width[cm.options.gutters[i]] = n.offsetWidth;
600
+ }
601
+ return {fixedPos: compensateForHScroll(d),
602
+ gutterTotalWidth: d.gutters.offsetWidth,
603
+ gutterLeft: left,
604
+ gutterWidth: width,
605
+ wrapperWidth: d.wrapper.clientWidth};
606
+ }
607
+
608
+ function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
609
+ var dims = getDimensions(cm);
610
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
611
+ if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
612
+ removeChildren(display.lineDiv);
613
+ var container = display.lineDiv, cur = container.firstChild;
614
+
615
+ function rm(node) {
616
+ var next = node.nextSibling;
617
+ if (webkit && mac && cm.display.currentWheelTarget == node) {
618
+ node.style.display = "none";
619
+ node.lineObj = null;
620
+ } else {
621
+ node.parentNode.removeChild(node);
622
+ }
623
+ return next;
624
+ }
625
+
626
+ var nextIntact = intact.shift(), lineN = from;
627
+ cm.doc.iter(from, to, function(line) {
628
+ if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
629
+ if (lineIsHidden(cm.doc, line)) {
630
+ if (line.height != 0) updateLineHeight(line, 0);
631
+ if (line.widgets && cur && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
632
+ var w = line.widgets[i];
633
+ if (w.showIfHidden) {
634
+ var prev = cur.previousSibling;
635
+ if (/pre/i.test(prev.nodeName)) {
636
+ var wrap = elt("div", null, null, "position: relative");
637
+ prev.parentNode.replaceChild(wrap, prev);
638
+ wrap.appendChild(prev);
639
+ prev = wrap;
640
+ }
641
+ var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
642
+ if (!w.handleMouseEvents) wnode.ignoreEvents = true;
643
+ positionLineWidget(w, wnode, prev, dims);
644
+ }
645
+ }
646
+ } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
647
+ // This line is intact. Skip to the actual node. Update its
648
+ // line number if needed.
649
+ while (cur.lineObj != line) cur = rm(cur);
650
+ if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
651
+ setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
652
+ cur = cur.nextSibling;
653
+ } else {
654
+ // For lines with widgets, make an attempt to find and reuse
655
+ // the existing element, so that widgets aren't needlessly
656
+ // removed and re-inserted into the dom
657
+ if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
658
+ if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
659
+ // This line needs to be generated.
660
+ var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
661
+ if (lineNode != reuse) {
662
+ container.insertBefore(lineNode, cur);
663
+ } else {
664
+ while (cur != reuse) cur = rm(cur);
665
+ cur = cur.nextSibling;
666
+ }
667
+
668
+ lineNode.lineObj = line;
669
+ }
670
+ ++lineN;
671
+ });
672
+ while (cur) cur = rm(cur);
673
+ }
674
+
675
+ function buildLineElement(cm, line, lineNo, dims, reuse) {
676
+ var built = buildLineContent(cm, line), lineElement = built.pre;
677
+ var markers = line.gutterMarkers, display = cm.display, wrap;
678
+
679
+ var bgClass = built.bgClass ? built.bgClass + " " + (line.bgClass || "") : line.bgClass;
680
+ if (!cm.options.lineNumbers && !markers && !bgClass && !line.wrapClass && !line.widgets)
681
+ return lineElement;
682
+
683
+ // Lines with gutter elements, widgets or a background class need
684
+ // to be wrapped again, and have the extra elements added to the
685
+ // wrapper div
686
+
687
+ if (reuse) {
688
+ reuse.alignable = null;
689
+ var isOk = true, widgetsSeen = 0, insertBefore = null;
690
+ for (var n = reuse.firstChild, next; n; n = next) {
691
+ next = n.nextSibling;
692
+ if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
693
+ reuse.removeChild(n);
694
+ } else {
695
+ for (var i = 0; i < line.widgets.length; ++i) {
696
+ var widget = line.widgets[i];
697
+ if (widget.node == n.firstChild) {
698
+ if (!widget.above && !insertBefore) insertBefore = n;
699
+ positionLineWidget(widget, n, reuse, dims);
700
+ ++widgetsSeen;
701
+ break;
702
+ }
703
+ }
704
+ if (i == line.widgets.length) { isOk = false; break; }
705
+ }
706
+ }
707
+ reuse.insertBefore(lineElement, insertBefore);
708
+ if (isOk && widgetsSeen == line.widgets.length) {
709
+ wrap = reuse;
710
+ reuse.className = line.wrapClass || "";
711
+ }
712
+ }
713
+ if (!wrap) {
714
+ wrap = elt("div", null, line.wrapClass, "position: relative");
715
+ wrap.appendChild(lineElement);
716
+ }
717
+ // Kludge to make sure the styled element lies behind the selection (by z-index)
718
+ if (bgClass)
719
+ wrap.insertBefore(elt("div", null, bgClass + " CodeMirror-linebackground"), wrap.firstChild);
720
+ if (cm.options.lineNumbers || markers) {
721
+ var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
722
+ (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
723
+ wrap.firstChild);
724
+ if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
725
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
726
+ wrap.lineNumber = gutterWrap.appendChild(
727
+ elt("div", lineNumberFor(cm.options, lineNo),
728
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
729
+ "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
730
+ + display.lineNumInnerWidth + "px"));
731
+ if (markers)
732
+ for (var k = 0; k < cm.options.gutters.length; ++k) {
733
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
734
+ if (found)
735
+ gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
736
+ dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
737
+ }
738
+ }
739
+ if (ie_lt8) wrap.style.zIndex = 2;
740
+ if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
741
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
742
+ if (!widget.handleMouseEvents) node.ignoreEvents = true;
743
+ positionLineWidget(widget, node, wrap, dims);
744
+ if (widget.above)
745
+ wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
746
+ else
747
+ wrap.appendChild(node);
748
+ signalLater(widget, "redraw");
749
+ }
750
+ return wrap;
751
+ }
752
+
753
+ function positionLineWidget(widget, node, wrap, dims) {
754
+ if (widget.noHScroll) {
755
+ (wrap.alignable || (wrap.alignable = [])).push(node);
756
+ var width = dims.wrapperWidth;
757
+ node.style.left = dims.fixedPos + "px";
758
+ if (!widget.coverGutter) {
759
+ width -= dims.gutterTotalWidth;
760
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
761
+ }
762
+ node.style.width = width + "px";
763
+ }
764
+ if (widget.coverGutter) {
765
+ node.style.zIndex = 5;
766
+ node.style.position = "relative";
767
+ if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
768
+ }
769
+ }
770
+
771
+ // SELECTION / CURSOR
772
+
773
+ function updateSelection(cm) {
774
+ var display = cm.display;
775
+ var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
776
+ if (collapsed || cm.options.showCursorWhenSelecting)
777
+ updateSelectionCursor(cm);
778
+ else
779
+ display.cursor.style.display = display.otherCursor.style.display = "none";
780
+ if (!collapsed)
781
+ updateSelectionRange(cm);
782
+ else
783
+ display.selectionDiv.style.display = "none";
784
+
785
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
786
+ if (cm.options.moveInputWithCursor) {
787
+ var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
788
+ var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
789
+ display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
790
+ headPos.top + lineOff.top - wrapOff.top)) + "px";
791
+ display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
792
+ headPos.left + lineOff.left - wrapOff.left)) + "px";
793
+ }
794
+ }
795
+
796
+ // No selection, plain cursor
797
+ function updateSelectionCursor(cm) {
798
+ var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
799
+ display.cursor.style.left = pos.left + "px";
800
+ display.cursor.style.top = pos.top + "px";
801
+ display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
802
+ display.cursor.style.display = "";
803
+
804
+ if (pos.other) {
805
+ display.otherCursor.style.display = "";
806
+ display.otherCursor.style.left = pos.other.left + "px";
807
+ display.otherCursor.style.top = pos.other.top + "px";
808
+ display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
809
+ } else { display.otherCursor.style.display = "none"; }
810
+ }
811
+
812
+ // Highlight selection
813
+ function updateSelectionRange(cm) {
814
+ var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
815
+ var fragment = document.createDocumentFragment();
816
+ var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
817
+
818
+ function add(left, top, width, bottom) {
819
+ if (top < 0) top = 0;
820
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
821
+ "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
822
+ "px; height: " + (bottom - top) + "px"));
823
+ }
824
+
825
+ function drawForLine(line, fromArg, toArg) {
826
+ var lineObj = getLine(doc, line);
827
+ var lineLen = lineObj.text.length;
828
+ var start, end;
829
+ function coords(ch, bias) {
830
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
831
+ }
832
+
833
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
834
+ var leftPos = coords(from, "left"), rightPos, left, right;
835
+ if (from == to) {
836
+ rightPos = leftPos;
837
+ left = right = leftPos.left;
838
+ } else {
839
+ rightPos = coords(to - 1, "right");
840
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
841
+ left = leftPos.left;
842
+ right = rightPos.right;
843
+ }
844
+ if (fromArg == null && from == 0) left = pl;
845
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
846
+ add(left, leftPos.top, null, leftPos.bottom);
847
+ left = pl;
848
+ if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
849
+ }
850
+ if (toArg == null && to == lineLen) right = clientWidth;
851
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
852
+ start = leftPos;
853
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
854
+ end = rightPos;
855
+ if (left < pl + 1) left = pl;
856
+ add(left, rightPos.top, right - left, rightPos.bottom);
857
+ });
858
+ return {start: start, end: end};
859
+ }
860
+
861
+ if (sel.from.line == sel.to.line) {
862
+ drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
863
+ } else {
864
+ var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
865
+ var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
866
+ var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
867
+ var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
868
+ if (singleVLine) {
869
+ if (leftEnd.top < rightStart.top - 2) {
870
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
871
+ add(pl, rightStart.top, rightStart.left, rightStart.bottom);
872
+ } else {
873
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
874
+ }
875
+ }
876
+ if (leftEnd.bottom < rightStart.top)
877
+ add(pl, leftEnd.bottom, null, rightStart.top);
878
+ }
879
+
880
+ removeChildrenAndAdd(display.selectionDiv, fragment);
881
+ display.selectionDiv.style.display = "";
882
+ }
883
+
884
+ // Cursor-blinking
885
+ function restartBlink(cm) {
886
+ if (!cm.state.focused) return;
887
+ var display = cm.display;
888
+ clearInterval(display.blinker);
889
+ var on = true;
890
+ display.cursor.style.visibility = display.otherCursor.style.visibility = "";
891
+ if (cm.options.cursorBlinkRate > 0)
892
+ display.blinker = setInterval(function() {
893
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
894
+ }, cm.options.cursorBlinkRate);
895
+ }
896
+
897
+ // HIGHLIGHT WORKER
898
+
899
+ function startWorker(cm, time) {
900
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
901
+ cm.state.highlight.set(time, bind(highlightWorker, cm));
902
+ }
903
+
904
+ function highlightWorker(cm) {
905
+ var doc = cm.doc;
906
+ if (doc.frontier < doc.first) doc.frontier = doc.first;
907
+ if (doc.frontier >= cm.display.showingTo) return;
908
+ var end = +new Date + cm.options.workTime;
909
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
910
+ var changed = [], prevChange;
911
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
912
+ if (doc.frontier >= cm.display.showingFrom) { // Visible
913
+ var oldStyles = line.styles;
914
+ line.styles = highlightLine(cm, line, state);
915
+ var ischange = !oldStyles || oldStyles.length != line.styles.length;
916
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
917
+ if (ischange) {
918
+ if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
919
+ else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
920
+ }
921
+ line.stateAfter = copyState(doc.mode, state);
922
+ } else {
923
+ processLine(cm, line, state);
924
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
925
+ }
926
+ ++doc.frontier;
927
+ if (+new Date > end) {
928
+ startWorker(cm, cm.options.workDelay);
929
+ return true;
930
+ }
931
+ });
932
+ if (changed.length)
933
+ operation(cm, function() {
934
+ for (var i = 0; i < changed.length; ++i)
935
+ regChange(this, changed[i].start, changed[i].end);
936
+ })();
937
+ }
938
+
939
+ // Finds the line to start with when starting a parse. Tries to
940
+ // find a line with a stateAfter, so that it can start with a
941
+ // valid state. If that fails, it returns the line with the
942
+ // smallest indentation, which tends to need the least context to
943
+ // parse correctly.
944
+ function findStartLine(cm, n, precise) {
945
+ var minindent, minline, doc = cm.doc;
946
+ var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
947
+ for (var search = n; search > lim; --search) {
948
+ if (search <= doc.first) return doc.first;
949
+ var line = getLine(doc, search - 1);
950
+ if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
951
+ var indented = countColumn(line.text, null, cm.options.tabSize);
952
+ if (minline == null || minindent > indented) {
953
+ minline = search - 1;
954
+ minindent = indented;
955
+ }
956
+ }
957
+ return minline;
958
+ }
959
+
960
+ function getStateBefore(cm, n, precise) {
961
+ var doc = cm.doc, display = cm.display;
962
+ if (!doc.mode.startState) return true;
963
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
964
+ if (!state) state = startState(doc.mode);
965
+ else state = copyState(doc.mode, state);
966
+ doc.iter(pos, n, function(line) {
967
+ processLine(cm, line, state);
968
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
969
+ line.stateAfter = save ? copyState(doc.mode, state) : null;
970
+ ++pos;
971
+ });
972
+ if (precise) doc.frontier = pos;
973
+ return state;
974
+ }
975
+
976
+ // POSITION MEASUREMENT
977
+
978
+ function paddingTop(display) {return display.lineSpace.offsetTop;}
979
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
980
+ function paddingLeft(display) {
981
+ var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
982
+ return e.offsetLeft;
983
+ }
984
+
985
+ function measureChar(cm, line, ch, data, bias) {
986
+ var dir = -1;
987
+ data = data || measureLine(cm, line);
988
+ if (data.crude) {
989
+ var left = data.left + ch * data.width;
990
+ return {left: left, right: left + data.width, top: data.top, bottom: data.bottom};
991
+ }
992
+
993
+ for (var pos = ch;; pos += dir) {
994
+ var r = data[pos];
995
+ if (r) break;
996
+ if (dir < 0 && pos == 0) dir = 1;
997
+ }
998
+ bias = pos > ch ? "left" : pos < ch ? "right" : bias;
999
+ if (bias == "left" && r.leftSide) r = r.leftSide;
1000
+ else if (bias == "right" && r.rightSide) r = r.rightSide;
1001
+ return {left: pos < ch ? r.right : r.left,
1002
+ right: pos > ch ? r.left : r.right,
1003
+ top: r.top,
1004
+ bottom: r.bottom};
1005
+ }
1006
+
1007
+ function findCachedMeasurement(cm, line) {
1008
+ var cache = cm.display.measureLineCache;
1009
+ for (var i = 0; i < cache.length; ++i) {
1010
+ var memo = cache[i];
1011
+ if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
1012
+ cm.display.scroller.clientWidth == memo.width &&
1013
+ memo.classes == line.textClass + "|" + line.wrapClass)
1014
+ return memo;
1015
+ }
1016
+ }
1017
+
1018
+ function clearCachedMeasurement(cm, line) {
1019
+ var exists = findCachedMeasurement(cm, line);
1020
+ if (exists) exists.text = exists.measure = exists.markedSpans = null;
1021
+ }
1022
+
1023
+ function measureLine(cm, line) {
1024
+ // First look in the cache
1025
+ var cached = findCachedMeasurement(cm, line);
1026
+ if (cached) return cached.measure;
1027
+
1028
+ // Failing that, recompute and store result in cache
1029
+ var measure = measureLineInner(cm, line);
1030
+ var cache = cm.display.measureLineCache;
1031
+ var memo = {text: line.text, width: cm.display.scroller.clientWidth,
1032
+ markedSpans: line.markedSpans, measure: measure,
1033
+ classes: line.textClass + "|" + line.wrapClass};
1034
+ if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
1035
+ else cache.push(memo);
1036
+ return measure;
1037
+ }
1038
+
1039
+ function measureLineInner(cm, line) {
1040
+ if (!cm.options.lineWrapping && line.text.length >= cm.options.crudeMeasuringFrom)
1041
+ return crudelyMeasureLine(cm, line);
1042
+
1043
+ var display = cm.display, measure = emptyArray(line.text.length);
1044
+ var pre = buildLineContent(cm, line, measure, true).pre;
1045
+
1046
+ // IE does not cache element positions of inline elements between
1047
+ // calls to getBoundingClientRect. This makes the loop below,
1048
+ // which gathers the positions of all the characters on the line,
1049
+ // do an amount of layout work quadratic to the number of
1050
+ // characters. When line wrapping is off, we try to improve things
1051
+ // by first subdividing the line into a bunch of inline blocks, so
1052
+ // that IE can reuse most of the layout information from caches
1053
+ // for those blocks. This does interfere with line wrapping, so it
1054
+ // doesn't work when wrapping is on, but in that case the
1055
+ // situation is slightly better, since IE does cache line-wrapping
1056
+ // information and only recomputes per-line.
1057
+ if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1058
+ var fragment = document.createDocumentFragment();
1059
+ var chunk = 10, n = pre.childNodes.length;
1060
+ for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
1061
+ var wrap = elt("div", null, null, "display: inline-block");
1062
+ for (var j = 0; j < chunk && n; ++j) {
1063
+ wrap.appendChild(pre.firstChild);
1064
+ --n;
1065
+ }
1066
+ fragment.appendChild(wrap);
1067
+ }
1068
+ pre.appendChild(fragment);
1069
+ }
1070
+
1071
+ removeChildrenAndAdd(display.measure, pre);
1072
+
1073
+ var outer = getRect(display.lineDiv);
1074
+ var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
1075
+ // Work around an IE7/8 bug where it will sometimes have randomly
1076
+ // replaced our pre with a clone at this point.
1077
+ if (ie_lt9 && display.measure.first != pre)
1078
+ removeChildrenAndAdd(display.measure, pre);
1079
+
1080
+ function measureRect(rect) {
1081
+ var top = rect.top - outer.top, bot = rect.bottom - outer.top;
1082
+ if (bot > maxBot) bot = maxBot;
1083
+ if (top < 0) top = 0;
1084
+ for (var i = vranges.length - 2; i >= 0; i -= 2) {
1085
+ var rtop = vranges[i], rbot = vranges[i+1];
1086
+ if (rtop > bot || rbot < top) continue;
1087
+ if (rtop <= top && rbot >= bot ||
1088
+ top <= rtop && bot >= rbot ||
1089
+ Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1090
+ vranges[i] = Math.min(top, rtop);
1091
+ vranges[i+1] = Math.max(bot, rbot);
1092
+ break;
1093
+ }
1094
+ }
1095
+ if (i < 0) { i = vranges.length; vranges.push(top, bot); }
1096
+ return {left: rect.left - outer.left,
1097
+ right: rect.right - outer.left,
1098
+ top: i, bottom: null};
1099
+ }
1100
+ function finishRect(rect) {
1101
+ rect.bottom = vranges[rect.top+1];
1102
+ rect.top = vranges[rect.top];
1103
+ }
1104
+
1105
+ for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1106
+ var node = cur, rect = null;
1107
+ // A widget might wrap, needs special care
1108
+ if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1109
+ if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1110
+ var rects = node.getClientRects();
1111
+ if (rects.length > 1) {
1112
+ rect = data[i] = measureRect(rects[0]);
1113
+ rect.rightSide = measureRect(rects[rects.length - 1]);
1114
+ }
1115
+ }
1116
+ if (!rect) rect = data[i] = measureRect(getRect(node));
1117
+ if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1118
+ if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
1119
+ }
1120
+ removeChildren(cm.display.measure);
1121
+ for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1122
+ finishRect(cur);
1123
+ if (cur.leftSide) finishRect(cur.leftSide);
1124
+ if (cur.rightSide) finishRect(cur.rightSide);
1125
+ }
1126
+ return data;
1127
+ }
1128
+
1129
+ function crudelyMeasureLine(cm, line) {
1130
+ var copy = new Line(line.text.slice(0, 100), null);
1131
+ if (line.textClass) copy.textClass = line.textClass;
1132
+ var measure = measureLineInner(cm, copy);
1133
+ var left = measureChar(cm, copy, 0, measure, "left");
1134
+ var right = measureChar(cm, copy, 99, measure, "right");
1135
+ return {crude: true, top: left.top, left: left.left, bottom: left.bottom, width: (right.right - left.left) / 100};
1136
+ }
1137
+
1138
+ function measureLineWidth(cm, line) {
1139
+ var hasBadSpan = false;
1140
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
1141
+ var sp = line.markedSpans[i];
1142
+ if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1143
+ }
1144
+ var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1145
+ if (cached || line.text.length >= cm.options.crudeMeasuringFrom)
1146
+ return measureChar(cm, line, line.text.length, cached && cached.measure, "right").right;
1147
+
1148
+ var pre = buildLineContent(cm, line, null, true).pre;
1149
+ var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1150
+ removeChildrenAndAdd(cm.display.measure, pre);
1151
+ return getRect(end).right - getRect(cm.display.lineDiv).left;
1152
+ }
1153
+
1154
+ function clearCaches(cm) {
1155
+ cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
1156
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
1157
+ if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
1158
+ cm.display.lineNumChars = null;
1159
+ }
1160
+
1161
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
1162
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
1163
+
1164
+ // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1165
+ function intoCoordSystem(cm, lineObj, rect, context) {
1166
+ if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
1167
+ var size = widgetHeight(lineObj.widgets[i]);
1168
+ rect.top += size; rect.bottom += size;
1169
+ }
1170
+ if (context == "line") return rect;
1171
+ if (!context) context = "local";
1172
+ var yOff = heightAtLine(cm, lineObj);
1173
+ if (context == "local") yOff += paddingTop(cm.display);
1174
+ else yOff -= cm.display.viewOffset;
1175
+ if (context == "page" || context == "window") {
1176
+ var lOff = getRect(cm.display.lineSpace);
1177
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
1178
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
1179
+ rect.left += xOff; rect.right += xOff;
1180
+ }
1181
+ rect.top += yOff; rect.bottom += yOff;
1182
+ return rect;
1183
+ }
1184
+
1185
+ // Context may be "window", "page", "div", or "local"/null
1186
+ // Result is in "div" coords
1187
+ function fromCoordSystem(cm, coords, context) {
1188
+ if (context == "div") return coords;
1189
+ var left = coords.left, top = coords.top;
1190
+ // First move into "page" coordinate system
1191
+ if (context == "page") {
1192
+ left -= pageScrollX();
1193
+ top -= pageScrollY();
1194
+ } else if (context == "local" || !context) {
1195
+ var localBox = getRect(cm.display.sizer);
1196
+ left += localBox.left;
1197
+ top += localBox.top;
1198
+ }
1199
+
1200
+ var lineSpaceBox = getRect(cm.display.lineSpace);
1201
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1202
+ }
1203
+
1204
+ function charCoords(cm, pos, context, lineObj, bias) {
1205
+ if (!lineObj) lineObj = getLine(cm.doc, pos.line);
1206
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
1207
+ }
1208
+
1209
+ function cursorCoords(cm, pos, context, lineObj, measurement) {
1210
+ lineObj = lineObj || getLine(cm.doc, pos.line);
1211
+ if (!measurement) measurement = measureLine(cm, lineObj);
1212
+ function get(ch, right) {
1213
+ var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
1214
+ if (right) m.left = m.right; else m.right = m.left;
1215
+ return intoCoordSystem(cm, lineObj, m, context);
1216
+ }
1217
+ function getBidi(ch, partPos) {
1218
+ var part = order[partPos], right = part.level % 2;
1219
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
1220
+ part = order[--partPos];
1221
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
1222
+ right = true;
1223
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
1224
+ part = order[++partPos];
1225
+ ch = bidiLeft(part) - part.level % 2;
1226
+ right = false;
1227
+ }
1228
+ if (right && ch == part.to && ch > part.from) return get(ch - 1);
1229
+ return get(ch, right);
1230
+ }
1231
+ var order = getOrder(lineObj), ch = pos.ch;
1232
+ if (!order) return get(ch);
1233
+ var partPos = getBidiPartAt(order, ch);
1234
+ var val = getBidi(ch, partPos);
1235
+ if (bidiOther != null) val.other = getBidi(ch, bidiOther);
1236
+ return val;
1237
+ }
1238
+
1239
+ function PosWithInfo(line, ch, outside, xRel) {
1240
+ var pos = new Pos(line, ch);
1241
+ pos.xRel = xRel;
1242
+ if (outside) pos.outside = true;
1243
+ return pos;
1244
+ }
1245
+
1246
+ // Coords must be lineSpace-local
1247
+ function coordsChar(cm, x, y) {
1248
+ var doc = cm.doc;
1249
+ y += cm.display.viewOffset;
1250
+ if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
1251
+ var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1252
+ if (lineNo > last)
1253
+ return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
1254
+ if (x < 0) x = 0;
1255
+
1256
+ for (;;) {
1257
+ var lineObj = getLine(doc, lineNo);
1258
+ var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1259
+ var merged = collapsedSpanAtEnd(lineObj);
1260
+ var mergedPos = merged && merged.find();
1261
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
1262
+ lineNo = mergedPos.to.line;
1263
+ else
1264
+ return found;
1265
+ }
1266
+ }
1267
+
1268
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
1269
+ var innerOff = y - heightAtLine(cm, lineObj);
1270
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
1271
+ var measurement = measureLine(cm, lineObj);
1272
+
1273
+ function getX(ch) {
1274
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
1275
+ lineObj, measurement);
1276
+ wrongLine = true;
1277
+ if (innerOff > sp.bottom) return sp.left - adjust;
1278
+ else if (innerOff < sp.top) return sp.left + adjust;
1279
+ else wrongLine = false;
1280
+ return sp.left;
1281
+ }
1282
+
1283
+ var bidi = getOrder(lineObj), dist = lineObj.text.length;
1284
+ var from = lineLeft(lineObj), to = lineRight(lineObj);
1285
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1286
+
1287
+ if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
1288
+ // Do a binary search between these bounds.
1289
+ for (;;) {
1290
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1291
+ var ch = x < fromX || x - fromX <= toX - x ? from : to;
1292
+ var xDiff = x - (ch == from ? fromX : toX);
1293
+ while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1294
+ var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1295
+ xDiff < 0 ? -1 : xDiff ? 1 : 0);
1296
+ return pos;
1297
+ }
1298
+ var step = Math.ceil(dist / 2), middle = from + step;
1299
+ if (bidi) {
1300
+ middle = from;
1301
+ for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
1302
+ }
1303
+ var middleX = getX(middle);
1304
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
1305
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
1306
+ }
1307
+ }
1308
+
1309
+ var measureText;
1310
+ function textHeight(display) {
1311
+ if (display.cachedTextHeight != null) return display.cachedTextHeight;
1312
+ if (measureText == null) {
1313
+ measureText = elt("pre");
1314
+ // Measure a bunch of lines, for browsers that compute
1315
+ // fractional heights.
1316
+ for (var i = 0; i < 49; ++i) {
1317
+ measureText.appendChild(document.createTextNode("x"));
1318
+ measureText.appendChild(elt("br"));
1319
+ }
1320
+ measureText.appendChild(document.createTextNode("x"));
1321
+ }
1322
+ removeChildrenAndAdd(display.measure, measureText);
1323
+ var height = measureText.offsetHeight / 50;
1324
+ if (height > 3) display.cachedTextHeight = height;
1325
+ removeChildren(display.measure);
1326
+ return height || 1;
1327
+ }
1328
+
1329
+ function charWidth(display) {
1330
+ if (display.cachedCharWidth != null) return display.cachedCharWidth;
1331
+ var anchor = elt("span", "x");
1332
+ var pre = elt("pre", [anchor]);
1333
+ removeChildrenAndAdd(display.measure, pre);
1334
+ var width = anchor.offsetWidth;
1335
+ if (width > 2) display.cachedCharWidth = width;
1336
+ return width || 10;
1337
+ }
1338
+
1339
+ // OPERATIONS
1340
+
1341
+ // Operations are used to wrap changes in such a way that each
1342
+ // change won't have to update the cursor and display (which would
1343
+ // be awkward, slow, and error-prone), but instead updates are
1344
+ // batched and then all combined and executed at once.
1345
+
1346
+ var nextOpId = 0;
1347
+ function startOperation(cm) {
1348
+ cm.curOp = {
1349
+ // An array of ranges of lines that have to be updated. See
1350
+ // updateDisplay.
1351
+ changes: [],
1352
+ forceUpdate: false,
1353
+ updateInput: null,
1354
+ userSelChange: null,
1355
+ textChanged: null,
1356
+ selectionChanged: false,
1357
+ cursorActivity: false,
1358
+ updateMaxLine: false,
1359
+ updateScrollPos: false,
1360
+ id: ++nextOpId
1361
+ };
1362
+ if (!delayedCallbackDepth++) delayedCallbacks = [];
1363
+ }
1364
+
1365
+ function endOperation(cm) {
1366
+ var op = cm.curOp, doc = cm.doc, display = cm.display;
1367
+ cm.curOp = null;
1368
+
1369
+ if (op.updateMaxLine) computeMaxLength(cm);
1370
+ if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
1371
+ var width = measureLineWidth(cm, display.maxLine);
1372
+ display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
1373
+ display.maxLineChanged = false;
1374
+ var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
1375
+ if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
1376
+ setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
1377
+ }
1378
+ var newScrollPos, updated;
1379
+ if (op.updateScrollPos) {
1380
+ newScrollPos = op.updateScrollPos;
1381
+ } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
1382
+ var coords = cursorCoords(cm, doc.sel.head);
1383
+ newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
1384
+ }
1385
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
1386
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
1387
+ if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
1388
+ }
1389
+ if (!updated && op.selectionChanged) updateSelection(cm);
1390
+ if (op.updateScrollPos) {
1391
+ display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
1392
+ display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
1393
+ alignHorizontally(cm);
1394
+ if (op.scrollToPos)
1395
+ scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),
1396
+ clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);
1397
+ } else if (newScrollPos) {
1398
+ scrollCursorIntoView(cm);
1399
+ }
1400
+ if (op.selectionChanged) restartBlink(cm);
1401
+
1402
+ if (cm.state.focused && op.updateInput)
1403
+ resetInput(cm, op.userSelChange);
1404
+
1405
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
1406
+ if (hidden) for (var i = 0; i < hidden.length; ++i)
1407
+ if (!hidden[i].lines.length) signal(hidden[i], "hide");
1408
+ if (unhidden) for (var i = 0; i < unhidden.length; ++i)
1409
+ if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
1410
+
1411
+ var delayed;
1412
+ if (!--delayedCallbackDepth) {
1413
+ delayed = delayedCallbacks;
1414
+ delayedCallbacks = null;
1415
+ }
1416
+ if (op.textChanged)
1417
+ signal(cm, "change", cm, op.textChanged);
1418
+ if (op.cursorActivity) signal(cm, "cursorActivity", cm);
1419
+ if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
1420
+ }
1421
+
1422
+ // Wraps a function in an operation. Returns the wrapped function.
1423
+ function operation(cm1, f) {
1424
+ return function() {
1425
+ var cm = cm1 || this, withOp = !cm.curOp;
1426
+ if (withOp) startOperation(cm);
1427
+ try { var result = f.apply(cm, arguments); }
1428
+ finally { if (withOp) endOperation(cm); }
1429
+ return result;
1430
+ };
1431
+ }
1432
+ function docOperation(f) {
1433
+ return function() {
1434
+ var withOp = this.cm && !this.cm.curOp, result;
1435
+ if (withOp) startOperation(this.cm);
1436
+ try { result = f.apply(this, arguments); }
1437
+ finally { if (withOp) endOperation(this.cm); }
1438
+ return result;
1439
+ };
1440
+ }
1441
+ function runInOp(cm, f) {
1442
+ var withOp = !cm.curOp, result;
1443
+ if (withOp) startOperation(cm);
1444
+ try { result = f(); }
1445
+ finally { if (withOp) endOperation(cm); }
1446
+ return result;
1447
+ }
1448
+
1449
+ function regChange(cm, from, to, lendiff) {
1450
+ if (from == null) from = cm.doc.first;
1451
+ if (to == null) to = cm.doc.first + cm.doc.size;
1452
+ cm.curOp.changes.push({from: from, to: to, diff: lendiff});
1453
+ }
1454
+
1455
+ // INPUT HANDLING
1456
+
1457
+ function slowPoll(cm) {
1458
+ if (cm.display.pollingFast) return;
1459
+ cm.display.poll.set(cm.options.pollInterval, function() {
1460
+ readInput(cm);
1461
+ if (cm.state.focused) slowPoll(cm);
1462
+ });
1463
+ }
1464
+
1465
+ function fastPoll(cm) {
1466
+ var missed = false;
1467
+ cm.display.pollingFast = true;
1468
+ function p() {
1469
+ var changed = readInput(cm);
1470
+ if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
1471
+ else {cm.display.pollingFast = false; slowPoll(cm);}
1472
+ }
1473
+ cm.display.poll.set(20, p);
1474
+ }
1475
+
1476
+ // prevInput is a hack to work with IME. If we reset the textarea
1477
+ // on every change, that breaks IME. So we look for changes
1478
+ // compared to the previous content instead. (Modern browsers have
1479
+ // events that indicate IME taking place, but these are not widely
1480
+ // supported or compatible enough yet to rely on.)
1481
+ function readInput(cm) {
1482
+ var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1483
+ if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1484
+ if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
1485
+ input.value = input.value.substring(0, input.value.length - 1);
1486
+ cm.state.fakedLastChar = false;
1487
+ }
1488
+ var text = input.value;
1489
+ if (text == prevInput && posEq(sel.from, sel.to)) return false;
1490
+ if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
1491
+ resetInput(cm, true);
1492
+ return false;
1493
+ }
1494
+
1495
+ var withOp = !cm.curOp;
1496
+ if (withOp) startOperation(cm);
1497
+ sel.shift = false;
1498
+ var same = 0, l = Math.min(prevInput.length, text.length);
1499
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1500
+ var from = sel.from, to = sel.to;
1501
+ if (same < prevInput.length)
1502
+ from = Pos(from.line, from.ch - (prevInput.length - same));
1503
+ else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1504
+ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1505
+
1506
+ var updateInput = cm.curOp.updateInput;
1507
+ var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1508
+ origin: cm.state.pasteIncoming ? "paste" : "+input"};
1509
+ makeChange(cm.doc, changeEvent, "end");
1510
+ cm.curOp.updateInput = updateInput;
1511
+ signalLater(cm, "inputRead", cm, changeEvent);
1512
+
1513
+ if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1514
+ else cm.display.prevInput = text;
1515
+ if (withOp) endOperation(cm);
1516
+ cm.state.pasteIncoming = false;
1517
+ return true;
1518
+ }
1519
+
1520
+ function resetInput(cm, user) {
1521
+ var minimal, selected, doc = cm.doc;
1522
+ if (!posEq(doc.sel.from, doc.sel.to)) {
1523
+ cm.display.prevInput = "";
1524
+ minimal = hasCopyEvent &&
1525
+ (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
1526
+ var content = minimal ? "-" : selected || cm.getSelection();
1527
+ cm.display.input.value = content;
1528
+ if (cm.state.focused) selectInput(cm.display.input);
1529
+ if (ie && !ie_lt9) cm.display.inputHasSelection = content;
1530
+ } else if (user) {
1531
+ cm.display.prevInput = cm.display.input.value = "";
1532
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
1533
+ }
1534
+ cm.display.inaccurateSelection = minimal;
1535
+ }
1536
+
1537
+ function focusInput(cm) {
1538
+ if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
1539
+ cm.display.input.focus();
1540
+ }
1541
+
1542
+ function isReadOnly(cm) {
1543
+ return cm.options.readOnly || cm.doc.cantEdit;
1544
+ }
1545
+
1546
+ // EVENT HANDLERS
1547
+
1548
+ function registerEventHandlers(cm) {
1549
+ var d = cm.display;
1550
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
1551
+ if (ie)
1552
+ on(d.scroller, "dblclick", operation(cm, function(e) {
1553
+ if (signalDOMEvent(cm, e)) return;
1554
+ var pos = posFromMouse(cm, e);
1555
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1556
+ e_preventDefault(e);
1557
+ var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
1558
+ extendSelection(cm.doc, word.from, word.to);
1559
+ }));
1560
+ else
1561
+ on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
1562
+ on(d.lineSpace, "selectstart", function(e) {
1563
+ if (!eventInWidget(d, e)) e_preventDefault(e);
1564
+ });
1565
+ // Gecko browsers fire contextmenu *after* opening the menu, at
1566
+ // which point we can't mess with it anymore. Context menu is
1567
+ // handled in onMouseDown for Gecko.
1568
+ if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
1569
+
1570
+ on(d.scroller, "scroll", function() {
1571
+ if (d.scroller.clientHeight) {
1572
+ setScrollTop(cm, d.scroller.scrollTop);
1573
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
1574
+ signal(cm, "scroll", cm);
1575
+ }
1576
+ });
1577
+ on(d.scrollbarV, "scroll", function() {
1578
+ if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
1579
+ });
1580
+ on(d.scrollbarH, "scroll", function() {
1581
+ if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
1582
+ });
1583
+
1584
+ on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
1585
+ on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
1586
+
1587
+ function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
1588
+ on(d.scrollbarH, "mousedown", reFocus);
1589
+ on(d.scrollbarV, "mousedown", reFocus);
1590
+ // Prevent wrapper from ever scrolling
1591
+ on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1592
+
1593
+ var resizeTimer;
1594
+ function onResize() {
1595
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
1596
+ resizeTimer = null;
1597
+ // Might be a text scaling operation, clear size caches.
1598
+ d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
1599
+ clearCaches(cm);
1600
+ runInOp(cm, bind(regChange, cm));
1601
+ }, 100);
1602
+ }
1603
+ on(window, "resize", onResize);
1604
+ // Above handler holds on to the editor and its data structures.
1605
+ // Here we poll to unregister it when the editor is no longer in
1606
+ // the document, so that it can be garbage-collected.
1607
+ function unregister() {
1608
+ for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
1609
+ if (p) setTimeout(unregister, 5000);
1610
+ else off(window, "resize", onResize);
1611
+ }
1612
+ setTimeout(unregister, 5000);
1613
+
1614
+ on(d.input, "keyup", operation(cm, function(e) {
1615
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1616
+ if (e.keyCode == 16) cm.doc.sel.shift = false;
1617
+ }));
1618
+ on(d.input, "input", function() {
1619
+ if (ie && !ie_lt9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
1620
+ fastPoll(cm);
1621
+ });
1622
+ on(d.input, "keydown", operation(cm, onKeyDown));
1623
+ on(d.input, "keypress", operation(cm, onKeyPress));
1624
+ on(d.input, "focus", bind(onFocus, cm));
1625
+ on(d.input, "blur", bind(onBlur, cm));
1626
+
1627
+ function drag_(e) {
1628
+ if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
1629
+ e_stop(e);
1630
+ }
1631
+ if (cm.options.dragDrop) {
1632
+ on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
1633
+ on(d.scroller, "dragenter", drag_);
1634
+ on(d.scroller, "dragover", drag_);
1635
+ on(d.scroller, "drop", operation(cm, onDrop));
1636
+ }
1637
+ on(d.scroller, "paste", function(e) {
1638
+ if (eventInWidget(d, e)) return;
1639
+ focusInput(cm);
1640
+ fastPoll(cm);
1641
+ });
1642
+ on(d.input, "paste", function() {
1643
+ // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
1644
+ // Add a char to the end of textarea before paste occur so that
1645
+ // selection doesn't span to the end of textarea.
1646
+ if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
1647
+ var start = d.input.selectionStart, end = d.input.selectionEnd;
1648
+ d.input.value += "$";
1649
+ d.input.selectionStart = start;
1650
+ d.input.selectionEnd = end;
1651
+ cm.state.fakedLastChar = true;
1652
+ }
1653
+ cm.state.pasteIncoming = true;
1654
+ fastPoll(cm);
1655
+ });
1656
+
1657
+ function prepareCopy() {
1658
+ if (d.inaccurateSelection) {
1659
+ d.prevInput = "";
1660
+ d.inaccurateSelection = false;
1661
+ d.input.value = cm.getSelection();
1662
+ selectInput(d.input);
1663
+ }
1664
+ }
1665
+ on(d.input, "cut", prepareCopy);
1666
+ on(d.input, "copy", prepareCopy);
1667
+
1668
+ // Needed to handle Tab key in KHTML
1669
+ if (khtml) on(d.sizer, "mouseup", function() {
1670
+ if (document.activeElement == d.input) d.input.blur();
1671
+ focusInput(cm);
1672
+ });
1673
+ }
1674
+
1675
+ function eventInWidget(display, e) {
1676
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1677
+ if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1678
+ }
1679
+ }
1680
+
1681
+ function posFromMouse(cm, e, liberal) {
1682
+ var display = cm.display;
1683
+ if (!liberal) {
1684
+ var target = e_target(e);
1685
+ if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1686
+ target == display.scrollbarV || target == display.scrollbarV.firstChild ||
1687
+ target == display.scrollbarFiller || target == display.gutterFiller) return null;
1688
+ }
1689
+ var x, y, space = getRect(display.lineSpace);
1690
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1691
+ try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
1692
+ return coordsChar(cm, x - space.left, y - space.top);
1693
+ }
1694
+
1695
+ var lastClick, lastDoubleClick;
1696
+ function onMouseDown(e) {
1697
+ if (signalDOMEvent(this, e)) return;
1698
+ var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1699
+ sel.shift = e.shiftKey;
1700
+
1701
+ if (eventInWidget(display, e)) {
1702
+ if (!webkit) {
1703
+ display.scroller.draggable = false;
1704
+ setTimeout(function(){display.scroller.draggable = true;}, 100);
1705
+ }
1706
+ return;
1707
+ }
1708
+ if (clickInGutter(cm, e)) return;
1709
+ var start = posFromMouse(cm, e);
1710
+
1711
+ switch (e_button(e)) {
1712
+ case 3:
1713
+ if (captureMiddleClick) onContextMenu.call(cm, cm, e);
1714
+ return;
1715
+ case 2:
1716
+ if (webkit) cm.state.lastMiddleDown = +new Date;
1717
+ if (start) extendSelection(cm.doc, start);
1718
+ setTimeout(bind(focusInput, cm), 20);
1719
+ e_preventDefault(e);
1720
+ return;
1721
+ }
1722
+ // For button 1, if it was clicked inside the editor
1723
+ // (posFromMouse returning non-null), we have to adjust the
1724
+ // selection.
1725
+ if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
1726
+
1727
+ if (!cm.state.focused) onFocus(cm);
1728
+
1729
+ var now = +new Date, type = "single";
1730
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
1731
+ type = "triple";
1732
+ e_preventDefault(e);
1733
+ setTimeout(bind(focusInput, cm), 20);
1734
+ selectLine(cm, start.line);
1735
+ } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
1736
+ type = "double";
1737
+ lastDoubleClick = {time: now, pos: start};
1738
+ e_preventDefault(e);
1739
+ var word = findWordAt(getLine(doc, start.line).text, start);
1740
+ extendSelection(cm.doc, word.from, word.to);
1741
+ } else { lastClick = {time: now, pos: start}; }
1742
+
1743
+ var last = start;
1744
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
1745
+ !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
1746
+ var dragEnd = operation(cm, function(e2) {
1747
+ if (webkit) display.scroller.draggable = false;
1748
+ cm.state.draggingText = false;
1749
+ off(document, "mouseup", dragEnd);
1750
+ off(display.scroller, "drop", dragEnd);
1751
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
1752
+ e_preventDefault(e2);
1753
+ extendSelection(cm.doc, start);
1754
+ focusInput(cm);
1755
+ }
1756
+ });
1757
+ // Let the drag handler handle this.
1758
+ if (webkit) display.scroller.draggable = true;
1759
+ cm.state.draggingText = dragEnd;
1760
+ // IE's approach to draggable
1761
+ if (display.scroller.dragDrop) display.scroller.dragDrop();
1762
+ on(document, "mouseup", dragEnd);
1763
+ on(display.scroller, "drop", dragEnd);
1764
+ return;
1765
+ }
1766
+ e_preventDefault(e);
1767
+ if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
1768
+
1769
+ var startstart = sel.from, startend = sel.to, lastPos = start;
1770
+
1771
+ function doSelect(cur) {
1772
+ if (posEq(lastPos, cur)) return;
1773
+ lastPos = cur;
1774
+
1775
+ if (type == "single") {
1776
+ extendSelection(cm.doc, clipPos(doc, start), cur);
1777
+ return;
1778
+ }
1779
+
1780
+ startstart = clipPos(doc, startstart);
1781
+ startend = clipPos(doc, startend);
1782
+ if (type == "double") {
1783
+ var word = findWordAt(getLine(doc, cur.line).text, cur);
1784
+ if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
1785
+ else extendSelection(cm.doc, startstart, word.to);
1786
+ } else if (type == "triple") {
1787
+ if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
1788
+ else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
1789
+ }
1790
+ }
1791
+
1792
+ var editorSize = getRect(display.wrapper);
1793
+ // Used to ensure timeout re-tries don't fire when another extend
1794
+ // happened in the meantime (clearTimeout isn't reliable -- at
1795
+ // least on Chrome, the timeouts still happen even when cleared,
1796
+ // if the clear happens after their scheduled firing time).
1797
+ var counter = 0;
1798
+
1799
+ function extend(e) {
1800
+ var curCount = ++counter;
1801
+ var cur = posFromMouse(cm, e, true);
1802
+ if (!cur) return;
1803
+ if (!posEq(cur, last)) {
1804
+ if (!cm.state.focused) onFocus(cm);
1805
+ last = cur;
1806
+ doSelect(cur);
1807
+ var visible = visibleLines(display, doc);
1808
+ if (cur.line >= visible.to || cur.line < visible.from)
1809
+ setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
1810
+ } else {
1811
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
1812
+ if (outside) setTimeout(operation(cm, function() {
1813
+ if (counter != curCount) return;
1814
+ display.scroller.scrollTop += outside;
1815
+ extend(e);
1816
+ }), 50);
1817
+ }
1818
+ }
1819
+
1820
+ function done(e) {
1821
+ counter = Infinity;
1822
+ e_preventDefault(e);
1823
+ focusInput(cm);
1824
+ off(document, "mousemove", move);
1825
+ off(document, "mouseup", up);
1826
+ }
1827
+
1828
+ var move = operation(cm, function(e) {
1829
+ if (!ie && !e_button(e)) done(e);
1830
+ else extend(e);
1831
+ });
1832
+ var up = operation(cm, done);
1833
+ on(document, "mousemove", move);
1834
+ on(document, "mouseup", up);
1835
+ }
1836
+
1837
+ function gutterEvent(cm, e, type, prevent, signalfn) {
1838
+ try { var mX = e.clientX, mY = e.clientY; }
1839
+ catch(e) { return false; }
1840
+ if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false;
1841
+ if (prevent) e_preventDefault(e);
1842
+
1843
+ var display = cm.display;
1844
+ var lineBox = getRect(display.lineDiv);
1845
+
1846
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
1847
+ mY -= lineBox.top - display.viewOffset;
1848
+
1849
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
1850
+ var g = display.gutters.childNodes[i];
1851
+ if (g && getRect(g).right >= mX) {
1852
+ var line = lineAtHeight(cm.doc, mY);
1853
+ var gutter = cm.options.gutters[i];
1854
+ signalfn(cm, type, cm, line, gutter, e);
1855
+ return e_defaultPrevented(e);
1856
+ }
1857
+ }
1858
+ }
1859
+
1860
+ function contextMenuInGutter(cm, e) {
1861
+ if (!hasHandler(cm, "gutterContextMenu")) return false;
1862
+ return gutterEvent(cm, e, "gutterContextMenu", false, signal);
1863
+ }
1864
+
1865
+ function clickInGutter(cm, e) {
1866
+ return gutterEvent(cm, e, "gutterClick", true, signalLater);
1867
+ }
1868
+
1869
+ // Kludge to work around strange IE behavior where it'll sometimes
1870
+ // re-fire a series of drag-related events right after the drop (#1551)
1871
+ var lastDrop = 0;
1872
+
1873
+ function onDrop(e) {
1874
+ var cm = this;
1875
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1876
+ return;
1877
+ e_preventDefault(e);
1878
+ if (ie) lastDrop = +new Date;
1879
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1880
+ if (!pos || isReadOnly(cm)) return;
1881
+ if (files && files.length && window.FileReader && window.File) {
1882
+ var n = files.length, text = Array(n), read = 0;
1883
+ var loadFile = function(file, i) {
1884
+ var reader = new FileReader;
1885
+ reader.onload = function() {
1886
+ text[i] = reader.result;
1887
+ if (++read == n) {
1888
+ pos = clipPos(cm.doc, pos);
1889
+ makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
1890
+ }
1891
+ };
1892
+ reader.readAsText(file);
1893
+ };
1894
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
1895
+ } else {
1896
+ // Don't do a replace if the drop happened inside of the selected text.
1897
+ if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
1898
+ cm.state.draggingText(e);
1899
+ // Ensure the editor is re-focused
1900
+ setTimeout(bind(focusInput, cm), 20);
1901
+ return;
1902
+ }
1903
+ try {
1904
+ var text = e.dataTransfer.getData("Text");
1905
+ if (text) {
1906
+ var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
1907
+ setSelection(cm.doc, pos, pos);
1908
+ if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
1909
+ cm.replaceSelection(text, null, "paste");
1910
+ focusInput(cm);
1911
+ onFocus(cm);
1912
+ }
1913
+ }
1914
+ catch(e){}
1915
+ }
1916
+ }
1917
+
1918
+ function onDragStart(cm, e) {
1919
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1920
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1921
+
1922
+ var txt = cm.getSelection();
1923
+ e.dataTransfer.setData("Text", txt);
1924
+
1925
+ // Use dummy image instead of default browsers image.
1926
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
1927
+ if (e.dataTransfer.setDragImage && !safari) {
1928
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1929
+ img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
1930
+ if (opera) {
1931
+ img.width = img.height = 1;
1932
+ cm.display.wrapper.appendChild(img);
1933
+ // Force a relayout, or Opera won't use our image for some obscure reason
1934
+ img._top = img.offsetTop;
1935
+ }
1936
+ e.dataTransfer.setDragImage(img, 0, 0);
1937
+ if (opera) img.parentNode.removeChild(img);
1938
+ }
1939
+ }
1940
+
1941
+ function setScrollTop(cm, val) {
1942
+ if (Math.abs(cm.doc.scrollTop - val) < 2) return;
1943
+ cm.doc.scrollTop = val;
1944
+ if (!gecko) updateDisplay(cm, [], val);
1945
+ if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1946
+ if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1947
+ if (gecko) updateDisplay(cm, []);
1948
+ startWorker(cm, 100);
1949
+ }
1950
+ function setScrollLeft(cm, val, isScroller) {
1951
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
1952
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
1953
+ cm.doc.scrollLeft = val;
1954
+ alignHorizontally(cm);
1955
+ if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
1956
+ if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
1957
+ }
1958
+
1959
+ // Since the delta values reported on mouse wheel events are
1960
+ // unstandardized between browsers and even browser versions, and
1961
+ // generally horribly unpredictable, this code starts by measuring
1962
+ // the scroll effect that the first few mouse wheel events have,
1963
+ // and, from that, detects the way it can convert deltas to pixel
1964
+ // offsets afterwards.
1965
+ //
1966
+ // The reason we want to know the amount a wheel event will scroll
1967
+ // is that it gives us a chance to update the display before the
1968
+ // actual scrolling happens, reducing flickering.
1969
+
1970
+ var wheelSamples = 0, wheelPixelsPerUnit = null;
1971
+ // Fill in a browser-detected starting value on browsers where we
1972
+ // know one. These don't have to be accurate -- the result of them
1973
+ // being wrong would just be a slight flicker on the first wheel
1974
+ // scroll (if it is large enough).
1975
+ if (ie) wheelPixelsPerUnit = -.53;
1976
+ else if (gecko) wheelPixelsPerUnit = 15;
1977
+ else if (chrome) wheelPixelsPerUnit = -.7;
1978
+ else if (safari) wheelPixelsPerUnit = -1/3;
1979
+
1980
+ function onScrollWheel(cm, e) {
1981
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
1982
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
1983
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
1984
+ else if (dy == null) dy = e.wheelDelta;
1985
+
1986
+ var display = cm.display, scroll = display.scroller;
1987
+ // Quit if there's nothing to scroll here
1988
+ if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
1989
+ dy && scroll.scrollHeight > scroll.clientHeight)) return;
1990
+
1991
+ // Webkit browsers on OS X abort momentum scrolls when the target
1992
+ // of the scroll event is removed from the scrollable element.
1993
+ // This hack (see related code in patchDisplay) makes sure the
1994
+ // element is kept around.
1995
+ if (dy && mac && webkit) {
1996
+ for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
1997
+ if (cur.lineObj) {
1998
+ cm.display.currentWheelTarget = cur;
1999
+ break;
2000
+ }
2001
+ }
2002
+ }
2003
+
2004
+ // On some browsers, horizontal scrolling will cause redraws to
2005
+ // happen before the gutter has been realigned, causing it to
2006
+ // wriggle around in a most unseemly way. When we have an
2007
+ // estimated pixels/delta value, we just handle horizontal
2008
+ // scrolling entirely here. It'll be slightly off from native, but
2009
+ // better than glitching out.
2010
+ if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
2011
+ if (dy)
2012
+ setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
2013
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
2014
+ e_preventDefault(e);
2015
+ display.wheelStartX = null; // Abort measurement, if in progress
2016
+ return;
2017
+ }
2018
+
2019
+ if (dy && wheelPixelsPerUnit != null) {
2020
+ var pixels = dy * wheelPixelsPerUnit;
2021
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
2022
+ if (pixels < 0) top = Math.max(0, top + pixels - 50);
2023
+ else bot = Math.min(cm.doc.height, bot + pixels + 50);
2024
+ updateDisplay(cm, [], {top: top, bottom: bot});
2025
+ }
2026
+
2027
+ if (wheelSamples < 20) {
2028
+ if (display.wheelStartX == null) {
2029
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
2030
+ display.wheelDX = dx; display.wheelDY = dy;
2031
+ setTimeout(function() {
2032
+ if (display.wheelStartX == null) return;
2033
+ var movedX = scroll.scrollLeft - display.wheelStartX;
2034
+ var movedY = scroll.scrollTop - display.wheelStartY;
2035
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
2036
+ (movedX && display.wheelDX && movedX / display.wheelDX);
2037
+ display.wheelStartX = display.wheelStartY = null;
2038
+ if (!sample) return;
2039
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
2040
+ ++wheelSamples;
2041
+ }, 200);
2042
+ } else {
2043
+ display.wheelDX += dx; display.wheelDY += dy;
2044
+ }
2045
+ }
2046
+ }
2047
+
2048
+ function doHandleBinding(cm, bound, dropShift) {
2049
+ if (typeof bound == "string") {
2050
+ bound = commands[bound];
2051
+ if (!bound) return false;
2052
+ }
2053
+ // Ensure previous input has been read, so that the handler sees a
2054
+ // consistent view of the document
2055
+ if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
2056
+ var doc = cm.doc, prevShift = doc.sel.shift, done = false;
2057
+ try {
2058
+ if (isReadOnly(cm)) cm.state.suppressEdits = true;
2059
+ if (dropShift) doc.sel.shift = false;
2060
+ done = bound(cm) != Pass;
2061
+ } finally {
2062
+ doc.sel.shift = prevShift;
2063
+ cm.state.suppressEdits = false;
2064
+ }
2065
+ return done;
2066
+ }
2067
+
2068
+ function allKeyMaps(cm) {
2069
+ var maps = cm.state.keyMaps.slice(0);
2070
+ if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
2071
+ maps.push(cm.options.keyMap);
2072
+ return maps;
2073
+ }
2074
+
2075
+ var maybeTransition;
2076
+ function handleKeyBinding(cm, e) {
2077
+ // Handle auto keymap transitions
2078
+ var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
2079
+ clearTimeout(maybeTransition);
2080
+ if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
2081
+ if (getKeyMap(cm.options.keyMap) == startMap) {
2082
+ cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2083
+ keyMapChanged(cm);
2084
+ }
2085
+ }, 50);
2086
+
2087
+ var name = keyName(e, true), handled = false;
2088
+ if (!name) return false;
2089
+ var keymaps = allKeyMaps(cm);
2090
+
2091
+ if (e.shiftKey) {
2092
+ // First try to resolve full name (including 'Shift-'). Failing
2093
+ // that, see if there is a cursor-motion command (starting with
2094
+ // 'go') bound to the keyname without 'Shift-'.
2095
+ handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
2096
+ || lookupKey(name, keymaps, function(b) {
2097
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
2098
+ return doHandleBinding(cm, b);
2099
+ });
2100
+ } else {
2101
+ handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
2102
+ }
2103
+
2104
+ if (handled) {
2105
+ e_preventDefault(e);
2106
+ restartBlink(cm);
2107
+ if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2108
+ signalLater(cm, "keyHandled", cm, name, e);
2109
+ }
2110
+ return handled;
2111
+ }
2112
+
2113
+ function handleCharBinding(cm, e, ch) {
2114
+ var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
2115
+ function(b) { return doHandleBinding(cm, b, true); });
2116
+ if (handled) {
2117
+ e_preventDefault(e);
2118
+ restartBlink(cm);
2119
+ signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
2120
+ }
2121
+ return handled;
2122
+ }
2123
+
2124
+ var lastStoppedKey = null;
2125
+ function onKeyDown(e) {
2126
+ var cm = this;
2127
+ if (!cm.state.focused) onFocus(cm);
2128
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2129
+ if (ie && e.keyCode == 27) e.returnValue = false;
2130
+ var code = e.keyCode;
2131
+ // IE does strange things with escape.
2132
+ cm.doc.sel.shift = code == 16 || e.shiftKey;
2133
+ // First give onKeyEvent option a chance to handle this.
2134
+ var handled = handleKeyBinding(cm, e);
2135
+ if (opera) {
2136
+ lastStoppedKey = handled ? code : null;
2137
+ // Opera has no cut event... we try to at least catch the key combo
2138
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
2139
+ cm.replaceSelection("");
2140
+ }
2141
+ }
2142
+
2143
+ function onKeyPress(e) {
2144
+ var cm = this;
2145
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2146
+ var keyCode = e.keyCode, charCode = e.charCode;
2147
+ if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2148
+ if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
2149
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
2150
+ if (this.options.electricChars && this.doc.mode.electricChars &&
2151
+ this.options.smartIndent && !isReadOnly(this) &&
2152
+ this.doc.mode.electricChars.indexOf(ch) > -1)
2153
+ setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
2154
+ if (handleCharBinding(cm, e, ch)) return;
2155
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
2156
+ fastPoll(cm);
2157
+ }
2158
+
2159
+ function onFocus(cm) {
2160
+ if (cm.options.readOnly == "nocursor") return;
2161
+ if (!cm.state.focused) {
2162
+ signal(cm, "focus", cm);
2163
+ cm.state.focused = true;
2164
+ if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
2165
+ cm.display.wrapper.className += " CodeMirror-focused";
2166
+ if (!cm.curOp) {
2167
+ resetInput(cm, true);
2168
+ if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
2169
+ }
2170
+ }
2171
+ slowPoll(cm);
2172
+ restartBlink(cm);
2173
+ }
2174
+ function onBlur(cm) {
2175
+ if (cm.state.focused) {
2176
+ signal(cm, "blur", cm);
2177
+ cm.state.focused = false;
2178
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
2179
+ }
2180
+ clearInterval(cm.display.blinker);
2181
+ setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
2182
+ }
2183
+
2184
+ var detectingSelectAll;
2185
+ function onContextMenu(cm, e) {
2186
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
2187
+ var display = cm.display, sel = cm.doc.sel;
2188
+ if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;
2189
+
2190
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
2191
+ if (!pos || opera) return; // Opera is difficult.
2192
+
2193
+ // Reset the current text selection only if the click is done outside of the selection
2194
+ // and 'resetSelectionOnContextMenu' option is true.
2195
+ var reset = cm.options.resetSelectionOnContextMenu;
2196
+ if (reset && (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)))
2197
+ operation(cm, setSelection)(cm.doc, pos, pos);
2198
+
2199
+ var oldCSS = display.input.style.cssText;
2200
+ display.inputDiv.style.position = "absolute";
2201
+ display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
2202
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
2203
+ "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
2204
+ focusInput(cm);
2205
+ resetInput(cm, true);
2206
+ // Adds "Select all" to context menu in FF
2207
+ if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
2208
+
2209
+ function prepareSelectAllHack() {
2210
+ if (display.input.selectionStart != null) {
2211
+ var extval = display.input.value = "\u200b" + (posEq(sel.from, sel.to) ? "" : display.input.value);
2212
+ display.prevInput = "\u200b";
2213
+ display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2214
+ }
2215
+ }
2216
+ function rehide() {
2217
+ display.inputDiv.style.position = "relative";
2218
+ display.input.style.cssText = oldCSS;
2219
+ if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
2220
+ slowPoll(cm);
2221
+
2222
+ // Try to detect the user choosing select-all
2223
+ if (display.input.selectionStart != null) {
2224
+ if (!ie || ie_lt9) prepareSelectAllHack();
2225
+ clearTimeout(detectingSelectAll);
2226
+ var i = 0, poll = function(){
2227
+ if (display.prevInput == " " && display.input.selectionStart == 0)
2228
+ operation(cm, commands.selectAll)(cm);
2229
+ else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
2230
+ else resetInput(cm);
2231
+ };
2232
+ detectingSelectAll = setTimeout(poll, 200);
2233
+ }
2234
+ }
2235
+
2236
+ if (ie && !ie_lt9) prepareSelectAllHack();
2237
+ if (captureMiddleClick) {
2238
+ e_stop(e);
2239
+ var mouseup = function() {
2240
+ off(window, "mouseup", mouseup);
2241
+ setTimeout(rehide, 20);
2242
+ };
2243
+ on(window, "mouseup", mouseup);
2244
+ } else {
2245
+ setTimeout(rehide, 50);
2246
+ }
2247
+ }
2248
+
2249
+ // UPDATING
2250
+
2251
+ var changeEnd = CodeMirror.changeEnd = function(change) {
2252
+ if (!change.text) return change.to;
2253
+ return Pos(change.from.line + change.text.length - 1,
2254
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2255
+ };
2256
+
2257
+ // Make sure a position will be valid after the given change.
2258
+ function clipPostChange(doc, change, pos) {
2259
+ if (!posLess(change.from, pos)) return clipPos(doc, pos);
2260
+ var diff = (change.text.length - 1) - (change.to.line - change.from.line);
2261
+ if (pos.line > change.to.line + diff) {
2262
+ var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
2263
+ if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
2264
+ return clipToLen(pos, getLine(doc, preLine).text.length);
2265
+ }
2266
+ if (pos.line == change.to.line + diff)
2267
+ return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
2268
+ getLine(doc, change.to.line).text.length - change.to.ch);
2269
+ var inside = pos.line - change.from.line;
2270
+ return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
2271
+ }
2272
+
2273
+ // Hint can be null|"end"|"start"|"around"|{anchor,head}
2274
+ function computeSelAfterChange(doc, change, hint) {
2275
+ if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
2276
+ return {anchor: clipPostChange(doc, change, hint.anchor),
2277
+ head: clipPostChange(doc, change, hint.head)};
2278
+
2279
+ if (hint == "start") return {anchor: change.from, head: change.from};
2280
+
2281
+ var end = changeEnd(change);
2282
+ if (hint == "around") return {anchor: change.from, head: end};
2283
+ if (hint == "end") return {anchor: end, head: end};
2284
+
2285
+ // hint is null, leave the selection alone as much as possible
2286
+ var adjustPos = function(pos) {
2287
+ if (posLess(pos, change.from)) return pos;
2288
+ if (!posLess(change.to, pos)) return end;
2289
+
2290
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
2291
+ if (pos.line == change.to.line) ch += end.ch - change.to.ch;
2292
+ return Pos(line, ch);
2293
+ };
2294
+ return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2295
+ }
2296
+
2297
+ function filterChange(doc, change, update) {
2298
+ var obj = {
2299
+ canceled: false,
2300
+ from: change.from,
2301
+ to: change.to,
2302
+ text: change.text,
2303
+ origin: change.origin,
2304
+ cancel: function() { this.canceled = true; }
2305
+ };
2306
+ if (update) obj.update = function(from, to, text, origin) {
2307
+ if (from) this.from = clipPos(doc, from);
2308
+ if (to) this.to = clipPos(doc, to);
2309
+ if (text) this.text = text;
2310
+ if (origin !== undefined) this.origin = origin;
2311
+ };
2312
+ signal(doc, "beforeChange", doc, obj);
2313
+ if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2314
+
2315
+ if (obj.canceled) return null;
2316
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
2317
+ }
2318
+
2319
+ // Replace the range from from to to by the strings in replacement.
2320
+ // change is a {from, to, text [, origin]} object
2321
+ function makeChange(doc, change, selUpdate, ignoreReadOnly) {
2322
+ if (doc.cm) {
2323
+ if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
2324
+ if (doc.cm.state.suppressEdits) return;
2325
+ }
2326
+
2327
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2328
+ change = filterChange(doc, change, true);
2329
+ if (!change) return;
2330
+ }
2331
+
2332
+ // Possibly split or suppress the update based on the presence
2333
+ // of read-only spans in its range.
2334
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
2335
+ if (split) {
2336
+ for (var i = split.length - 1; i >= 1; --i)
2337
+ makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
2338
+ if (split.length)
2339
+ makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
2340
+ } else {
2341
+ makeChangeNoReadonly(doc, change, selUpdate);
2342
+ }
2343
+ }
2344
+
2345
+ function makeChangeNoReadonly(doc, change, selUpdate) {
2346
+ if (change.text.length == 1 && change.text[0] == "" && posEq(change.from, change.to)) return;
2347
+ var selAfter = computeSelAfterChange(doc, change, selUpdate);
2348
+ addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
2349
+
2350
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
2351
+ var rebased = [];
2352
+
2353
+ linkedDocs(doc, function(doc, sharedHist) {
2354
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2355
+ rebaseHist(doc.history, change);
2356
+ rebased.push(doc.history);
2357
+ }
2358
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
2359
+ });
2360
+ }
2361
+
2362
+ function makeChangeFromHistory(doc, type) {
2363
+ if (doc.cm && doc.cm.state.suppressEdits) return;
2364
+
2365
+ var hist = doc.history;
2366
+ var event = (type == "undo" ? hist.done : hist.undone).pop();
2367
+ if (!event) return;
2368
+
2369
+ var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
2370
+ anchorAfter: event.anchorBefore, headAfter: event.headBefore,
2371
+ generation: hist.generation};
2372
+ (type == "undo" ? hist.undone : hist.done).push(anti);
2373
+ hist.generation = event.generation || ++hist.maxGeneration;
2374
+
2375
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
2376
+
2377
+ for (var i = event.changes.length - 1; i >= 0; --i) {
2378
+ var change = event.changes[i];
2379
+ change.origin = type;
2380
+ if (filter && !filterChange(doc, change, false)) {
2381
+ (type == "undo" ? hist.done : hist.undone).length = 0;
2382
+ return;
2383
+ }
2384
+
2385
+ anti.changes.push(historyChangeFromChange(doc, change));
2386
+
2387
+ var after = i ? computeSelAfterChange(doc, change, null)
2388
+ : {anchor: event.anchorBefore, head: event.headBefore};
2389
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
2390
+ var rebased = [];
2391
+
2392
+ linkedDocs(doc, function(doc, sharedHist) {
2393
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2394
+ rebaseHist(doc.history, change);
2395
+ rebased.push(doc.history);
2396
+ }
2397
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
2398
+ });
2399
+ }
2400
+ }
2401
+
2402
+ function shiftDoc(doc, distance) {
2403
+ function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
2404
+ doc.first += distance;
2405
+ if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
2406
+ doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
2407
+ doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
2408
+ }
2409
+
2410
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
2411
+ if (doc.cm && !doc.cm.curOp)
2412
+ return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
2413
+
2414
+ if (change.to.line < doc.first) {
2415
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
2416
+ return;
2417
+ }
2418
+ if (change.from.line > doc.lastLine()) return;
2419
+
2420
+ // Clip the change to the size of this doc
2421
+ if (change.from.line < doc.first) {
2422
+ var shift = change.text.length - 1 - (doc.first - change.from.line);
2423
+ shiftDoc(doc, shift);
2424
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
2425
+ text: [lst(change.text)], origin: change.origin};
2426
+ }
2427
+ var last = doc.lastLine();
2428
+ if (change.to.line > last) {
2429
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
2430
+ text: [change.text[0]], origin: change.origin};
2431
+ }
2432
+
2433
+ change.removed = getBetween(doc, change.from, change.to);
2434
+
2435
+ if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
2436
+ if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
2437
+ else updateDoc(doc, change, spans, selAfter);
2438
+ }
2439
+
2440
+ function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
2441
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
2442
+
2443
+ var recomputeMaxLength = false, checkWidthStart = from.line;
2444
+ if (!cm.options.lineWrapping) {
2445
+ checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
2446
+ doc.iter(checkWidthStart, to.line + 1, function(line) {
2447
+ if (line == display.maxLine) {
2448
+ recomputeMaxLength = true;
2449
+ return true;
2450
+ }
2451
+ });
2452
+ }
2453
+
2454
+ if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
2455
+ cm.curOp.cursorActivity = true;
2456
+
2457
+ updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
2458
+
2459
+ if (!cm.options.lineWrapping) {
2460
+ doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
2461
+ var len = lineLength(doc, line);
2462
+ if (len > display.maxLineLength) {
2463
+ display.maxLine = line;
2464
+ display.maxLineLength = len;
2465
+ display.maxLineChanged = true;
2466
+ recomputeMaxLength = false;
2467
+ }
2468
+ });
2469
+ if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
2470
+ }
2471
+
2472
+ // Adjust frontier, schedule worker
2473
+ doc.frontier = Math.min(doc.frontier, from.line);
2474
+ startWorker(cm, 400);
2475
+
2476
+ var lendiff = change.text.length - (to.line - from.line) - 1;
2477
+ // Remember that these lines changed, for updating the display
2478
+ regChange(cm, from.line, to.line + 1, lendiff);
2479
+
2480
+ if (hasHandler(cm, "change")) {
2481
+ var changeObj = {from: from, to: to,
2482
+ text: change.text,
2483
+ removed: change.removed,
2484
+ origin: change.origin};
2485
+ if (cm.curOp.textChanged) {
2486
+ for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
2487
+ cur.next = changeObj;
2488
+ } else cm.curOp.textChanged = changeObj;
2489
+ }
2490
+ }
2491
+
2492
+ function replaceRange(doc, code, from, to, origin) {
2493
+ if (!to) to = from;
2494
+ if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
2495
+ if (typeof code == "string") code = splitLines(code);
2496
+ makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
2497
+ }
2498
+
2499
+ // POSITION OBJECT
2500
+
2501
+ function Pos(line, ch) {
2502
+ if (!(this instanceof Pos)) return new Pos(line, ch);
2503
+ this.line = line; this.ch = ch;
2504
+ }
2505
+ CodeMirror.Pos = Pos;
2506
+
2507
+ function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
2508
+ function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2509
+ function copyPos(x) {return Pos(x.line, x.ch);}
2510
+
2511
+ // SELECTION
2512
+
2513
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
2514
+ function clipPos(doc, pos) {
2515
+ if (pos.line < doc.first) return Pos(doc.first, 0);
2516
+ var last = doc.first + doc.size - 1;
2517
+ if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2518
+ return clipToLen(pos, getLine(doc, pos.line).text.length);
2519
+ }
2520
+ function clipToLen(pos, linelen) {
2521
+ var ch = pos.ch;
2522
+ if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2523
+ else if (ch < 0) return Pos(pos.line, 0);
2524
+ else return pos;
2525
+ }
2526
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2527
+
2528
+ // If shift is held, this will move the selection anchor. Otherwise,
2529
+ // it'll set the whole selection.
2530
+ function extendSelection(doc, pos, other, bias) {
2531
+ if (doc.sel.shift || doc.sel.extend) {
2532
+ var anchor = doc.sel.anchor;
2533
+ if (other) {
2534
+ var posBefore = posLess(pos, anchor);
2535
+ if (posBefore != posLess(other, anchor)) {
2536
+ anchor = pos;
2537
+ pos = other;
2538
+ } else if (posBefore != posLess(pos, other)) {
2539
+ pos = other;
2540
+ }
2541
+ }
2542
+ setSelection(doc, anchor, pos, bias);
2543
+ } else {
2544
+ setSelection(doc, pos, other || pos, bias);
2545
+ }
2546
+ if (doc.cm) doc.cm.curOp.userSelChange = true;
2547
+ }
2548
+
2549
+ function filterSelectionChange(doc, anchor, head) {
2550
+ var obj = {anchor: anchor, head: head};
2551
+ signal(doc, "beforeSelectionChange", doc, obj);
2552
+ if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2553
+ obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
2554
+ return obj;
2555
+ }
2556
+
2557
+ // Update the selection. Last two args are only used by
2558
+ // updateDoc, since they have to be expressed in the line
2559
+ // numbers before the update.
2560
+ function setSelection(doc, anchor, head, bias, checkAtomic) {
2561
+ if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
2562
+ var filtered = filterSelectionChange(doc, anchor, head);
2563
+ head = filtered.head;
2564
+ anchor = filtered.anchor;
2565
+ }
2566
+
2567
+ var sel = doc.sel;
2568
+ sel.goalColumn = null;
2569
+ if (bias == null) bias = posLess(head, sel.head) ? -1 : 1;
2570
+ // Skip over atomic spans.
2571
+ if (checkAtomic || !posEq(anchor, sel.anchor))
2572
+ anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
2573
+ if (checkAtomic || !posEq(head, sel.head))
2574
+ head = skipAtomic(doc, head, bias, checkAtomic != "push");
2575
+
2576
+ if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
2577
+
2578
+ sel.anchor = anchor; sel.head = head;
2579
+ var inv = posLess(head, anchor);
2580
+ sel.from = inv ? head : anchor;
2581
+ sel.to = inv ? anchor : head;
2582
+
2583
+ if (doc.cm)
2584
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
2585
+ doc.cm.curOp.cursorActivity = true;
2586
+
2587
+ signalLater(doc, "cursorActivity", doc);
2588
+ }
2589
+
2590
+ function reCheckSelection(cm) {
2591
+ setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
2592
+ }
2593
+
2594
+ function skipAtomic(doc, pos, bias, mayClear) {
2595
+ var flipped = false, curPos = pos;
2596
+ var dir = bias || 1;
2597
+ doc.cantEdit = false;
2598
+ search: for (;;) {
2599
+ var line = getLine(doc, curPos.line);
2600
+ if (line.markedSpans) {
2601
+ for (var i = 0; i < line.markedSpans.length; ++i) {
2602
+ var sp = line.markedSpans[i], m = sp.marker;
2603
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
2604
+ (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
2605
+ if (mayClear) {
2606
+ signal(m, "beforeCursorEnter");
2607
+ if (m.explicitlyCleared) {
2608
+ if (!line.markedSpans) break;
2609
+ else {--i; continue;}
2610
+ }
2611
+ }
2612
+ if (!m.atomic) continue;
2613
+ var newPos = m.find()[dir < 0 ? "from" : "to"];
2614
+ if (posEq(newPos, curPos)) {
2615
+ newPos.ch += dir;
2616
+ if (newPos.ch < 0) {
2617
+ if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
2618
+ else newPos = null;
2619
+ } else if (newPos.ch > line.text.length) {
2620
+ if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
2621
+ else newPos = null;
2622
+ }
2623
+ if (!newPos) {
2624
+ if (flipped) {
2625
+ // Driven in a corner -- no valid cursor position found at all
2626
+ // -- try again *with* clearing, if we didn't already
2627
+ if (!mayClear) return skipAtomic(doc, pos, bias, true);
2628
+ // Otherwise, turn off editing until further notice, and return the start of the doc
2629
+ doc.cantEdit = true;
2630
+ return Pos(doc.first, 0);
2631
+ }
2632
+ flipped = true; newPos = pos; dir = -dir;
2633
+ }
2634
+ }
2635
+ curPos = newPos;
2636
+ continue search;
2637
+ }
2638
+ }
2639
+ }
2640
+ return curPos;
2641
+ }
2642
+ }
2643
+
2644
+ // SCROLLING
2645
+
2646
+ function scrollCursorIntoView(cm) {
2647
+ var coords = scrollPosIntoView(cm, cm.doc.sel.head, null, cm.options.cursorScrollMargin);
2648
+ if (!cm.state.focused) return;
2649
+ var display = cm.display, box = getRect(display.sizer), doScroll = null;
2650
+ if (coords.top + box.top < 0) doScroll = true;
2651
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2652
+ if (doScroll != null && !phantom) {
2653
+ var hidden = display.cursor.style.display == "none";
2654
+ if (hidden) {
2655
+ display.cursor.style.display = "";
2656
+ display.cursor.style.left = coords.left + "px";
2657
+ display.cursor.style.top = (coords.top - display.viewOffset) + "px";
2658
+ }
2659
+ display.cursor.scrollIntoView(doScroll);
2660
+ if (hidden) display.cursor.style.display = "none";
2661
+ }
2662
+ }
2663
+
2664
+ function scrollPosIntoView(cm, pos, end, margin) {
2665
+ if (margin == null) margin = 0;
2666
+ for (;;) {
2667
+ var changed = false, coords = cursorCoords(cm, pos);
2668
+ var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
2669
+ var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
2670
+ Math.min(coords.top, endCoords.top) - margin,
2671
+ Math.max(coords.left, endCoords.left),
2672
+ Math.max(coords.bottom, endCoords.bottom) + margin);
2673
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
2674
+ if (scrollPos.scrollTop != null) {
2675
+ setScrollTop(cm, scrollPos.scrollTop);
2676
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
2677
+ }
2678
+ if (scrollPos.scrollLeft != null) {
2679
+ setScrollLeft(cm, scrollPos.scrollLeft);
2680
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
2681
+ }
2682
+ if (!changed) return coords;
2683
+ }
2684
+ }
2685
+
2686
+ function scrollIntoView(cm, x1, y1, x2, y2) {
2687
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
2688
+ if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
2689
+ if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
2690
+ }
2691
+
2692
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
2693
+ var display = cm.display, snapMargin = textHeight(cm.display);
2694
+ if (y1 < 0) y1 = 0;
2695
+ var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2696
+ var docBottom = cm.doc.height + paddingVert(display);
2697
+ var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
2698
+ if (y1 < screentop) {
2699
+ result.scrollTop = atTop ? 0 : y1;
2700
+ } else if (y2 > screentop + screen) {
2701
+ var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
2702
+ if (newTop != screentop) result.scrollTop = newTop;
2703
+ }
2704
+
2705
+ var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
2706
+ x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
2707
+ var gutterw = display.gutters.offsetWidth;
2708
+ var atLeft = x1 < gutterw + 10;
2709
+ if (x1 < screenleft + gutterw || atLeft) {
2710
+ if (atLeft) x1 = 0;
2711
+ result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
2712
+ } else if (x2 > screenw + screenleft - 3) {
2713
+ result.scrollLeft = x2 + 10 - screenw;
2714
+ }
2715
+ return result;
2716
+ }
2717
+
2718
+ function updateScrollPos(cm, left, top) {
2719
+ cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
2720
+ scrollTop: top == null ? cm.doc.scrollTop : top};
2721
+ }
2722
+
2723
+ function addToScrollPos(cm, left, top) {
2724
+ var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
2725
+ var scroll = cm.display.scroller;
2726
+ pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
2727
+ pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
2728
+ }
2729
+
2730
+ // API UTILITIES
2731
+
2732
+ function indentLine(cm, n, how, aggressive) {
2733
+ var doc = cm.doc;
2734
+ if (how == null) how = "add";
2735
+ if (how == "smart") {
2736
+ if (!cm.doc.mode.indent) how = "prev";
2737
+ else var state = getStateBefore(cm, n);
2738
+ }
2739
+
2740
+ var tabSize = cm.options.tabSize;
2741
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
2742
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation;
2743
+ if (how == "smart") {
2744
+ indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
2745
+ if (indentation == Pass) {
2746
+ if (!aggressive) return;
2747
+ how = "prev";
2748
+ }
2749
+ }
2750
+ if (how == "prev") {
2751
+ if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
2752
+ else indentation = 0;
2753
+ } else if (how == "add") {
2754
+ indentation = curSpace + cm.options.indentUnit;
2755
+ } else if (how == "subtract") {
2756
+ indentation = curSpace - cm.options.indentUnit;
2757
+ } else if (typeof how == "number") {
2758
+ indentation = curSpace + how;
2759
+ }
2760
+ indentation = Math.max(0, indentation);
2761
+
2762
+ var indentString = "", pos = 0;
2763
+ if (cm.options.indentWithTabs)
2764
+ for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
2765
+ if (pos < indentation) indentString += spaceStr(indentation - pos);
2766
+
2767
+ if (indentString != curSpaceString)
2768
+ replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
2769
+ line.stateAfter = null;
2770
+ }
2771
+
2772
+ function changeLine(cm, handle, op) {
2773
+ var no = handle, line = handle, doc = cm.doc;
2774
+ if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
2775
+ else no = lineNo(handle);
2776
+ if (no == null) return null;
2777
+ if (op(line, no)) regChange(cm, no, no + 1);
2778
+ else return null;
2779
+ return line;
2780
+ }
2781
+
2782
+ function findPosH(doc, pos, dir, unit, visually) {
2783
+ var line = pos.line, ch = pos.ch, origDir = dir;
2784
+ var lineObj = getLine(doc, line);
2785
+ var possible = true;
2786
+ function findNextLine() {
2787
+ var l = line + dir;
2788
+ if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
2789
+ line = l;
2790
+ return lineObj = getLine(doc, l);
2791
+ }
2792
+ function moveOnce(boundToLine) {
2793
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
2794
+ if (next == null) {
2795
+ if (!boundToLine && findNextLine()) {
2796
+ if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
2797
+ else ch = dir < 0 ? lineObj.text.length : 0;
2798
+ } else return (possible = false);
2799
+ } else ch = next;
2800
+ return true;
2801
+ }
2802
+
2803
+ if (unit == "char") moveOnce();
2804
+ else if (unit == "column") moveOnce(true);
2805
+ else if (unit == "word" || unit == "group") {
2806
+ var sawType = null, group = unit == "group";
2807
+ for (var first = true;; first = false) {
2808
+ if (dir < 0 && !moveOnce(!first)) break;
2809
+ var cur = lineObj.text.charAt(ch) || "\n";
2810
+ var type = isWordChar(cur) ? "w"
2811
+ : !group ? null
2812
+ : /\s/.test(cur) ? null
2813
+ : "p";
2814
+ if (sawType && sawType != type) {
2815
+ if (dir < 0) {dir = 1; moveOnce();}
2816
+ break;
2817
+ }
2818
+ if (type) sawType = type;
2819
+ if (dir > 0 && !moveOnce(!first)) break;
2820
+ }
2821
+ }
2822
+ var result = skipAtomic(doc, Pos(line, ch), origDir, true);
2823
+ if (!possible) result.hitSide = true;
2824
+ return result;
2825
+ }
2826
+
2827
+ function findPosV(cm, pos, dir, unit) {
2828
+ var doc = cm.doc, x = pos.left, y;
2829
+ if (unit == "page") {
2830
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
2831
+ y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
2832
+ } else if (unit == "line") {
2833
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
2834
+ }
2835
+ for (;;) {
2836
+ var target = coordsChar(cm, x, y);
2837
+ if (!target.outside) break;
2838
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
2839
+ y += dir * 5;
2840
+ }
2841
+ return target;
2842
+ }
2843
+
2844
+ function findWordAt(line, pos) {
2845
+ var start = pos.ch, end = pos.ch;
2846
+ if (line) {
2847
+ if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
2848
+ var startChar = line.charAt(start);
2849
+ var check = isWordChar(startChar) ? isWordChar
2850
+ : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
2851
+ : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
2852
+ while (start > 0 && check(line.charAt(start - 1))) --start;
2853
+ while (end < line.length && check(line.charAt(end))) ++end;
2854
+ }
2855
+ return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
2856
+ }
2857
+
2858
+ function selectLine(cm, line) {
2859
+ extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
2860
+ }
2861
+
2862
+ // PROTOTYPE
2863
+
2864
+ // The publicly visible API. Note that operation(null, f) means
2865
+ // 'wrap f in an operation, performed on its `this` parameter'
2866
+
2867
+ CodeMirror.prototype = {
2868
+ constructor: CodeMirror,
2869
+ focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2870
+
2871
+ setOption: function(option, value) {
2872
+ var options = this.options, old = options[option];
2873
+ if (options[option] == value && option != "mode") return;
2874
+ options[option] = value;
2875
+ if (optionHandlers.hasOwnProperty(option))
2876
+ operation(this, optionHandlers[option])(this, value, old);
2877
+ },
2878
+
2879
+ getOption: function(option) {return this.options[option];},
2880
+ getDoc: function() {return this.doc;},
2881
+
2882
+ addKeyMap: function(map, bottom) {
2883
+ this.state.keyMaps[bottom ? "push" : "unshift"](map);
2884
+ },
2885
+ removeKeyMap: function(map) {
2886
+ var maps = this.state.keyMaps;
2887
+ for (var i = 0; i < maps.length; ++i)
2888
+ if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
2889
+ maps.splice(i, 1);
2890
+ return true;
2891
+ }
2892
+ },
2893
+
2894
+ addOverlay: operation(null, function(spec, options) {
2895
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
2896
+ if (mode.startState) throw new Error("Overlays may not be stateful.");
2897
+ this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
2898
+ this.state.modeGen++;
2899
+ regChange(this);
2900
+ }),
2901
+ removeOverlay: operation(null, function(spec) {
2902
+ var overlays = this.state.overlays;
2903
+ for (var i = 0; i < overlays.length; ++i) {
2904
+ var cur = overlays[i].modeSpec;
2905
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
2906
+ overlays.splice(i, 1);
2907
+ this.state.modeGen++;
2908
+ regChange(this);
2909
+ return;
2910
+ }
2911
+ }
2912
+ }),
2913
+
2914
+ indentLine: operation(null, function(n, dir, aggressive) {
2915
+ if (typeof dir != "string" && typeof dir != "number") {
2916
+ if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2917
+ else dir = dir ? "add" : "subtract";
2918
+ }
2919
+ if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
2920
+ }),
2921
+ indentSelection: operation(null, function(how) {
2922
+ var sel = this.doc.sel;
2923
+ if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
2924
+ var e = sel.to.line - (sel.to.ch ? 0 : 1);
2925
+ for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
2926
+ }),
2927
+
2928
+ // Fetch the parser token for a given character. Useful for hacks
2929
+ // that want to inspect the mode state (say, for completion).
2930
+ getTokenAt: function(pos, precise) {
2931
+ var doc = this.doc;
2932
+ pos = clipPos(doc, pos);
2933
+ var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
2934
+ var line = getLine(doc, pos.line);
2935
+ var stream = new StringStream(line.text, this.options.tabSize);
2936
+ while (stream.pos < pos.ch && !stream.eol()) {
2937
+ stream.start = stream.pos;
2938
+ var style = mode.token(stream, state);
2939
+ }
2940
+ return {start: stream.start,
2941
+ end: stream.pos,
2942
+ string: stream.current(),
2943
+ className: style || null, // Deprecated, use 'type' instead
2944
+ type: style || null,
2945
+ state: state};
2946
+ },
2947
+
2948
+ getTokenTypeAt: function(pos) {
2949
+ pos = clipPos(this.doc, pos);
2950
+ var styles = getLineStyles(this, getLine(this.doc, pos.line));
2951
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2952
+ if (ch == 0) return styles[2];
2953
+ for (;;) {
2954
+ var mid = (before + after) >> 1;
2955
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
2956
+ else if (styles[mid * 2 + 1] < ch) before = mid + 1;
2957
+ else return styles[mid * 2 + 2];
2958
+ }
2959
+ },
2960
+
2961
+ getModeAt: function(pos) {
2962
+ var mode = this.doc.mode;
2963
+ if (!mode.innerMode) return mode;
2964
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
2965
+ },
2966
+
2967
+ getHelper: function(pos, type) {
2968
+ if (!helpers.hasOwnProperty(type)) return;
2969
+ var help = helpers[type], mode = this.getModeAt(pos);
2970
+ return mode[type] && help[mode[type]] ||
2971
+ mode.helperType && help[mode.helperType] ||
2972
+ help[mode.name];
2973
+ },
2974
+
2975
+ getStateAfter: function(line, precise) {
2976
+ var doc = this.doc;
2977
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2978
+ return getStateBefore(this, line + 1, precise);
2979
+ },
2980
+
2981
+ cursorCoords: function(start, mode) {
2982
+ var pos, sel = this.doc.sel;
2983
+ if (start == null) pos = sel.head;
2984
+ else if (typeof start == "object") pos = clipPos(this.doc, start);
2985
+ else pos = start ? sel.from : sel.to;
2986
+ return cursorCoords(this, pos, mode || "page");
2987
+ },
2988
+
2989
+ charCoords: function(pos, mode) {
2990
+ return charCoords(this, clipPos(this.doc, pos), mode || "page");
2991
+ },
2992
+
2993
+ coordsChar: function(coords, mode) {
2994
+ coords = fromCoordSystem(this, coords, mode || "page");
2995
+ return coordsChar(this, coords.left, coords.top);
2996
+ },
2997
+
2998
+ lineAtHeight: function(height, mode) {
2999
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
3000
+ return lineAtHeight(this.doc, height + this.display.viewOffset);
3001
+ },
3002
+ heightAtLine: function(line, mode) {
3003
+ var end = false, last = this.doc.first + this.doc.size - 1;
3004
+ if (line < this.doc.first) line = this.doc.first;
3005
+ else if (line > last) { line = last; end = true; }
3006
+ var lineObj = getLine(this.doc, line);
3007
+ return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
3008
+ (end ? lineObj.height : 0);
3009
+ },
3010
+
3011
+ defaultTextHeight: function() { return textHeight(this.display); },
3012
+ defaultCharWidth: function() { return charWidth(this.display); },
3013
+
3014
+ setGutterMarker: operation(null, function(line, gutterID, value) {
3015
+ return changeLine(this, line, function(line) {
3016
+ var markers = line.gutterMarkers || (line.gutterMarkers = {});
3017
+ markers[gutterID] = value;
3018
+ if (!value && isEmpty(markers)) line.gutterMarkers = null;
3019
+ return true;
3020
+ });
3021
+ }),
3022
+
3023
+ clearGutter: operation(null, function(gutterID) {
3024
+ var cm = this, doc = cm.doc, i = doc.first;
3025
+ doc.iter(function(line) {
3026
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
3027
+ line.gutterMarkers[gutterID] = null;
3028
+ regChange(cm, i, i + 1);
3029
+ if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
3030
+ }
3031
+ ++i;
3032
+ });
3033
+ }),
3034
+
3035
+ addLineClass: operation(null, function(handle, where, cls) {
3036
+ return changeLine(this, handle, function(line) {
3037
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
3038
+ if (!line[prop]) line[prop] = cls;
3039
+ else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
3040
+ else line[prop] += " " + cls;
3041
+ return true;
3042
+ });
3043
+ }),
3044
+
3045
+ removeLineClass: operation(null, function(handle, where, cls) {
3046
+ return changeLine(this, handle, function(line) {
3047
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
3048
+ var cur = line[prop];
3049
+ if (!cur) return false;
3050
+ else if (cls == null) line[prop] = null;
3051
+ else {
3052
+ var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
3053
+ if (!found) return false;
3054
+ var end = found.index + found[0].length;
3055
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
3056
+ }
3057
+ return true;
3058
+ });
3059
+ }),
3060
+
3061
+ addLineWidget: operation(null, function(handle, node, options) {
3062
+ return addLineWidget(this, handle, node, options);
3063
+ }),
3064
+
3065
+ removeLineWidget: function(widget) { widget.clear(); },
3066
+
3067
+ lineInfo: function(line) {
3068
+ if (typeof line == "number") {
3069
+ if (!isLine(this.doc, line)) return null;
3070
+ var n = line;
3071
+ line = getLine(this.doc, line);
3072
+ if (!line) return null;
3073
+ } else {
3074
+ var n = lineNo(line);
3075
+ if (n == null) return null;
3076
+ }
3077
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
3078
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
3079
+ widgets: line.widgets};
3080
+ },
3081
+
3082
+ getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
3083
+
3084
+ addWidget: function(pos, node, scroll, vert, horiz) {
3085
+ var display = this.display;
3086
+ pos = cursorCoords(this, clipPos(this.doc, pos));
3087
+ var top = pos.bottom, left = pos.left;
3088
+ node.style.position = "absolute";
3089
+ display.sizer.appendChild(node);
3090
+ if (vert == "over") {
3091
+ top = pos.top;
3092
+ } else if (vert == "above" || vert == "near") {
3093
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
3094
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
3095
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
3096
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
3097
+ top = pos.top - node.offsetHeight;
3098
+ else if (pos.bottom + node.offsetHeight <= vspace)
3099
+ top = pos.bottom;
3100
+ if (left + node.offsetWidth > hspace)
3101
+ left = hspace - node.offsetWidth;
3102
+ }
3103
+ node.style.top = top + "px";
3104
+ node.style.left = node.style.right = "";
3105
+ if (horiz == "right") {
3106
+ left = display.sizer.clientWidth - node.offsetWidth;
3107
+ node.style.right = "0px";
3108
+ } else {
3109
+ if (horiz == "left") left = 0;
3110
+ else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
3111
+ node.style.left = left + "px";
3112
+ }
3113
+ if (scroll)
3114
+ scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
3115
+ },
3116
+
3117
+ triggerOnKeyDown: operation(null, onKeyDown),
3118
+
3119
+ execCommand: function(cmd) {return commands[cmd](this);},
3120
+
3121
+ findPosH: function(from, amount, unit, visually) {
3122
+ var dir = 1;
3123
+ if (amount < 0) { dir = -1; amount = -amount; }
3124
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3125
+ cur = findPosH(this.doc, cur, dir, unit, visually);
3126
+ if (cur.hitSide) break;
3127
+ }
3128
+ return cur;
3129
+ },
3130
+
3131
+ moveH: operation(null, function(dir, unit) {
3132
+ var sel = this.doc.sel, pos;
3133
+ if (sel.shift || sel.extend || posEq(sel.from, sel.to))
3134
+ pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
3135
+ else
3136
+ pos = dir < 0 ? sel.from : sel.to;
3137
+ extendSelection(this.doc, pos, pos, dir);
3138
+ }),
3139
+
3140
+ deleteH: operation(null, function(dir, unit) {
3141
+ var sel = this.doc.sel;
3142
+ if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
3143
+ else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
3144
+ this.curOp.userSelChange = true;
3145
+ }),
3146
+
3147
+ findPosV: function(from, amount, unit, goalColumn) {
3148
+ var dir = 1, x = goalColumn;
3149
+ if (amount < 0) { dir = -1; amount = -amount; }
3150
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3151
+ var coords = cursorCoords(this, cur, "div");
3152
+ if (x == null) x = coords.left;
3153
+ else coords.left = x;
3154
+ cur = findPosV(this, coords, dir, unit);
3155
+ if (cur.hitSide) break;
3156
+ }
3157
+ return cur;
3158
+ },
3159
+
3160
+ moveV: operation(null, function(dir, unit) {
3161
+ var sel = this.doc.sel;
3162
+ var pos = cursorCoords(this, sel.head, "div");
3163
+ if (sel.goalColumn != null) pos.left = sel.goalColumn;
3164
+ var target = findPosV(this, pos, dir, unit);
3165
+
3166
+ if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3167
+ extendSelection(this.doc, target, target, dir);
3168
+ sel.goalColumn = pos.left;
3169
+ }),
3170
+
3171
+ toggleOverwrite: function(value) {
3172
+ if (value != null && value == this.state.overwrite) return;
3173
+ if (this.state.overwrite = !this.state.overwrite)
3174
+ this.display.cursor.className += " CodeMirror-overwrite";
3175
+ else
3176
+ this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
3177
+ },
3178
+ hasFocus: function() { return this.state.focused; },
3179
+
3180
+ scrollTo: operation(null, function(x, y) {
3181
+ updateScrollPos(this, x, y);
3182
+ }),
3183
+ getScrollInfo: function() {
3184
+ var scroller = this.display.scroller, co = scrollerCutOff;
3185
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
3186
+ height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
3187
+ clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
3188
+ },
3189
+
3190
+ scrollIntoView: operation(null, function(range, margin) {
3191
+ if (range == null) range = {from: this.doc.sel.head, to: null};
3192
+ else if (typeof range == "number") range = {from: Pos(range, 0), to: null};
3193
+ else if (range.from == null) range = {from: range, to: null};
3194
+ if (!range.to) range.to = range.from;
3195
+ if (!margin) margin = 0;
3196
+
3197
+ var coords = range;
3198
+ if (range.from.line != null) {
3199
+ this.curOp.scrollToPos = {from: range.from, to: range.to, margin: margin};
3200
+ coords = {from: cursorCoords(this, range.from),
3201
+ to: cursorCoords(this, range.to)};
3202
+ }
3203
+ var sPos = calculateScrollPos(this, Math.min(coords.from.left, coords.to.left),
3204
+ Math.min(coords.from.top, coords.to.top) - margin,
3205
+ Math.max(coords.from.right, coords.to.right),
3206
+ Math.max(coords.from.bottom, coords.to.bottom) + margin);
3207
+ updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
3208
+ }),
3209
+
3210
+ setSize: operation(null, function(width, height) {
3211
+ function interpret(val) {
3212
+ return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
3213
+ }
3214
+ if (width != null) this.display.wrapper.style.width = interpret(width);
3215
+ if (height != null) this.display.wrapper.style.height = interpret(height);
3216
+ if (this.options.lineWrapping)
3217
+ this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
3218
+ this.curOp.forceUpdate = true;
3219
+ }),
3220
+
3221
+ operation: function(f){return runInOp(this, f);},
3222
+
3223
+ refresh: operation(null, function() {
3224
+ var badHeight = this.display.cachedTextHeight == null;
3225
+ clearCaches(this);
3226
+ updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
3227
+ regChange(this);
3228
+ if (badHeight) estimateLineHeights(this);
3229
+ }),
3230
+
3231
+ swapDoc: operation(null, function(doc) {
3232
+ var old = this.doc;
3233
+ old.cm = null;
3234
+ attachDoc(this, doc);
3235
+ clearCaches(this);
3236
+ resetInput(this, true);
3237
+ updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
3238
+ signalLater(this, "swapDoc", this, old);
3239
+ return old;
3240
+ }),
3241
+
3242
+ getInputField: function(){return this.display.input;},
3243
+ getWrapperElement: function(){return this.display.wrapper;},
3244
+ getScrollerElement: function(){return this.display.scroller;},
3245
+ getGutterElement: function(){return this.display.gutters;}
3246
+ };
3247
+ eventMixin(CodeMirror);
3248
+
3249
+ // OPTION DEFAULTS
3250
+
3251
+ var optionHandlers = CodeMirror.optionHandlers = {};
3252
+
3253
+ // The default configuration options.
3254
+ var defaults = CodeMirror.defaults = {};
3255
+
3256
+ function option(name, deflt, handle, notOnInit) {
3257
+ CodeMirror.defaults[name] = deflt;
3258
+ if (handle) optionHandlers[name] =
3259
+ notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
3260
+ }
3261
+
3262
+ var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
3263
+
3264
+ // These two are, on init, called from the constructor because they
3265
+ // have to be initialized before the editor can start at all.
3266
+ option("value", "", function(cm, val) {
3267
+ cm.setValue(val);
3268
+ }, true);
3269
+ option("mode", null, function(cm, val) {
3270
+ cm.doc.modeOption = val;
3271
+ loadMode(cm);
3272
+ }, true);
3273
+
3274
+ option("indentUnit", 2, loadMode, true);
3275
+ option("indentWithTabs", false);
3276
+ option("smartIndent", true);
3277
+ option("tabSize", 4, function(cm) {
3278
+ loadMode(cm);
3279
+ clearCaches(cm);
3280
+ regChange(cm);
3281
+ }, true);
3282
+ option("electricChars", true);
3283
+ option("rtlMoveVisually", !windows);
3284
+
3285
+ option("theme", "default", function(cm) {
3286
+ themeChanged(cm);
3287
+ guttersChanged(cm);
3288
+ }, true);
3289
+ option("keyMap", "default", keyMapChanged);
3290
+ option("extraKeys", null);
3291
+
3292
+ option("onKeyEvent", null);
3293
+ option("onDragEvent", null);
3294
+
3295
+ option("lineWrapping", false, wrappingChanged, true);
3296
+ option("gutters", [], function(cm) {
3297
+ setGuttersForLineNumbers(cm.options);
3298
+ guttersChanged(cm);
3299
+ }, true);
3300
+ option("fixedGutter", true, function(cm, val) {
3301
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3302
+ cm.refresh();
3303
+ }, true);
3304
+ option("coverGutterNextToScrollbar", false, updateScrollbars, true);
3305
+ option("lineNumbers", false, function(cm) {
3306
+ setGuttersForLineNumbers(cm.options);
3307
+ guttersChanged(cm);
3308
+ }, true);
3309
+ option("firstLineNumber", 1, guttersChanged, true);
3310
+ option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
3311
+ option("showCursorWhenSelecting", false, updateSelection, true);
3312
+
3313
+ option("resetSelectionOnContextMenu", true);
3314
+
3315
+ option("readOnly", false, function(cm, val) {
3316
+ if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
3317
+ else if (!val) resetInput(cm, true);
3318
+ });
3319
+ option("dragDrop", true);
3320
+
3321
+ option("cursorBlinkRate", 530);
3322
+ option("cursorScrollMargin", 0);
3323
+ option("cursorHeight", 1);
3324
+ option("workTime", 100);
3325
+ option("workDelay", 100);
3326
+ option("flattenSpans", true);
3327
+ option("pollInterval", 100);
3328
+ option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
3329
+ option("historyEventDelay", 500);
3330
+ option("viewportMargin", 10, function(cm){cm.refresh();}, true);
3331
+ option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
3332
+ option("crudeMeasuringFrom", 10000);
3333
+ option("moveInputWithCursor", true, function(cm, val) {
3334
+ if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
3335
+ });
3336
+
3337
+ option("tabindex", null, function(cm, val) {
3338
+ cm.display.input.tabIndex = val || "";
3339
+ });
3340
+ option("autofocus", null);
3341
+
3342
+ // MODE DEFINITION AND QUERYING
3343
+
3344
+ // Known modes, by name and by MIME
3345
+ var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
3346
+
3347
+ CodeMirror.defineMode = function(name, mode) {
3348
+ if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
3349
+ if (arguments.length > 2) {
3350
+ mode.dependencies = [];
3351
+ for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
3352
+ }
3353
+ modes[name] = mode;
3354
+ };
3355
+
3356
+ CodeMirror.defineMIME = function(mime, spec) {
3357
+ mimeModes[mime] = spec;
3358
+ };
3359
+
3360
+ CodeMirror.resolveMode = function(spec) {
3361
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
3362
+ spec = mimeModes[spec];
3363
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
3364
+ var found = mimeModes[spec.name];
3365
+ spec = createObj(found, spec);
3366
+ spec.name = found.name;
3367
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
3368
+ return CodeMirror.resolveMode("application/xml");
3369
+ }
3370
+ if (typeof spec == "string") return {name: spec};
3371
+ else return spec || {name: "null"};
3372
+ };
3373
+
3374
+ CodeMirror.getMode = function(options, spec) {
3375
+ var spec = CodeMirror.resolveMode(spec);
3376
+ var mfactory = modes[spec.name];
3377
+ if (!mfactory) return CodeMirror.getMode(options, "text/plain");
3378
+ var modeObj = mfactory(options, spec);
3379
+ if (modeExtensions.hasOwnProperty(spec.name)) {
3380
+ var exts = modeExtensions[spec.name];
3381
+ for (var prop in exts) {
3382
+ if (!exts.hasOwnProperty(prop)) continue;
3383
+ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
3384
+ modeObj[prop] = exts[prop];
3385
+ }
3386
+ }
3387
+ modeObj.name = spec.name;
3388
+
3389
+ return modeObj;
3390
+ };
3391
+
3392
+ CodeMirror.defineMode("null", function() {
3393
+ return {token: function(stream) {stream.skipToEnd();}};
3394
+ });
3395
+ CodeMirror.defineMIME("text/plain", "null");
3396
+
3397
+ var modeExtensions = CodeMirror.modeExtensions = {};
3398
+ CodeMirror.extendMode = function(mode, properties) {
3399
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
3400
+ copyObj(properties, exts);
3401
+ };
3402
+
3403
+ // EXTENSIONS
3404
+
3405
+ CodeMirror.defineExtension = function(name, func) {
3406
+ CodeMirror.prototype[name] = func;
3407
+ };
3408
+ CodeMirror.defineDocExtension = function(name, func) {
3409
+ Doc.prototype[name] = func;
3410
+ };
3411
+ CodeMirror.defineOption = option;
3412
+
3413
+ var initHooks = [];
3414
+ CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
3415
+
3416
+ var helpers = CodeMirror.helpers = {};
3417
+ CodeMirror.registerHelper = function(type, name, value) {
3418
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3419
+ helpers[type][name] = value;
3420
+ };
3421
+
3422
+ // UTILITIES
3423
+
3424
+ CodeMirror.isWordChar = isWordChar;
3425
+
3426
+ // MODE STATE HANDLING
3427
+
3428
+ // Utility functions for working with state. Exported because modes
3429
+ // sometimes need to do this.
3430
+ function copyState(mode, state) {
3431
+ if (state === true) return state;
3432
+ if (mode.copyState) return mode.copyState(state);
3433
+ var nstate = {};
3434
+ for (var n in state) {
3435
+ var val = state[n];
3436
+ if (val instanceof Array) val = val.concat([]);
3437
+ nstate[n] = val;
3438
+ }
3439
+ return nstate;
3440
+ }
3441
+ CodeMirror.copyState = copyState;
3442
+
3443
+ function startState(mode, a1, a2) {
3444
+ return mode.startState ? mode.startState(a1, a2) : true;
3445
+ }
3446
+ CodeMirror.startState = startState;
3447
+
3448
+ CodeMirror.innerMode = function(mode, state) {
3449
+ while (mode.innerMode) {
3450
+ var info = mode.innerMode(state);
3451
+ if (!info || info.mode == mode) break;
3452
+ state = info.state;
3453
+ mode = info.mode;
3454
+ }
3455
+ return info || {mode: mode, state: state};
3456
+ };
3457
+
3458
+ // STANDARD COMMANDS
3459
+
3460
+ var commands = CodeMirror.commands = {
3461
+ selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
3462
+ killLine: function(cm) {
3463
+ var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
3464
+ if (!sel && cm.getLine(from.line).length == from.ch)
3465
+ cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
3466
+ else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
3467
+ },
3468
+ deleteLine: function(cm) {
3469
+ var l = cm.getCursor().line;
3470
+ cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
3471
+ },
3472
+ delLineLeft: function(cm) {
3473
+ var cur = cm.getCursor();
3474
+ cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
3475
+ },
3476
+ undo: function(cm) {cm.undo();},
3477
+ redo: function(cm) {cm.redo();},
3478
+ goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
3479
+ goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
3480
+ goLineStart: function(cm) {
3481
+ cm.extendSelection(lineStart(cm, cm.getCursor().line));
3482
+ },
3483
+ goLineStartSmart: function(cm) {
3484
+ var cur = cm.getCursor(), start = lineStart(cm, cur.line);
3485
+ var line = cm.getLineHandle(start.line);
3486
+ var order = getOrder(line);
3487
+ if (!order || order[0].level == 0) {
3488
+ var firstNonWS = Math.max(0, line.text.search(/\S/));
3489
+ var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
3490
+ cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
3491
+ } else cm.extendSelection(start);
3492
+ },
3493
+ goLineEnd: function(cm) {
3494
+ cm.extendSelection(lineEnd(cm, cm.getCursor().line));
3495
+ },
3496
+ goLineRight: function(cm) {
3497
+ var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3498
+ cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
3499
+ },
3500
+ goLineLeft: function(cm) {
3501
+ var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3502
+ cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
3503
+ },
3504
+ goLineUp: function(cm) {cm.moveV(-1, "line");},
3505
+ goLineDown: function(cm) {cm.moveV(1, "line");},
3506
+ goPageUp: function(cm) {cm.moveV(-1, "page");},
3507
+ goPageDown: function(cm) {cm.moveV(1, "page");},
3508
+ goCharLeft: function(cm) {cm.moveH(-1, "char");},
3509
+ goCharRight: function(cm) {cm.moveH(1, "char");},
3510
+ goColumnLeft: function(cm) {cm.moveH(-1, "column");},
3511
+ goColumnRight: function(cm) {cm.moveH(1, "column");},
3512
+ goWordLeft: function(cm) {cm.moveH(-1, "word");},
3513
+ goGroupRight: function(cm) {cm.moveH(1, "group");},
3514
+ goGroupLeft: function(cm) {cm.moveH(-1, "group");},
3515
+ goWordRight: function(cm) {cm.moveH(1, "word");},
3516
+ delCharBefore: function(cm) {cm.deleteH(-1, "char");},
3517
+ delCharAfter: function(cm) {cm.deleteH(1, "char");},
3518
+ delWordBefore: function(cm) {cm.deleteH(-1, "word");},
3519
+ delWordAfter: function(cm) {cm.deleteH(1, "word");},
3520
+ delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
3521
+ delGroupAfter: function(cm) {cm.deleteH(1, "group");},
3522
+ indentAuto: function(cm) {cm.indentSelection("smart");},
3523
+ indentMore: function(cm) {cm.indentSelection("add");},
3524
+ indentLess: function(cm) {cm.indentSelection("subtract");},
3525
+ insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
3526
+ defaultTab: function(cm) {
3527
+ if (cm.somethingSelected()) cm.indentSelection("add");
3528
+ else cm.replaceSelection("\t", "end", "+input");
3529
+ },
3530
+ transposeChars: function(cm) {
3531
+ var cur = cm.getCursor(), line = cm.getLine(cur.line);
3532
+ if (cur.ch > 0 && cur.ch < line.length - 1)
3533
+ cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
3534
+ Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
3535
+ },
3536
+ newlineAndIndent: function(cm) {
3537
+ operation(cm, function() {
3538
+ cm.replaceSelection("\n", "end", "+input");
3539
+ cm.indentLine(cm.getCursor().line, null, true);
3540
+ })();
3541
+ },
3542
+ toggleOverwrite: function(cm) {cm.toggleOverwrite();}
3543
+ };
3544
+
3545
+ // STANDARD KEYMAPS
3546
+
3547
+ var keyMap = CodeMirror.keyMap = {};
3548
+ keyMap.basic = {
3549
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
3550
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
3551
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
3552
+ "Tab": "defaultTab", "Shift-Tab": "indentAuto",
3553
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
3554
+ };
3555
+ // Note that the save and find-related commands aren't defined by
3556
+ // default. Unknown commands are simply ignored.
3557
+ keyMap.pcDefault = {
3558
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
3559
+ "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
3560
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
3561
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
3562
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
3563
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
3564
+ fallthrough: "basic"
3565
+ };
3566
+ keyMap.macDefault = {
3567
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
3568
+ "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
3569
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3570
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3571
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3572
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
3573
+ fallthrough: ["basic", "emacsy"]
3574
+ };
3575
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
3576
+ keyMap.emacsy = {
3577
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
3578
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
3579
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
3580
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
3581
+ };
3582
+
3583
+ // KEYMAP DISPATCH
3584
+
3585
+ function getKeyMap(val) {
3586
+ if (typeof val == "string") return keyMap[val];
3587
+ else return val;
3588
+ }
3589
+
3590
+ function lookupKey(name, maps, handle) {
3591
+ function lookup(map) {
3592
+ map = getKeyMap(map);
3593
+ var found = map[name];
3594
+ if (found === false) return "stop";
3595
+ if (found != null && handle(found)) return true;
3596
+ if (map.nofallthrough) return "stop";
3597
+
3598
+ var fallthrough = map.fallthrough;
3599
+ if (fallthrough == null) return false;
3600
+ if (Object.prototype.toString.call(fallthrough) != "[object Array]")
3601
+ return lookup(fallthrough);
3602
+ for (var i = 0, e = fallthrough.length; i < e; ++i) {
3603
+ var done = lookup(fallthrough[i]);
3604
+ if (done) return done;
3605
+ }
3606
+ return false;
3607
+ }
3608
+
3609
+ for (var i = 0; i < maps.length; ++i) {
3610
+ var done = lookup(maps[i]);
3611
+ if (done) return done != "stop";
3612
+ }
3613
+ }
3614
+ function isModifierKey(event) {
3615
+ var name = keyNames[event.keyCode];
3616
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
3617
+ }
3618
+ function keyName(event, noShift) {
3619
+ if (opera && event.keyCode == 34 && event["char"]) return false;
3620
+ var name = keyNames[event.keyCode];
3621
+ if (name == null || event.altGraphKey) return false;
3622
+ if (event.altKey) name = "Alt-" + name;
3623
+ if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
3624
+ if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
3625
+ if (!noShift && event.shiftKey) name = "Shift-" + name;
3626
+ return name;
3627
+ }
3628
+ CodeMirror.lookupKey = lookupKey;
3629
+ CodeMirror.isModifierKey = isModifierKey;
3630
+ CodeMirror.keyName = keyName;
3631
+
3632
+ // FROMTEXTAREA
3633
+
3634
+ CodeMirror.fromTextArea = function(textarea, options) {
3635
+ if (!options) options = {};
3636
+ options.value = textarea.value;
3637
+ if (!options.tabindex && textarea.tabindex)
3638
+ options.tabindex = textarea.tabindex;
3639
+ if (!options.placeholder && textarea.placeholder)
3640
+ options.placeholder = textarea.placeholder;
3641
+ // Set autofocus to true if this textarea is focused, or if it has
3642
+ // autofocus and no other element is focused.
3643
+ if (options.autofocus == null) {
3644
+ var hasFocus = document.body;
3645
+ // doc.activeElement occasionally throws on IE
3646
+ try { hasFocus = document.activeElement; } catch(e) {}
3647
+ options.autofocus = hasFocus == textarea ||
3648
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body;
3649
+ }
3650
+
3651
+ function save() {textarea.value = cm.getValue();}
3652
+ if (textarea.form) {
3653
+ on(textarea.form, "submit", save);
3654
+ // Deplorable hack to make the submit method do the right thing.
3655
+ if (!options.leaveSubmitMethodAlone) {
3656
+ var form = textarea.form, realSubmit = form.submit;
3657
+ try {
3658
+ var wrappedSubmit = form.submit = function() {
3659
+ save();
3660
+ form.submit = realSubmit;
3661
+ form.submit();
3662
+ form.submit = wrappedSubmit;
3663
+ };
3664
+ } catch(e) {}
3665
+ }
3666
+ }
3667
+
3668
+ textarea.style.display = "none";
3669
+ var cm = CodeMirror(function(node) {
3670
+ textarea.parentNode.insertBefore(node, textarea.nextSibling);
3671
+ }, options);
3672
+ cm.save = save;
3673
+ cm.getTextArea = function() { return textarea; };
3674
+ cm.toTextArea = function() {
3675
+ save();
3676
+ textarea.parentNode.removeChild(cm.getWrapperElement());
3677
+ textarea.style.display = "";
3678
+ if (textarea.form) {
3679
+ off(textarea.form, "submit", save);
3680
+ if (typeof textarea.form.submit == "function")
3681
+ textarea.form.submit = realSubmit;
3682
+ }
3683
+ };
3684
+ return cm;
3685
+ };
3686
+
3687
+ // STRING STREAM
3688
+
3689
+ // Fed to the mode parsers, provides helper functions to make
3690
+ // parsers more succinct.
3691
+
3692
+ // The character stream used by a mode's parser.
3693
+ function StringStream(string, tabSize) {
3694
+ this.pos = this.start = 0;
3695
+ this.string = string;
3696
+ this.tabSize = tabSize || 8;
3697
+ this.lastColumnPos = this.lastColumnValue = 0;
3698
+ }
3699
+
3700
+ StringStream.prototype = {
3701
+ eol: function() {return this.pos >= this.string.length;},
3702
+ sol: function() {return this.pos == 0;},
3703
+ peek: function() {return this.string.charAt(this.pos) || undefined;},
3704
+ next: function() {
3705
+ if (this.pos < this.string.length)
3706
+ return this.string.charAt(this.pos++);
3707
+ },
3708
+ eat: function(match) {
3709
+ var ch = this.string.charAt(this.pos);
3710
+ if (typeof match == "string") var ok = ch == match;
3711
+ else var ok = ch && (match.test ? match.test(ch) : match(ch));
3712
+ if (ok) {++this.pos; return ch;}
3713
+ },
3714
+ eatWhile: function(match) {
3715
+ var start = this.pos;
3716
+ while (this.eat(match)){}
3717
+ return this.pos > start;
3718
+ },
3719
+ eatSpace: function() {
3720
+ var start = this.pos;
3721
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
3722
+ return this.pos > start;
3723
+ },
3724
+ skipToEnd: function() {this.pos = this.string.length;},
3725
+ skipTo: function(ch) {
3726
+ var found = this.string.indexOf(ch, this.pos);
3727
+ if (found > -1) {this.pos = found; return true;}
3728
+ },
3729
+ backUp: function(n) {this.pos -= n;},
3730
+ column: function() {
3731
+ if (this.lastColumnPos < this.start) {
3732
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
3733
+ this.lastColumnPos = this.start;
3734
+ }
3735
+ return this.lastColumnValue;
3736
+ },
3737
+ indentation: function() {return countColumn(this.string, null, this.tabSize);},
3738
+ match: function(pattern, consume, caseInsensitive) {
3739
+ if (typeof pattern == "string") {
3740
+ var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
3741
+ var substr = this.string.substr(this.pos, pattern.length);
3742
+ if (cased(substr) == cased(pattern)) {
3743
+ if (consume !== false) this.pos += pattern.length;
3744
+ return true;
3745
+ }
3746
+ } else {
3747
+ var match = this.string.slice(this.pos).match(pattern);
3748
+ if (match && match.index > 0) return null;
3749
+ if (match && consume !== false) this.pos += match[0].length;
3750
+ return match;
3751
+ }
3752
+ },
3753
+ current: function(){return this.string.slice(this.start, this.pos);}
3754
+ };
3755
+ CodeMirror.StringStream = StringStream;
3756
+
3757
+ // TEXTMARKERS
3758
+
3759
+ function TextMarker(doc, type) {
3760
+ this.lines = [];
3761
+ this.type = type;
3762
+ this.doc = doc;
3763
+ }
3764
+ CodeMirror.TextMarker = TextMarker;
3765
+ eventMixin(TextMarker);
3766
+
3767
+ TextMarker.prototype.clear = function() {
3768
+ if (this.explicitlyCleared) return;
3769
+ var cm = this.doc.cm, withOp = cm && !cm.curOp;
3770
+ if (withOp) startOperation(cm);
3771
+ if (hasHandler(this, "clear")) {
3772
+ var found = this.find();
3773
+ if (found) signalLater(this, "clear", found.from, found.to);
3774
+ }
3775
+ var min = null, max = null;
3776
+ for (var i = 0; i < this.lines.length; ++i) {
3777
+ var line = this.lines[i];
3778
+ var span = getMarkedSpanFor(line.markedSpans, this);
3779
+ if (span.to != null) max = lineNo(line);
3780
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
3781
+ if (span.from != null)
3782
+ min = lineNo(line);
3783
+ else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
3784
+ updateLineHeight(line, textHeight(cm.display));
3785
+ }
3786
+ if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
3787
+ var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
3788
+ if (len > cm.display.maxLineLength) {
3789
+ cm.display.maxLine = visual;
3790
+ cm.display.maxLineLength = len;
3791
+ cm.display.maxLineChanged = true;
3792
+ }
3793
+ }
3794
+
3795
+ if (min != null && cm) regChange(cm, min, max + 1);
3796
+ this.lines.length = 0;
3797
+ this.explicitlyCleared = true;
3798
+ if (this.atomic && this.doc.cantEdit) {
3799
+ this.doc.cantEdit = false;
3800
+ if (cm) reCheckSelection(cm);
3801
+ }
3802
+ if (withOp) endOperation(cm);
3803
+ };
3804
+
3805
+ TextMarker.prototype.find = function() {
3806
+ var from, to;
3807
+ for (var i = 0; i < this.lines.length; ++i) {
3808
+ var line = this.lines[i];
3809
+ var span = getMarkedSpanFor(line.markedSpans, this);
3810
+ if (span.from != null || span.to != null) {
3811
+ var found = lineNo(line);
3812
+ if (span.from != null) from = Pos(found, span.from);
3813
+ if (span.to != null) to = Pos(found, span.to);
3814
+ }
3815
+ }
3816
+ if (this.type == "bookmark") return from;
3817
+ return from && {from: from, to: to};
3818
+ };
3819
+
3820
+ TextMarker.prototype.changed = function() {
3821
+ var pos = this.find(), cm = this.doc.cm;
3822
+ if (!pos || !cm) return;
3823
+ if (this.type != "bookmark") pos = pos.from;
3824
+ var line = getLine(this.doc, pos.line);
3825
+ clearCachedMeasurement(cm, line);
3826
+ if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {
3827
+ for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
3828
+ if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3829
+ break;
3830
+ }
3831
+ runInOp(cm, function() {
3832
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
3833
+ });
3834
+ }
3835
+ };
3836
+
3837
+ TextMarker.prototype.attachLine = function(line) {
3838
+ if (!this.lines.length && this.doc.cm) {
3839
+ var op = this.doc.cm.curOp;
3840
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
3841
+ (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
3842
+ }
3843
+ this.lines.push(line);
3844
+ };
3845
+ TextMarker.prototype.detachLine = function(line) {
3846
+ this.lines.splice(indexOf(this.lines, line), 1);
3847
+ if (!this.lines.length && this.doc.cm) {
3848
+ var op = this.doc.cm.curOp;
3849
+ (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
3850
+ }
3851
+ };
3852
+
3853
+ function markText(doc, from, to, options, type) {
3854
+ if (options && options.shared) return markTextShared(doc, from, to, options, type);
3855
+ if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
3856
+
3857
+ var marker = new TextMarker(doc, type);
3858
+ if (type == "range" && !posLess(from, to)) return marker;
3859
+ if (options) copyObj(options, marker);
3860
+ if (marker.replacedWith) {
3861
+ marker.collapsed = true;
3862
+ marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3863
+ if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3864
+ }
3865
+ if (marker.collapsed) sawCollapsedSpans = true;
3866
+
3867
+ if (marker.addToHistory)
3868
+ addToHistory(doc, {from: from, to: to, origin: "markText"},
3869
+ {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
3870
+
3871
+ var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
3872
+ doc.iter(curLine, to.line + 1, function(line) {
3873
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
3874
+ updateMaxLine = true;
3875
+ var span = {from: null, to: null, marker: marker};
3876
+ size += line.text.length;
3877
+ if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
3878
+ if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
3879
+ if (marker.collapsed) {
3880
+ if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
3881
+ if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
3882
+ else updateLineHeight(line, 0);
3883
+ }
3884
+ addMarkedSpan(line, span);
3885
+ ++curLine;
3886
+ });
3887
+ if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
3888
+ if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
3889
+ });
3890
+
3891
+ if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
3892
+
3893
+ if (marker.readOnly) {
3894
+ sawReadOnlySpans = true;
3895
+ if (doc.history.done.length || doc.history.undone.length)
3896
+ doc.clearHistory();
3897
+ }
3898
+ if (marker.collapsed) {
3899
+ if (collapsedAtStart != collapsedAtEnd)
3900
+ throw new Error("Inserting collapsed marker overlapping an existing one");
3901
+ marker.size = size;
3902
+ marker.atomic = true;
3903
+ }
3904
+ if (cm) {
3905
+ if (updateMaxLine) cm.curOp.updateMaxLine = true;
3906
+ if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
3907
+ regChange(cm, from.line, to.line + 1);
3908
+ if (marker.atomic) reCheckSelection(cm);
3909
+ }
3910
+ return marker;
3911
+ }
3912
+
3913
+ // SHARED TEXTMARKERS
3914
+
3915
+ function SharedTextMarker(markers, primary) {
3916
+ this.markers = markers;
3917
+ this.primary = primary;
3918
+ for (var i = 0, me = this; i < markers.length; ++i) {
3919
+ markers[i].parent = this;
3920
+ on(markers[i], "clear", function(){me.clear();});
3921
+ }
3922
+ }
3923
+ CodeMirror.SharedTextMarker = SharedTextMarker;
3924
+ eventMixin(SharedTextMarker);
3925
+
3926
+ SharedTextMarker.prototype.clear = function() {
3927
+ if (this.explicitlyCleared) return;
3928
+ this.explicitlyCleared = true;
3929
+ for (var i = 0; i < this.markers.length; ++i)
3930
+ this.markers[i].clear();
3931
+ signalLater(this, "clear");
3932
+ };
3933
+ SharedTextMarker.prototype.find = function() {
3934
+ return this.primary.find();
3935
+ };
3936
+
3937
+ function markTextShared(doc, from, to, options, type) {
3938
+ options = copyObj(options);
3939
+ options.shared = false;
3940
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0];
3941
+ var widget = options.replacedWith;
3942
+ linkedDocs(doc, function(doc) {
3943
+ if (widget) options.replacedWith = widget.cloneNode(true);
3944
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
3945
+ for (var i = 0; i < doc.linked.length; ++i)
3946
+ if (doc.linked[i].isParent) return;
3947
+ primary = lst(markers);
3948
+ });
3949
+ return new SharedTextMarker(markers, primary);
3950
+ }
3951
+
3952
+ // TEXTMARKER SPANS
3953
+
3954
+ function getMarkedSpanFor(spans, marker) {
3955
+ if (spans) for (var i = 0; i < spans.length; ++i) {
3956
+ var span = spans[i];
3957
+ if (span.marker == marker) return span;
3958
+ }
3959
+ }
3960
+ function removeMarkedSpan(spans, span) {
3961
+ for (var r, i = 0; i < spans.length; ++i)
3962
+ if (spans[i] != span) (r || (r = [])).push(spans[i]);
3963
+ return r;
3964
+ }
3965
+ function addMarkedSpan(line, span) {
3966
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
3967
+ span.marker.attachLine(line);
3968
+ }
3969
+
3970
+ function markedSpansBefore(old, startCh, isInsert) {
3971
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
3972
+ var span = old[i], marker = span.marker;
3973
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3974
+ if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
3975
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
3976
+ (nw || (nw = [])).push({from: span.from,
3977
+ to: endsAfter ? null : span.to,
3978
+ marker: marker});
3979
+ }
3980
+ }
3981
+ return nw;
3982
+ }
3983
+
3984
+ function markedSpansAfter(old, endCh, isInsert) {
3985
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
3986
+ var span = old[i], marker = span.marker;
3987
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
3988
+ if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
3989
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
3990
+ (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
3991
+ to: span.to == null ? null : span.to - endCh,
3992
+ marker: marker});
3993
+ }
3994
+ }
3995
+ return nw;
3996
+ }
3997
+
3998
+ function stretchSpansOverChange(doc, change) {
3999
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
4000
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
4001
+ if (!oldFirst && !oldLast) return null;
4002
+
4003
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
4004
+ // Get the spans that 'stick out' on both sides
4005
+ var first = markedSpansBefore(oldFirst, startCh, isInsert);
4006
+ var last = markedSpansAfter(oldLast, endCh, isInsert);
4007
+
4008
+ // Next, merge those two ends
4009
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
4010
+ if (first) {
4011
+ // Fix up .to properties of first
4012
+ for (var i = 0; i < first.length; ++i) {
4013
+ var span = first[i];
4014
+ if (span.to == null) {
4015
+ var found = getMarkedSpanFor(last, span.marker);
4016
+ if (!found) span.to = startCh;
4017
+ else if (sameLine) span.to = found.to == null ? null : found.to + offset;
4018
+ }
4019
+ }
4020
+ }
4021
+ if (last) {
4022
+ // Fix up .from in last (or move them into first in case of sameLine)
4023
+ for (var i = 0; i < last.length; ++i) {
4024
+ var span = last[i];
4025
+ if (span.to != null) span.to += offset;
4026
+ if (span.from == null) {
4027
+ var found = getMarkedSpanFor(first, span.marker);
4028
+ if (!found) {
4029
+ span.from = offset;
4030
+ if (sameLine) (first || (first = [])).push(span);
4031
+ }
4032
+ } else {
4033
+ span.from += offset;
4034
+ if (sameLine) (first || (first = [])).push(span);
4035
+ }
4036
+ }
4037
+ }
4038
+ if (sameLine && first) {
4039
+ // Make sure we didn't create any zero-length spans
4040
+ for (var i = 0; i < first.length; ++i)
4041
+ if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
4042
+ first.splice(i--, 1);
4043
+ if (!first.length) first = null;
4044
+ }
4045
+
4046
+ var newMarkers = [first];
4047
+ if (!sameLine) {
4048
+ // Fill gap with whole-line-spans
4049
+ var gap = change.text.length - 2, gapMarkers;
4050
+ if (gap > 0 && first)
4051
+ for (var i = 0; i < first.length; ++i)
4052
+ if (first[i].to == null)
4053
+ (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
4054
+ for (var i = 0; i < gap; ++i)
4055
+ newMarkers.push(gapMarkers);
4056
+ newMarkers.push(last);
4057
+ }
4058
+ return newMarkers;
4059
+ }
4060
+
4061
+ function mergeOldSpans(doc, change) {
4062
+ var old = getOldSpans(doc, change);
4063
+ var stretched = stretchSpansOverChange(doc, change);
4064
+ if (!old) return stretched;
4065
+ if (!stretched) return old;
4066
+
4067
+ for (var i = 0; i < old.length; ++i) {
4068
+ var oldCur = old[i], stretchCur = stretched[i];
4069
+ if (oldCur && stretchCur) {
4070
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
4071
+ var span = stretchCur[j];
4072
+ for (var k = 0; k < oldCur.length; ++k)
4073
+ if (oldCur[k].marker == span.marker) continue spans;
4074
+ oldCur.push(span);
4075
+ }
4076
+ } else if (stretchCur) {
4077
+ old[i] = stretchCur;
4078
+ }
4079
+ }
4080
+ return old;
4081
+ }
4082
+
4083
+ function removeReadOnlyRanges(doc, from, to) {
4084
+ var markers = null;
4085
+ doc.iter(from.line, to.line + 1, function(line) {
4086
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
4087
+ var mark = line.markedSpans[i].marker;
4088
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
4089
+ (markers || (markers = [])).push(mark);
4090
+ }
4091
+ });
4092
+ if (!markers) return null;
4093
+ var parts = [{from: from, to: to}];
4094
+ for (var i = 0; i < markers.length; ++i) {
4095
+ var mk = markers[i], m = mk.find();
4096
+ for (var j = 0; j < parts.length; ++j) {
4097
+ var p = parts[j];
4098
+ if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
4099
+ var newParts = [j, 1];
4100
+ if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
4101
+ newParts.push({from: p.from, to: m.from});
4102
+ if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
4103
+ newParts.push({from: m.to, to: p.to});
4104
+ parts.splice.apply(parts, newParts);
4105
+ j += newParts.length - 1;
4106
+ }
4107
+ }
4108
+ return parts;
4109
+ }
4110
+
4111
+ function collapsedSpanAt(line, ch) {
4112
+ var sps = sawCollapsedSpans && line.markedSpans, found;
4113
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4114
+ sp = sps[i];
4115
+ if (!sp.marker.collapsed) continue;
4116
+ if ((sp.from == null || sp.from < ch) &&
4117
+ (sp.to == null || sp.to > ch) &&
4118
+ (!found || found.width < sp.marker.width))
4119
+ found = sp.marker;
4120
+ }
4121
+ return found;
4122
+ }
4123
+ function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
4124
+ function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
4125
+
4126
+ function visualLine(doc, line) {
4127
+ var merged;
4128
+ while (merged = collapsedSpanAtStart(line))
4129
+ line = getLine(doc, merged.find().from.line);
4130
+ return line;
4131
+ }
4132
+
4133
+ function lineIsHidden(doc, line) {
4134
+ var sps = sawCollapsedSpans && line.markedSpans;
4135
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4136
+ sp = sps[i];
4137
+ if (!sp.marker.collapsed) continue;
4138
+ if (sp.from == null) return true;
4139
+ if (sp.marker.replacedWith) continue;
4140
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
4141
+ return true;
4142
+ }
4143
+ }
4144
+ function lineIsHiddenInner(doc, line, span) {
4145
+ if (span.to == null) {
4146
+ var end = span.marker.find().to, endLine = getLine(doc, end.line);
4147
+ return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
4148
+ }
4149
+ if (span.marker.inclusiveRight && span.to == line.text.length)
4150
+ return true;
4151
+ for (var sp, i = 0; i < line.markedSpans.length; ++i) {
4152
+ sp = line.markedSpans[i];
4153
+ if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
4154
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4155
+ lineIsHiddenInner(doc, line, sp)) return true;
4156
+ }
4157
+ }
4158
+
4159
+ function detachMarkedSpans(line) {
4160
+ var spans = line.markedSpans;
4161
+ if (!spans) return;
4162
+ for (var i = 0; i < spans.length; ++i)
4163
+ spans[i].marker.detachLine(line);
4164
+ line.markedSpans = null;
4165
+ }
4166
+
4167
+ function attachMarkedSpans(line, spans) {
4168
+ if (!spans) return;
4169
+ for (var i = 0; i < spans.length; ++i)
4170
+ spans[i].marker.attachLine(line);
4171
+ line.markedSpans = spans;
4172
+ }
4173
+
4174
+ // LINE WIDGETS
4175
+
4176
+ var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
4177
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
4178
+ this[opt] = options[opt];
4179
+ this.cm = cm;
4180
+ this.node = node;
4181
+ };
4182
+ eventMixin(LineWidget);
4183
+ function widgetOperation(f) {
4184
+ return function() {
4185
+ var withOp = !this.cm.curOp;
4186
+ if (withOp) startOperation(this.cm);
4187
+ try {var result = f.apply(this, arguments);}
4188
+ finally {if (withOp) endOperation(this.cm);}
4189
+ return result;
4190
+ };
4191
+ }
4192
+ LineWidget.prototype.clear = widgetOperation(function() {
4193
+ var ws = this.line.widgets, no = lineNo(this.line);
4194
+ if (no == null || !ws) return;
4195
+ for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
4196
+ if (!ws.length) this.line.widgets = null;
4197
+ var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
4198
+ updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
4199
+ if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
4200
+ regChange(this.cm, no, no + 1);
4201
+ });
4202
+ LineWidget.prototype.changed = widgetOperation(function() {
4203
+ var oldH = this.height;
4204
+ this.height = null;
4205
+ var diff = widgetHeight(this) - oldH;
4206
+ if (!diff) return;
4207
+ updateLineHeight(this.line, this.line.height + diff);
4208
+ var no = lineNo(this.line);
4209
+ regChange(this.cm, no, no + 1);
4210
+ });
4211
+
4212
+ function widgetHeight(widget) {
4213
+ if (widget.height != null) return widget.height;
4214
+ if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
4215
+ removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
4216
+ return widget.height = widget.node.offsetHeight;
4217
+ }
4218
+
4219
+ function addLineWidget(cm, handle, node, options) {
4220
+ var widget = new LineWidget(cm, node, options);
4221
+ if (widget.noHScroll) cm.display.alignWidgets = true;
4222
+ changeLine(cm, handle, function(line) {
4223
+ var widgets = line.widgets || (line.widgets = []);
4224
+ if (widget.insertAt == null) widgets.push(widget);
4225
+ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
4226
+ widget.line = line;
4227
+ if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
4228
+ var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
4229
+ updateLineHeight(line, line.height + widgetHeight(widget));
4230
+ if (aboveVisible) addToScrollPos(cm, 0, widget.height);
4231
+ }
4232
+ return true;
4233
+ });
4234
+ return widget;
4235
+ }
4236
+
4237
+ // LINE DATA STRUCTURE
4238
+
4239
+ // Line objects. These hold state related to a line, including
4240
+ // highlighting info (the styles array).
4241
+ var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
4242
+ this.text = text;
4243
+ attachMarkedSpans(this, markedSpans);
4244
+ this.height = estimateHeight ? estimateHeight(this) : 1;
4245
+ };
4246
+ eventMixin(Line);
4247
+
4248
+ function updateLine(line, text, markedSpans, estimateHeight) {
4249
+ line.text = text;
4250
+ if (line.stateAfter) line.stateAfter = null;
4251
+ if (line.styles) line.styles = null;
4252
+ if (line.order != null) line.order = null;
4253
+ detachMarkedSpans(line);
4254
+ attachMarkedSpans(line, markedSpans);
4255
+ var estHeight = estimateHeight ? estimateHeight(line) : 1;
4256
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
4257
+ }
4258
+
4259
+ function cleanUpLine(line) {
4260
+ line.parent = null;
4261
+ detachMarkedSpans(line);
4262
+ }
4263
+
4264
+ // Run the given mode's parser over a line, update the styles
4265
+ // array, which contains alternating fragments of text and CSS
4266
+ // classes.
4267
+ function runMode(cm, text, mode, state, f) {
4268
+ var flattenSpans = mode.flattenSpans;
4269
+ if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4270
+ var curStart = 0, curStyle = null;
4271
+ var stream = new StringStream(text, cm.options.tabSize), style;
4272
+ if (text == "" && mode.blankLine) mode.blankLine(state);
4273
+ while (!stream.eol()) {
4274
+ if (stream.pos > cm.options.maxHighlightLength) {
4275
+ flattenSpans = false;
4276
+ stream.pos = text.length;
4277
+ style = null;
4278
+ } else {
4279
+ style = mode.token(stream, state);
4280
+ }
4281
+ if (!flattenSpans || curStyle != style) {
4282
+ if (curStart < stream.start) f(stream.start, curStyle);
4283
+ curStart = stream.start; curStyle = style;
4284
+ }
4285
+ stream.start = stream.pos;
4286
+ }
4287
+ while (curStart < stream.pos) {
4288
+ // Webkit seems to refuse to render text nodes longer than 57444 characters
4289
+ var pos = Math.min(stream.pos, curStart + 50000);
4290
+ f(pos, curStyle);
4291
+ curStart = pos;
4292
+ }
4293
+ }
4294
+
4295
+ function highlightLine(cm, line, state) {
4296
+ // A styles array always starts with a number identifying the
4297
+ // mode/overlays that it is based on (for easy invalidation).
4298
+ var st = [cm.state.modeGen];
4299
+ // Compute the base array of styles
4300
+ runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
4301
+
4302
+ // Run overlays, adjust style array.
4303
+ for (var o = 0; o < cm.state.overlays.length; ++o) {
4304
+ var overlay = cm.state.overlays[o], i = 1, at = 0;
4305
+ runMode(cm, line.text, overlay.mode, true, function(end, style) {
4306
+ var start = i;
4307
+ // Ensure there's a token end at the current position, and that i points at it
4308
+ while (at < end) {
4309
+ var i_end = st[i];
4310
+ if (i_end > end)
4311
+ st.splice(i, 1, end, st[i+1], i_end);
4312
+ i += 2;
4313
+ at = Math.min(end, i_end);
4314
+ }
4315
+ if (!style) return;
4316
+ if (overlay.opaque) {
4317
+ st.splice(start, i - start, end, style);
4318
+ i = start + 2;
4319
+ } else {
4320
+ for (; start < i; start += 2) {
4321
+ var cur = st[start+1];
4322
+ st[start+1] = cur ? cur + " " + style : style;
4323
+ }
4324
+ }
4325
+ });
4326
+ }
4327
+
4328
+ return st;
4329
+ }
4330
+
4331
+ function getLineStyles(cm, line) {
4332
+ if (!line.styles || line.styles[0] != cm.state.modeGen)
4333
+ line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
4334
+ return line.styles;
4335
+ }
4336
+
4337
+ // Lightweight form of highlight -- proceed over this line and
4338
+ // update state, but don't save a style array.
4339
+ function processLine(cm, line, state) {
4340
+ var mode = cm.doc.mode;
4341
+ var stream = new StringStream(line.text, cm.options.tabSize);
4342
+ if (line.text == "" && mode.blankLine) mode.blankLine(state);
4343
+ while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
4344
+ mode.token(stream, state);
4345
+ stream.start = stream.pos;
4346
+ }
4347
+ }
4348
+
4349
+ var styleToClassCache = {};
4350
+ function interpretTokenStyle(style, builder) {
4351
+ if (!style) return null;
4352
+ for (;;) {
4353
+ var lineClass = style.match(/(?:^|\s)line-(background-)?(\S+)/);
4354
+ if (!lineClass) break;
4355
+ style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length);
4356
+ var prop = lineClass[1] ? "bgClass" : "textClass";
4357
+ if (builder[prop] == null)
4358
+ builder[prop] = lineClass[2];
4359
+ else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop]))
4360
+ builder[prop] += " " + lineClass[2];
4361
+ }
4362
+ return styleToClassCache[style] ||
4363
+ (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4364
+ }
4365
+
4366
+ function buildLineContent(cm, realLine, measure, copyWidgets) {
4367
+ var merged, line = realLine, empty = true;
4368
+ while (merged = collapsedSpanAtStart(line))
4369
+ line = getLine(cm.doc, merged.find().from.line);
4370
+
4371
+ var builder = {pre: elt("pre"), col: 0, pos: 0,
4372
+ measure: null, measuredSomething: false, cm: cm,
4373
+ copyWidgets: copyWidgets};
4374
+
4375
+ do {
4376
+ if (line.text) empty = false;
4377
+ builder.measure = line == realLine && measure;
4378
+ builder.pos = 0;
4379
+ builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4380
+ if ((ie || webkit) && cm.getOption("lineWrapping"))
4381
+ builder.addToken = buildTokenSplitSpaces(builder.addToken);
4382
+ var next = insertLineContent(line, builder, getLineStyles(cm, line));
4383
+ if (measure && line == realLine && !builder.measuredSomething) {
4384
+ measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4385
+ builder.measuredSomething = true;
4386
+ }
4387
+ if (next) line = getLine(cm.doc, next.to.line);
4388
+ } while (next);
4389
+
4390
+ if (measure && !builder.measuredSomething && !measure[0])
4391
+ measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4392
+ if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4393
+ builder.pre.appendChild(document.createTextNode("\u00a0"));
4394
+
4395
+ var order;
4396
+ // Work around problem with the reported dimensions of single-char
4397
+ // direction spans on IE (issue #1129). See also the comment in
4398
+ // cursorCoords.
4399
+ if (measure && ie && (order = getOrder(line))) {
4400
+ var l = order.length - 1;
4401
+ if (order[l].from == order[l].to) --l;
4402
+ var last = order[l], prev = order[l - 1];
4403
+ if (last.from + 1 == last.to && prev && last.level < prev.level) {
4404
+ var span = measure[builder.pos - 1];
4405
+ if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
4406
+ span.nextSibling);
4407
+ }
4408
+ }
4409
+
4410
+ var textClass = builder.textClass ? builder.textClass + " " + (realLine.textClass || "") : realLine.textClass;
4411
+ if (textClass) builder.pre.className = textClass;
4412
+
4413
+ signal(cm, "renderLine", cm, realLine, builder.pre);
4414
+ return builder;
4415
+ }
4416
+
4417
+ var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
4418
+ function buildToken(builder, text, style, startStyle, endStyle, title) {
4419
+ if (!text) return;
4420
+ if (!tokenSpecialChars.test(text)) {
4421
+ builder.col += text.length;
4422
+ var content = document.createTextNode(text);
4423
+ } else {
4424
+ var content = document.createDocumentFragment(), pos = 0;
4425
+ while (true) {
4426
+ tokenSpecialChars.lastIndex = pos;
4427
+ var m = tokenSpecialChars.exec(text);
4428
+ var skipped = m ? m.index - pos : text.length - pos;
4429
+ if (skipped) {
4430
+ content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
4431
+ builder.col += skipped;
4432
+ }
4433
+ if (!m) break;
4434
+ pos += skipped + 1;
4435
+ if (m[0] == "\t") {
4436
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
4437
+ content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
4438
+ builder.col += tabWidth;
4439
+ } else {
4440
+ var token = elt("span", "\u2022", "cm-invalidchar");
4441
+ token.title = "\\u" + m[0].charCodeAt(0).toString(16);
4442
+ content.appendChild(token);
4443
+ builder.col += 1;
4444
+ }
4445
+ }
4446
+ }
4447
+ if (style || startStyle || endStyle || builder.measure) {
4448
+ var fullStyle = style || "";
4449
+ if (startStyle) fullStyle += startStyle;
4450
+ if (endStyle) fullStyle += endStyle;
4451
+ var token = elt("span", [content], fullStyle);
4452
+ if (title) token.title = title;
4453
+ return builder.pre.appendChild(token);
4454
+ }
4455
+ builder.pre.appendChild(content);
4456
+ }
4457
+
4458
+ function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
4459
+ var wrapping = builder.cm.options.lineWrapping;
4460
+ for (var i = 0; i < text.length; ++i) {
4461
+ var ch = text.charAt(i), start = i == 0;
4462
+ if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4463
+ ch = text.slice(i, i + 2);
4464
+ ++i;
4465
+ } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4466
+ builder.pre.appendChild(elt("wbr"));
4467
+ }
4468
+ var old = builder.measure[builder.pos];
4469
+ var span = builder.measure[builder.pos] =
4470
+ buildToken(builder, ch, style,
4471
+ start && startStyle, i == text.length - 1 && endStyle);
4472
+ if (old) span.leftSide = old.leftSide || old;
4473
+ // In IE single-space nodes wrap differently than spaces
4474
+ // embedded in larger text nodes, except when set to
4475
+ // white-space: normal (issue #1268).
4476
+ if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4477
+ i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
4478
+ span.style.whiteSpace = "normal";
4479
+ builder.pos += ch.length;
4480
+ }
4481
+ if (text.length) builder.measuredSomething = true;
4482
+ }
4483
+
4484
+ function buildTokenSplitSpaces(inner) {
4485
+ function split(old) {
4486
+ var out = " ";
4487
+ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
4488
+ out += " ";
4489
+ return out;
4490
+ }
4491
+ return function(builder, text, style, startStyle, endStyle, title) {
4492
+ return inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
4493
+ };
4494
+ }
4495
+
4496
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
4497
+ var widget = !ignoreWidget && marker.replacedWith;
4498
+ if (widget) {
4499
+ if (builder.copyWidgets) widget = widget.cloneNode(true);
4500
+ builder.pre.appendChild(widget);
4501
+ if (builder.measure) {
4502
+ if (size) {
4503
+ builder.measure[builder.pos] = widget;
4504
+ } else {
4505
+ var elt = zeroWidthElement(builder.cm.display.measure);
4506
+ if (marker.type == "bookmark" && !marker.insertLeft)
4507
+ builder.measure[builder.pos] = builder.pre.appendChild(elt);
4508
+ else if (builder.measure[builder.pos])
4509
+ return;
4510
+ else
4511
+ builder.measure[builder.pos] = builder.pre.insertBefore(elt, widget);
4512
+ }
4513
+ builder.measuredSomething = true;
4514
+ }
4515
+ }
4516
+ builder.pos += size;
4517
+ }
4518
+
4519
+ // Outputs a number of spans to make up a line, taking highlighting
4520
+ // and marked text into account.
4521
+ function insertLineContent(line, builder, styles) {
4522
+ var spans = line.markedSpans, allText = line.text, at = 0;
4523
+ if (!spans) {
4524
+ for (var i = 1; i < styles.length; i+=2)
4525
+ builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder));
4526
+ return;
4527
+ }
4528
+
4529
+ var len = allText.length, pos = 0, i = 1, text = "", style;
4530
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
4531
+ for (;;) {
4532
+ if (nextChange == pos) { // Update current marker set
4533
+ spanStyle = spanEndStyle = spanStartStyle = title = "";
4534
+ collapsed = null; nextChange = Infinity;
4535
+ var foundBookmarks = [];
4536
+ for (var j = 0; j < spans.length; ++j) {
4537
+ var sp = spans[j], m = sp.marker;
4538
+ if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
4539
+ if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
4540
+ if (m.className) spanStyle += " " + m.className;
4541
+ if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4542
+ if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4543
+ if (m.title && !title) title = m.title;
4544
+ if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4545
+ collapsed = sp;
4546
+ } else if (sp.from > pos && nextChange > sp.from) {
4547
+ nextChange = sp.from;
4548
+ }
4549
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);
4550
+ }
4551
+ if (collapsed && (collapsed.from || 0) == pos) {
4552
+ buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
4553
+ collapsed.marker, collapsed.from == null);
4554
+ if (collapsed.to == null) return collapsed.marker.find();
4555
+ }
4556
+ if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
4557
+ buildCollapsedSpan(builder, 0, foundBookmarks[j]);
4558
+ }
4559
+ if (pos >= len) break;
4560
+
4561
+ var upto = Math.min(len, nextChange);
4562
+ while (true) {
4563
+ if (text) {
4564
+ var end = pos + text.length;
4565
+ if (!collapsed) {
4566
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text;
4567
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
4568
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
4569
+ }
4570
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
4571
+ pos = end;
4572
+ spanStartStyle = "";
4573
+ }
4574
+ text = allText.slice(at, at = styles[i++]);
4575
+ style = interpretTokenStyle(styles[i++], builder);
4576
+ }
4577
+ }
4578
+ }
4579
+
4580
+ // DOCUMENT DATA STRUCTURE
4581
+
4582
+ function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
4583
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
4584
+ function update(line, text, spans) {
4585
+ updateLine(line, text, spans, estimateHeight);
4586
+ signalLater(line, "change", line, change);
4587
+ }
4588
+
4589
+ var from = change.from, to = change.to, text = change.text;
4590
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
4591
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
4592
+
4593
+ // First adjust the line structure
4594
+ if (from.ch == 0 && to.ch == 0 && lastText == "") {
4595
+ // This is a whole-line replace. Treated specially to make
4596
+ // sure line objects move the way they are supposed to.
4597
+ for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
4598
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4599
+ update(lastLine, lastLine.text, lastSpans);
4600
+ if (nlines) doc.remove(from.line, nlines);
4601
+ if (added.length) doc.insert(from.line, added);
4602
+ } else if (firstLine == lastLine) {
4603
+ if (text.length == 1) {
4604
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4605
+ } else {
4606
+ for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
4607
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4608
+ added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4609
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4610
+ doc.insert(from.line + 1, added);
4611
+ }
4612
+ } else if (text.length == 1) {
4613
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
4614
+ doc.remove(from.line + 1, nlines);
4615
+ } else {
4616
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4617
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4618
+ for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
4619
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
4620
+ if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
4621
+ doc.insert(from.line + 1, added);
4622
+ }
4623
+
4624
+ signalLater(doc, "change", doc, change);
4625
+ setSelection(doc, selAfter.anchor, selAfter.head, null, true);
4626
+ }
4627
+
4628
+ function LeafChunk(lines) {
4629
+ this.lines = lines;
4630
+ this.parent = null;
4631
+ for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
4632
+ lines[i].parent = this;
4633
+ height += lines[i].height;
4634
+ }
4635
+ this.height = height;
4636
+ }
4637
+
4638
+ LeafChunk.prototype = {
4639
+ chunkSize: function() { return this.lines.length; },
4640
+ removeInner: function(at, n) {
4641
+ for (var i = at, e = at + n; i < e; ++i) {
4642
+ var line = this.lines[i];
4643
+ this.height -= line.height;
4644
+ cleanUpLine(line);
4645
+ signalLater(line, "delete");
4646
+ }
4647
+ this.lines.splice(at, n);
4648
+ },
4649
+ collapse: function(lines) {
4650
+ lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
4651
+ },
4652
+ insertInner: function(at, lines, height) {
4653
+ this.height += height;
4654
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
4655
+ for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
4656
+ },
4657
+ iterN: function(at, n, op) {
4658
+ for (var e = at + n; at < e; ++at)
4659
+ if (op(this.lines[at])) return true;
4660
+ }
4661
+ };
4662
+
4663
+ function BranchChunk(children) {
4664
+ this.children = children;
4665
+ var size = 0, height = 0;
4666
+ for (var i = 0, e = children.length; i < e; ++i) {
4667
+ var ch = children[i];
4668
+ size += ch.chunkSize(); height += ch.height;
4669
+ ch.parent = this;
4670
+ }
4671
+ this.size = size;
4672
+ this.height = height;
4673
+ this.parent = null;
4674
+ }
4675
+
4676
+ BranchChunk.prototype = {
4677
+ chunkSize: function() { return this.size; },
4678
+ removeInner: function(at, n) {
4679
+ this.size -= n;
4680
+ for (var i = 0; i < this.children.length; ++i) {
4681
+ var child = this.children[i], sz = child.chunkSize();
4682
+ if (at < sz) {
4683
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
4684
+ child.removeInner(at, rm);
4685
+ this.height -= oldHeight - child.height;
4686
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
4687
+ if ((n -= rm) == 0) break;
4688
+ at = 0;
4689
+ } else at -= sz;
4690
+ }
4691
+ if (this.size - n < 25) {
4692
+ var lines = [];
4693
+ this.collapse(lines);
4694
+ this.children = [new LeafChunk(lines)];
4695
+ this.children[0].parent = this;
4696
+ }
4697
+ },
4698
+ collapse: function(lines) {
4699
+ for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
4700
+ },
4701
+ insertInner: function(at, lines, height) {
4702
+ this.size += lines.length;
4703
+ this.height += height;
4704
+ for (var i = 0, e = this.children.length; i < e; ++i) {
4705
+ var child = this.children[i], sz = child.chunkSize();
4706
+ if (at <= sz) {
4707
+ child.insertInner(at, lines, height);
4708
+ if (child.lines && child.lines.length > 50) {
4709
+ while (child.lines.length > 50) {
4710
+ var spilled = child.lines.splice(child.lines.length - 25, 25);
4711
+ var newleaf = new LeafChunk(spilled);
4712
+ child.height -= newleaf.height;
4713
+ this.children.splice(i + 1, 0, newleaf);
4714
+ newleaf.parent = this;
4715
+ }
4716
+ this.maybeSpill();
4717
+ }
4718
+ break;
4719
+ }
4720
+ at -= sz;
4721
+ }
4722
+ },
4723
+ maybeSpill: function() {
4724
+ if (this.children.length <= 10) return;
4725
+ var me = this;
4726
+ do {
4727
+ var spilled = me.children.splice(me.children.length - 5, 5);
4728
+ var sibling = new BranchChunk(spilled);
4729
+ if (!me.parent) { // Become the parent node
4730
+ var copy = new BranchChunk(me.children);
4731
+ copy.parent = me;
4732
+ me.children = [copy, sibling];
4733
+ me = copy;
4734
+ } else {
4735
+ me.size -= sibling.size;
4736
+ me.height -= sibling.height;
4737
+ var myIndex = indexOf(me.parent.children, me);
4738
+ me.parent.children.splice(myIndex + 1, 0, sibling);
4739
+ }
4740
+ sibling.parent = me.parent;
4741
+ } while (me.children.length > 10);
4742
+ me.parent.maybeSpill();
4743
+ },
4744
+ iterN: function(at, n, op) {
4745
+ for (var i = 0, e = this.children.length; i < e; ++i) {
4746
+ var child = this.children[i], sz = child.chunkSize();
4747
+ if (at < sz) {
4748
+ var used = Math.min(n, sz - at);
4749
+ if (child.iterN(at, used, op)) return true;
4750
+ if ((n -= used) == 0) break;
4751
+ at = 0;
4752
+ } else at -= sz;
4753
+ }
4754
+ }
4755
+ };
4756
+
4757
+ var nextDocId = 0;
4758
+ var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
4759
+ if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
4760
+ if (firstLine == null) firstLine = 0;
4761
+
4762
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
4763
+ this.first = firstLine;
4764
+ this.scrollTop = this.scrollLeft = 0;
4765
+ this.cantEdit = false;
4766
+ this.history = makeHistory();
4767
+ this.cleanGeneration = 1;
4768
+ this.frontier = firstLine;
4769
+ var start = Pos(firstLine, 0);
4770
+ this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
4771
+ this.id = ++nextDocId;
4772
+ this.modeOption = mode;
4773
+
4774
+ if (typeof text == "string") text = splitLines(text);
4775
+ updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
4776
+ };
4777
+
4778
+ Doc.prototype = createObj(BranchChunk.prototype, {
4779
+ constructor: Doc,
4780
+ iter: function(from, to, op) {
4781
+ if (op) this.iterN(from - this.first, to - from, op);
4782
+ else this.iterN(this.first, this.first + this.size, from);
4783
+ },
4784
+
4785
+ insert: function(at, lines) {
4786
+ var height = 0;
4787
+ for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
4788
+ this.insertInner(at - this.first, lines, height);
4789
+ },
4790
+ remove: function(at, n) { this.removeInner(at - this.first, n); },
4791
+
4792
+ getValue: function(lineSep) {
4793
+ var lines = getLines(this, this.first, this.first + this.size);
4794
+ if (lineSep === false) return lines;
4795
+ return lines.join(lineSep || "\n");
4796
+ },
4797
+ setValue: function(code) {
4798
+ var top = Pos(this.first, 0), last = this.first + this.size - 1;
4799
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
4800
+ text: splitLines(code), origin: "setValue"},
4801
+ {head: top, anchor: top}, true);
4802
+ },
4803
+ replaceRange: function(code, from, to, origin) {
4804
+ from = clipPos(this, from);
4805
+ to = to ? clipPos(this, to) : from;
4806
+ replaceRange(this, code, from, to, origin);
4807
+ },
4808
+ getRange: function(from, to, lineSep) {
4809
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
4810
+ if (lineSep === false) return lines;
4811
+ return lines.join(lineSep || "\n");
4812
+ },
4813
+
4814
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
4815
+ setLine: function(line, text) {
4816
+ if (isLine(this, line))
4817
+ replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
4818
+ },
4819
+ removeLine: function(line) {
4820
+ if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));
4821
+ else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));
4822
+ },
4823
+
4824
+ getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
4825
+ getLineNumber: function(line) {return lineNo(line);},
4826
+
4827
+ getLineHandleVisualStart: function(line) {
4828
+ if (typeof line == "number") line = getLine(this, line);
4829
+ return visualLine(this, line);
4830
+ },
4831
+
4832
+ lineCount: function() {return this.size;},
4833
+ firstLine: function() {return this.first;},
4834
+ lastLine: function() {return this.first + this.size - 1;},
4835
+
4836
+ clipPos: function(pos) {return clipPos(this, pos);},
4837
+
4838
+ getCursor: function(start) {
4839
+ var sel = this.sel, pos;
4840
+ if (start == null || start == "head") pos = sel.head;
4841
+ else if (start == "anchor") pos = sel.anchor;
4842
+ else if (start == "end" || start === false) pos = sel.to;
4843
+ else pos = sel.from;
4844
+ return copyPos(pos);
4845
+ },
4846
+ somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
4847
+
4848
+ setCursor: docOperation(function(line, ch, extend) {
4849
+ var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
4850
+ if (extend) extendSelection(this, pos);
4851
+ else setSelection(this, pos, pos);
4852
+ }),
4853
+ setSelection: docOperation(function(anchor, head, bias) {
4854
+ setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), bias);
4855
+ }),
4856
+ extendSelection: docOperation(function(from, to, bias) {
4857
+ extendSelection(this, clipPos(this, from), to && clipPos(this, to), bias);
4858
+ }),
4859
+
4860
+ getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
4861
+ replaceSelection: function(code, collapse, origin) {
4862
+ makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
4863
+ },
4864
+ undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
4865
+ redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
4866
+
4867
+ setExtending: function(val) {this.sel.extend = val;},
4868
+
4869
+ historySize: function() {
4870
+ var hist = this.history;
4871
+ return {undo: hist.done.length, redo: hist.undone.length};
4872
+ },
4873
+ clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4874
+
4875
+ markClean: function() {
4876
+ this.cleanGeneration = this.changeGeneration();
4877
+ },
4878
+ changeGeneration: function() {
4879
+ this.history.lastOp = this.history.lastOrigin = null;
4880
+ return this.history.generation;
4881
+ },
4882
+ isClean: function (gen) {
4883
+ return this.history.generation == (gen || this.cleanGeneration);
4884
+ },
4885
+
4886
+ getHistory: function() {
4887
+ return {done: copyHistoryArray(this.history.done),
4888
+ undone: copyHistoryArray(this.history.undone)};
4889
+ },
4890
+ setHistory: function(histData) {
4891
+ var hist = this.history = makeHistory(this.history.maxGeneration);
4892
+ hist.done = histData.done.slice(0);
4893
+ hist.undone = histData.undone.slice(0);
4894
+ },
4895
+
4896
+ markText: function(from, to, options) {
4897
+ return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
4898
+ },
4899
+ setBookmark: function(pos, options) {
4900
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4901
+ insertLeft: options && options.insertLeft};
4902
+ pos = clipPos(this, pos);
4903
+ return markText(this, pos, pos, realOpts, "bookmark");
4904
+ },
4905
+ findMarksAt: function(pos) {
4906
+ pos = clipPos(this, pos);
4907
+ var markers = [], spans = getLine(this, pos.line).markedSpans;
4908
+ if (spans) for (var i = 0; i < spans.length; ++i) {
4909
+ var span = spans[i];
4910
+ if ((span.from == null || span.from <= pos.ch) &&
4911
+ (span.to == null || span.to >= pos.ch))
4912
+ markers.push(span.marker.parent || span.marker);
4913
+ }
4914
+ return markers;
4915
+ },
4916
+ getAllMarks: function() {
4917
+ var markers = [];
4918
+ this.iter(function(line) {
4919
+ var sps = line.markedSpans;
4920
+ if (sps) for (var i = 0; i < sps.length; ++i)
4921
+ if (sps[i].from != null) markers.push(sps[i].marker);
4922
+ });
4923
+ return markers;
4924
+ },
4925
+
4926
+ posFromIndex: function(off) {
4927
+ var ch, lineNo = this.first;
4928
+ this.iter(function(line) {
4929
+ var sz = line.text.length + 1;
4930
+ if (sz > off) { ch = off; return true; }
4931
+ off -= sz;
4932
+ ++lineNo;
4933
+ });
4934
+ return clipPos(this, Pos(lineNo, ch));
4935
+ },
4936
+ indexFromPos: function (coords) {
4937
+ coords = clipPos(this, coords);
4938
+ var index = coords.ch;
4939
+ if (coords.line < this.first || coords.ch < 0) return 0;
4940
+ this.iter(this.first, coords.line, function (line) {
4941
+ index += line.text.length + 1;
4942
+ });
4943
+ return index;
4944
+ },
4945
+
4946
+ copy: function(copyHistory) {
4947
+ var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
4948
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
4949
+ doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
4950
+ shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
4951
+ if (copyHistory) {
4952
+ doc.history.undoDepth = this.history.undoDepth;
4953
+ doc.setHistory(this.getHistory());
4954
+ }
4955
+ return doc;
4956
+ },
4957
+
4958
+ linkedDoc: function(options) {
4959
+ if (!options) options = {};
4960
+ var from = this.first, to = this.first + this.size;
4961
+ if (options.from != null && options.from > from) from = options.from;
4962
+ if (options.to != null && options.to < to) to = options.to;
4963
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
4964
+ if (options.sharedHist) copy.history = this.history;
4965
+ (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
4966
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
4967
+ return copy;
4968
+ },
4969
+ unlinkDoc: function(other) {
4970
+ if (other instanceof CodeMirror) other = other.doc;
4971
+ if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
4972
+ var link = this.linked[i];
4973
+ if (link.doc != other) continue;
4974
+ this.linked.splice(i, 1);
4975
+ other.unlinkDoc(this);
4976
+ break;
4977
+ }
4978
+ // If the histories were shared, split them again
4979
+ if (other.history == this.history) {
4980
+ var splitIds = [other.id];
4981
+ linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
4982
+ other.history = makeHistory();
4983
+ other.history.done = copyHistoryArray(this.history.done, splitIds);
4984
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds);
4985
+ }
4986
+ },
4987
+ iterLinkedDocs: function(f) {linkedDocs(this, f);},
4988
+
4989
+ getMode: function() {return this.mode;},
4990
+ getEditor: function() {return this.cm;}
4991
+ });
4992
+
4993
+ Doc.prototype.eachLine = Doc.prototype.iter;
4994
+
4995
+ // The Doc methods that should be available on CodeMirror instances
4996
+ var dontDelegate = "iter insert remove copy getEditor".split(" ");
4997
+ for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
4998
+ CodeMirror.prototype[prop] = (function(method) {
4999
+ return function() {return method.apply(this.doc, arguments);};
5000
+ })(Doc.prototype[prop]);
5001
+
5002
+ eventMixin(Doc);
5003
+
5004
+ function linkedDocs(doc, f, sharedHistOnly) {
5005
+ function propagate(doc, skip, sharedHist) {
5006
+ if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
5007
+ var rel = doc.linked[i];
5008
+ if (rel.doc == skip) continue;
5009
+ var shared = sharedHist && rel.sharedHist;
5010
+ if (sharedHistOnly && !shared) continue;
5011
+ f(rel.doc, shared);
5012
+ propagate(rel.doc, doc, shared);
5013
+ }
5014
+ }
5015
+ propagate(doc, null, true);
5016
+ }
5017
+
5018
+ function attachDoc(cm, doc) {
5019
+ if (doc.cm) throw new Error("This document is already in use.");
5020
+ cm.doc = doc;
5021
+ doc.cm = cm;
5022
+ estimateLineHeights(cm);
5023
+ loadMode(cm);
5024
+ if (!cm.options.lineWrapping) computeMaxLength(cm);
5025
+ cm.options.mode = doc.modeOption;
5026
+ regChange(cm);
5027
+ }
5028
+
5029
+ // LINE UTILITIES
5030
+
5031
+ function getLine(chunk, n) {
5032
+ n -= chunk.first;
5033
+ while (!chunk.lines) {
5034
+ for (var i = 0;; ++i) {
5035
+ var child = chunk.children[i], sz = child.chunkSize();
5036
+ if (n < sz) { chunk = child; break; }
5037
+ n -= sz;
5038
+ }
5039
+ }
5040
+ return chunk.lines[n];
5041
+ }
5042
+
5043
+ function getBetween(doc, start, end) {
5044
+ var out = [], n = start.line;
5045
+ doc.iter(start.line, end.line + 1, function(line) {
5046
+ var text = line.text;
5047
+ if (n == end.line) text = text.slice(0, end.ch);
5048
+ if (n == start.line) text = text.slice(start.ch);
5049
+ out.push(text);
5050
+ ++n;
5051
+ });
5052
+ return out;
5053
+ }
5054
+ function getLines(doc, from, to) {
5055
+ var out = [];
5056
+ doc.iter(from, to, function(line) { out.push(line.text); });
5057
+ return out;
5058
+ }
5059
+
5060
+ function updateLineHeight(line, height) {
5061
+ var diff = height - line.height;
5062
+ for (var n = line; n; n = n.parent) n.height += diff;
5063
+ }
5064
+
5065
+ function lineNo(line) {
5066
+ if (line.parent == null) return null;
5067
+ var cur = line.parent, no = indexOf(cur.lines, line);
5068
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
5069
+ for (var i = 0;; ++i) {
5070
+ if (chunk.children[i] == cur) break;
5071
+ no += chunk.children[i].chunkSize();
5072
+ }
5073
+ }
5074
+ return no + cur.first;
5075
+ }
5076
+
5077
+ function lineAtHeight(chunk, h) {
5078
+ var n = chunk.first;
5079
+ outer: do {
5080
+ for (var i = 0, e = chunk.children.length; i < e; ++i) {
5081
+ var child = chunk.children[i], ch = child.height;
5082
+ if (h < ch) { chunk = child; continue outer; }
5083
+ h -= ch;
5084
+ n += child.chunkSize();
5085
+ }
5086
+ return n;
5087
+ } while (!chunk.lines);
5088
+ for (var i = 0, e = chunk.lines.length; i < e; ++i) {
5089
+ var line = chunk.lines[i], lh = line.height;
5090
+ if (h < lh) break;
5091
+ h -= lh;
5092
+ }
5093
+ return n + i;
5094
+ }
5095
+
5096
+ function heightAtLine(cm, lineObj) {
5097
+ lineObj = visualLine(cm.doc, lineObj);
5098
+
5099
+ var h = 0, chunk = lineObj.parent;
5100
+ for (var i = 0; i < chunk.lines.length; ++i) {
5101
+ var line = chunk.lines[i];
5102
+ if (line == lineObj) break;
5103
+ else h += line.height;
5104
+ }
5105
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
5106
+ for (var i = 0; i < p.children.length; ++i) {
5107
+ var cur = p.children[i];
5108
+ if (cur == chunk) break;
5109
+ else h += cur.height;
5110
+ }
5111
+ }
5112
+ return h;
5113
+ }
5114
+
5115
+ function getOrder(line) {
5116
+ var order = line.order;
5117
+ if (order == null) order = line.order = bidiOrdering(line.text);
5118
+ return order;
5119
+ }
5120
+
5121
+ // HISTORY
5122
+
5123
+ function makeHistory(startGen) {
5124
+ return {
5125
+ // Arrays of history events. Doing something adds an event to
5126
+ // done and clears undo. Undoing moves events from done to
5127
+ // undone, redoing moves them in the other direction.
5128
+ done: [], undone: [], undoDepth: Infinity,
5129
+ // Used to track when changes can be merged into a single undo
5130
+ // event
5131
+ lastTime: 0, lastOp: null, lastOrigin: null,
5132
+ // Used by the isClean() method
5133
+ generation: startGen || 1, maxGeneration: startGen || 1
5134
+ };
5135
+ }
5136
+
5137
+ function attachLocalSpans(doc, change, from, to) {
5138
+ var existing = change["spans_" + doc.id], n = 0;
5139
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
5140
+ if (line.markedSpans)
5141
+ (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
5142
+ ++n;
5143
+ });
5144
+ }
5145
+
5146
+ function historyChangeFromChange(doc, change) {
5147
+ var from = { line: change.from.line, ch: change.from.ch };
5148
+ var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
5149
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
5150
+ linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
5151
+ return histChange;
5152
+ }
5153
+
5154
+ function addToHistory(doc, change, selAfter, opId) {
5155
+ var hist = doc.history;
5156
+ hist.undone.length = 0;
5157
+ var time = +new Date, cur = lst(hist.done);
5158
+
5159
+ if (cur &&
5160
+ (hist.lastOp == opId ||
5161
+ hist.lastOrigin == change.origin && change.origin &&
5162
+ ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||
5163
+ change.origin.charAt(0) == "*"))) {
5164
+ // Merge this change into the last event
5165
+ var last = lst(cur.changes);
5166
+ if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
5167
+ // Optimized case for simple insertion -- don't want to add
5168
+ // new changesets for every character typed
5169
+ last.to = changeEnd(change);
5170
+ } else {
5171
+ // Add new sub-event
5172
+ cur.changes.push(historyChangeFromChange(doc, change));
5173
+ }
5174
+ cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
5175
+ } else {
5176
+ // Can not be merged, start a new event.
5177
+ cur = {changes: [historyChangeFromChange(doc, change)],
5178
+ generation: hist.generation,
5179
+ anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
5180
+ anchorAfter: selAfter.anchor, headAfter: selAfter.head};
5181
+ hist.done.push(cur);
5182
+ hist.generation = ++hist.maxGeneration;
5183
+ while (hist.done.length > hist.undoDepth)
5184
+ hist.done.shift();
5185
+ }
5186
+ hist.lastTime = time;
5187
+ hist.lastOp = opId;
5188
+ hist.lastOrigin = change.origin;
5189
+ }
5190
+
5191
+ function removeClearedSpans(spans) {
5192
+ if (!spans) return null;
5193
+ for (var i = 0, out; i < spans.length; ++i) {
5194
+ if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
5195
+ else if (out) out.push(spans[i]);
5196
+ }
5197
+ return !out ? spans : out.length ? out : null;
5198
+ }
5199
+
5200
+ function getOldSpans(doc, change) {
5201
+ var found = change["spans_" + doc.id];
5202
+ if (!found) return null;
5203
+ for (var i = 0, nw = []; i < change.text.length; ++i)
5204
+ nw.push(removeClearedSpans(found[i]));
5205
+ return nw;
5206
+ }
5207
+
5208
+ // Used both to provide a JSON-safe object in .getHistory, and, when
5209
+ // detaching a document, to split the history in two
5210
+ function copyHistoryArray(events, newGroup) {
5211
+ for (var i = 0, copy = []; i < events.length; ++i) {
5212
+ var event = events[i], changes = event.changes, newChanges = [];
5213
+ copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
5214
+ anchorAfter: event.anchorAfter, headAfter: event.headAfter});
5215
+ for (var j = 0; j < changes.length; ++j) {
5216
+ var change = changes[j], m;
5217
+ newChanges.push({from: change.from, to: change.to, text: change.text});
5218
+ if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
5219
+ if (indexOf(newGroup, Number(m[1])) > -1) {
5220
+ lst(newChanges)[prop] = change[prop];
5221
+ delete change[prop];
5222
+ }
5223
+ }
5224
+ }
5225
+ }
5226
+ return copy;
5227
+ }
5228
+
5229
+ // Rebasing/resetting history to deal with externally-sourced changes
5230
+
5231
+ function rebaseHistSel(pos, from, to, diff) {
5232
+ if (to < pos.line) {
5233
+ pos.line += diff;
5234
+ } else if (from < pos.line) {
5235
+ pos.line = from;
5236
+ pos.ch = 0;
5237
+ }
5238
+ }
5239
+
5240
+ // Tries to rebase an array of history events given a change in the
5241
+ // document. If the change touches the same lines as the event, the
5242
+ // event, and everything 'behind' it, is discarded. If the change is
5243
+ // before the event, the event's positions are updated. Uses a
5244
+ // copy-on-write scheme for the positions, to avoid having to
5245
+ // reallocate them all on every rebase, but also avoid problems with
5246
+ // shared position objects being unsafely updated.
5247
+ function rebaseHistArray(array, from, to, diff) {
5248
+ for (var i = 0; i < array.length; ++i) {
5249
+ var sub = array[i], ok = true;
5250
+ for (var j = 0; j < sub.changes.length; ++j) {
5251
+ var cur = sub.changes[j];
5252
+ if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
5253
+ if (to < cur.from.line) {
5254
+ cur.from.line += diff;
5255
+ cur.to.line += diff;
5256
+ } else if (from <= cur.to.line) {
5257
+ ok = false;
5258
+ break;
5259
+ }
5260
+ }
5261
+ if (!sub.copied) {
5262
+ sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
5263
+ sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
5264
+ sub.copied = true;
5265
+ }
5266
+ if (!ok) {
5267
+ array.splice(0, i + 1);
5268
+ i = 0;
5269
+ } else {
5270
+ rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
5271
+ rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
5272
+ }
5273
+ }
5274
+ }
5275
+
5276
+ function rebaseHist(hist, change) {
5277
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
5278
+ rebaseHistArray(hist.done, from, to, diff);
5279
+ rebaseHistArray(hist.undone, from, to, diff);
5280
+ }
5281
+
5282
+ // EVENT OPERATORS
5283
+
5284
+ function stopMethod() {e_stop(this);}
5285
+ // Ensure an event has a stop method.
5286
+ function addStop(event) {
5287
+ if (!event.stop) event.stop = stopMethod;
5288
+ return event;
5289
+ }
5290
+
5291
+ function e_preventDefault(e) {
5292
+ if (e.preventDefault) e.preventDefault();
5293
+ else e.returnValue = false;
5294
+ }
5295
+ function e_stopPropagation(e) {
5296
+ if (e.stopPropagation) e.stopPropagation();
5297
+ else e.cancelBubble = true;
5298
+ }
5299
+ function e_defaultPrevented(e) {
5300
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5301
+ }
5302
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5303
+ CodeMirror.e_stop = e_stop;
5304
+ CodeMirror.e_preventDefault = e_preventDefault;
5305
+ CodeMirror.e_stopPropagation = e_stopPropagation;
5306
+
5307
+ function e_target(e) {return e.target || e.srcElement;}
5308
+ function e_button(e) {
5309
+ var b = e.which;
5310
+ if (b == null) {
5311
+ if (e.button & 1) b = 1;
5312
+ else if (e.button & 2) b = 3;
5313
+ else if (e.button & 4) b = 2;
5314
+ }
5315
+ if (mac && e.ctrlKey && b == 1) b = 3;
5316
+ return b;
5317
+ }
5318
+
5319
+ // EVENT HANDLING
5320
+
5321
+ function on(emitter, type, f) {
5322
+ if (emitter.addEventListener)
5323
+ emitter.addEventListener(type, f, false);
5324
+ else if (emitter.attachEvent)
5325
+ emitter.attachEvent("on" + type, f);
5326
+ else {
5327
+ var map = emitter._handlers || (emitter._handlers = {});
5328
+ var arr = map[type] || (map[type] = []);
5329
+ arr.push(f);
5330
+ }
5331
+ }
5332
+
5333
+ function off(emitter, type, f) {
5334
+ if (emitter.removeEventListener)
5335
+ emitter.removeEventListener(type, f, false);
5336
+ else if (emitter.detachEvent)
5337
+ emitter.detachEvent("on" + type, f);
5338
+ else {
5339
+ var arr = emitter._handlers && emitter._handlers[type];
5340
+ if (!arr) return;
5341
+ for (var i = 0; i < arr.length; ++i)
5342
+ if (arr[i] == f) { arr.splice(i, 1); break; }
5343
+ }
5344
+ }
5345
+
5346
+ function signal(emitter, type /*, values...*/) {
5347
+ var arr = emitter._handlers && emitter._handlers[type];
5348
+ if (!arr) return;
5349
+ var args = Array.prototype.slice.call(arguments, 2);
5350
+ for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
5351
+ }
5352
+
5353
+ var delayedCallbacks, delayedCallbackDepth = 0;
5354
+ function signalLater(emitter, type /*, values...*/) {
5355
+ var arr = emitter._handlers && emitter._handlers[type];
5356
+ if (!arr) return;
5357
+ var args = Array.prototype.slice.call(arguments, 2);
5358
+ if (!delayedCallbacks) {
5359
+ ++delayedCallbackDepth;
5360
+ delayedCallbacks = [];
5361
+ setTimeout(fireDelayed, 0);
5362
+ }
5363
+ function bnd(f) {return function(){f.apply(null, args);};};
5364
+ for (var i = 0; i < arr.length; ++i)
5365
+ delayedCallbacks.push(bnd(arr[i]));
5366
+ }
5367
+
5368
+ function signalDOMEvent(cm, e, override) {
5369
+ signal(cm, override || e.type, cm, e);
5370
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
5371
+ }
5372
+
5373
+ function fireDelayed() {
5374
+ --delayedCallbackDepth;
5375
+ var delayed = delayedCallbacks;
5376
+ delayedCallbacks = null;
5377
+ for (var i = 0; i < delayed.length; ++i) delayed[i]();
5378
+ }
5379
+
5380
+ function hasHandler(emitter, type) {
5381
+ var arr = emitter._handlers && emitter._handlers[type];
5382
+ return arr && arr.length > 0;
5383
+ }
5384
+
5385
+ CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
5386
+
5387
+ function eventMixin(ctor) {
5388
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
5389
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
5390
+ }
5391
+
5392
+ // MISC UTILITIES
5393
+
5394
+ // Number of pixels added to scroller and sizer to hide scrollbar
5395
+ var scrollerCutOff = 30;
5396
+
5397
+ // Returned or thrown by various protocols to signal 'I'm not
5398
+ // handling this'.
5399
+ var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
5400
+
5401
+ function Delayed() {this.id = null;}
5402
+ Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
5403
+
5404
+ // Counts the column offset in a string, taking tabs into account.
5405
+ // Used mostly to find indentation.
5406
+ function countColumn(string, end, tabSize, startIndex, startValue) {
5407
+ if (end == null) {
5408
+ end = string.search(/[^\s\u00a0]/);
5409
+ if (end == -1) end = string.length;
5410
+ }
5411
+ for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
5412
+ if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
5413
+ else ++n;
5414
+ }
5415
+ return n;
5416
+ }
5417
+ CodeMirror.countColumn = countColumn;
5418
+
5419
+ var spaceStrs = [""];
5420
+ function spaceStr(n) {
5421
+ while (spaceStrs.length <= n)
5422
+ spaceStrs.push(lst(spaceStrs) + " ");
5423
+ return spaceStrs[n];
5424
+ }
5425
+
5426
+ function lst(arr) { return arr[arr.length-1]; }
5427
+
5428
+ function selectInput(node) {
5429
+ if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5430
+ node.selectionStart = 0;
5431
+ node.selectionEnd = node.value.length;
5432
+ } else {
5433
+ // Suppress mysterious IE10 errors
5434
+ try { node.select(); }
5435
+ catch(_e) {}
5436
+ }
5437
+ }
5438
+
5439
+ function indexOf(collection, elt) {
5440
+ if (collection.indexOf) return collection.indexOf(elt);
5441
+ for (var i = 0, e = collection.length; i < e; ++i)
5442
+ if (collection[i] == elt) return i;
5443
+ return -1;
5444
+ }
5445
+
5446
+ function createObj(base, props) {
5447
+ function Obj() {}
5448
+ Obj.prototype = base;
5449
+ var inst = new Obj();
5450
+ if (props) copyObj(props, inst);
5451
+ return inst;
5452
+ }
5453
+
5454
+ function copyObj(obj, target) {
5455
+ if (!target) target = {};
5456
+ for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
5457
+ return target;
5458
+ }
5459
+
5460
+ function emptyArray(size) {
5461
+ for (var a = [], i = 0; i < size; ++i) a.push(undefined);
5462
+ return a;
5463
+ }
5464
+
5465
+ function bind(f) {
5466
+ var args = Array.prototype.slice.call(arguments, 1);
5467
+ return function(){return f.apply(null, args);};
5468
+ }
5469
+
5470
+ var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
5471
+ function isWordChar(ch) {
5472
+ return /\w/.test(ch) || ch > "\x80" &&
5473
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
5474
+ }
5475
+
5476
+ function isEmpty(obj) {
5477
+ for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
5478
+ return true;
5479
+ }
5480
+
5481
+ var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
5482
+
5483
+ // DOM UTILITIES
5484
+
5485
+ function elt(tag, content, className, style) {
5486
+ var e = document.createElement(tag);
5487
+ if (className) e.className = className;
5488
+ if (style) e.style.cssText = style;
5489
+ if (typeof content == "string") setTextContent(e, content);
5490
+ else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
5491
+ return e;
5492
+ }
5493
+
5494
+ function removeChildren(e) {
5495
+ for (var count = e.childNodes.length; count > 0; --count)
5496
+ e.removeChild(e.firstChild);
5497
+ return e;
5498
+ }
5499
+
5500
+ function removeChildrenAndAdd(parent, e) {
5501
+ return removeChildren(parent).appendChild(e);
5502
+ }
5503
+
5504
+ function setTextContent(e, str) {
5505
+ if (ie_lt9) {
5506
+ e.innerHTML = "";
5507
+ e.appendChild(document.createTextNode(str));
5508
+ } else e.textContent = str;
5509
+ }
5510
+
5511
+ function getRect(node) {
5512
+ return node.getBoundingClientRect();
5513
+ }
5514
+ CodeMirror.replaceGetRect = function(f) { getRect = f; };
5515
+
5516
+ // FEATURE DETECTION
5517
+
5518
+ // Detect drag-and-drop
5519
+ var dragAndDrop = function() {
5520
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
5521
+ // couldn't get it to work yet.
5522
+ if (ie_lt9) return false;
5523
+ var div = elt('div');
5524
+ return "draggable" in div || "dragDrop" in div;
5525
+ }();
5526
+
5527
+ // For a reason I have yet to figure out, some browsers disallow
5528
+ // word wrapping between certain characters *only* if a new inline
5529
+ // element is started between them. This makes it hard to reliably
5530
+ // measure the position of things, since that requires inserting an
5531
+ // extra span. This terribly fragile set of tests matches the
5532
+ // character combinations that suffer from this phenomenon on the
5533
+ // various browsers.
5534
+ function spanAffectsWrapping() { return false; }
5535
+ if (gecko) // Only for "$'"
5536
+ spanAffectsWrapping = function(str, i) {
5537
+ return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;
5538
+ };
5539
+ else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
5540
+ spanAffectsWrapping = function(str, i) {
5541
+ return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
5542
+ };
5543
+ else if (webkit && /Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
5544
+ spanAffectsWrapping = function(str, i) {
5545
+ var code = str.charCodeAt(i - 1);
5546
+ return code >= 8208 && code <= 8212;
5547
+ };
5548
+ else if (webkit)
5549
+ spanAffectsWrapping = function(str, i) {
5550
+ if (i > 1 && str.charCodeAt(i - 1) == 45) {
5551
+ if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5552
+ if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5553
+ }
5554
+ return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5555
+ };
5556
+
5557
+ var knownScrollbarWidth;
5558
+ function scrollbarWidth(measure) {
5559
+ if (knownScrollbarWidth != null) return knownScrollbarWidth;
5560
+ var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
5561
+ removeChildrenAndAdd(measure, test);
5562
+ if (test.offsetWidth)
5563
+ knownScrollbarWidth = test.offsetHeight - test.clientHeight;
5564
+ return knownScrollbarWidth || 0;
5565
+ }
5566
+
5567
+ var zwspSupported;
5568
+ function zeroWidthElement(measure) {
5569
+ if (zwspSupported == null) {
5570
+ var test = elt("span", "\u200b");
5571
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
5572
+ if (measure.firstChild.offsetHeight != 0)
5573
+ zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
5574
+ }
5575
+ if (zwspSupported) return elt("span", "\u200b");
5576
+ else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
5577
+ }
5578
+
5579
+ // See if "".split is the broken IE version, if so, provide an
5580
+ // alternative way to split lines.
5581
+ var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
5582
+ var pos = 0, result = [], l = string.length;
5583
+ while (pos <= l) {
5584
+ var nl = string.indexOf("\n", pos);
5585
+ if (nl == -1) nl = string.length;
5586
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
5587
+ var rt = line.indexOf("\r");
5588
+ if (rt != -1) {
5589
+ result.push(line.slice(0, rt));
5590
+ pos += rt + 1;
5591
+ } else {
5592
+ result.push(line);
5593
+ pos = nl + 1;
5594
+ }
5595
+ }
5596
+ return result;
5597
+ } : function(string){return string.split(/\r\n?|\n/);};
5598
+ CodeMirror.splitLines = splitLines;
5599
+
5600
+ var hasSelection = window.getSelection ? function(te) {
5601
+ try { return te.selectionStart != te.selectionEnd; }
5602
+ catch(e) { return false; }
5603
+ } : function(te) {
5604
+ try {var range = te.ownerDocument.selection.createRange();}
5605
+ catch(e) {}
5606
+ if (!range || range.parentElement() != te) return false;
5607
+ return range.compareEndPoints("StartToEnd", range) != 0;
5608
+ };
5609
+
5610
+ var hasCopyEvent = (function() {
5611
+ var e = elt("div");
5612
+ if ("oncopy" in e) return true;
5613
+ e.setAttribute("oncopy", "return;");
5614
+ return typeof e.oncopy == 'function';
5615
+ })();
5616
+
5617
+ // KEY NAMING
5618
+
5619
+ var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
5620
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
5621
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
5622
+ 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
5623
+ 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
5624
+ 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
5625
+ 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
5626
+ CodeMirror.keyNames = keyNames;
5627
+ (function() {
5628
+ // Number keys
5629
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
5630
+ // Alphabetic keys
5631
+ for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
5632
+ // Function keys
5633
+ for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
5634
+ })();
5635
+
5636
+ // BIDI HELPERS
5637
+
5638
+ function iterateBidiSections(order, from, to, f) {
5639
+ if (!order) return f(from, to, "ltr");
5640
+ var found = false;
5641
+ for (var i = 0; i < order.length; ++i) {
5642
+ var part = order[i];
5643
+ if (part.from < to && part.to > from || from == to && part.to == from) {
5644
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
5645
+ found = true;
5646
+ }
5647
+ }
5648
+ if (!found) f(from, to, "ltr");
5649
+ }
5650
+
5651
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
5652
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
5653
+
5654
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
5655
+ function lineRight(line) {
5656
+ var order = getOrder(line);
5657
+ if (!order) return line.text.length;
5658
+ return bidiRight(lst(order));
5659
+ }
5660
+
5661
+ function lineStart(cm, lineN) {
5662
+ var line = getLine(cm.doc, lineN);
5663
+ var visual = visualLine(cm.doc, line);
5664
+ if (visual != line) lineN = lineNo(visual);
5665
+ var order = getOrder(visual);
5666
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
5667
+ return Pos(lineN, ch);
5668
+ }
5669
+ function lineEnd(cm, lineN) {
5670
+ var merged, line;
5671
+ while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
5672
+ lineN = merged.find().to.line;
5673
+ var order = getOrder(line);
5674
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
5675
+ return Pos(lineN, ch);
5676
+ }
5677
+
5678
+ function compareBidiLevel(order, a, b) {
5679
+ var linedir = order[0].level;
5680
+ if (a == linedir) return true;
5681
+ if (b == linedir) return false;
5682
+ return a < b;
5683
+ }
5684
+ var bidiOther;
5685
+ function getBidiPartAt(order, pos) {
5686
+ for (var i = 0, found; i < order.length; ++i) {
5687
+ var cur = order[i];
5688
+ if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
5689
+ if (cur.from == pos || cur.to == pos) {
5690
+ if (found == null) {
5691
+ found = i;
5692
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) {
5693
+ bidiOther = found;
5694
+ return i;
5695
+ } else {
5696
+ bidiOther = i;
5697
+ return found;
5698
+ }
5699
+ }
5700
+ }
5701
+ bidiOther = null;
5702
+ return found;
5703
+ }
5704
+
5705
+ function moveInLine(line, pos, dir, byUnit) {
5706
+ if (!byUnit) return pos + dir;
5707
+ do pos += dir;
5708
+ while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5709
+ return pos;
5710
+ }
5711
+
5712
+ // This is somewhat involved. It is needed in order to move
5713
+ // 'visually' through bi-directional text -- i.e., pressing left
5714
+ // should make the cursor go left, even when in RTL text. The
5715
+ // tricky part is the 'jumps', where RTL and LTR text touch each
5716
+ // other. This often requires the cursor offset to move more than
5717
+ // one unit, in order to visually move one unit.
5718
+ function moveVisually(line, start, dir, byUnit) {
5719
+ var bidi = getOrder(line);
5720
+ if (!bidi) return moveLogically(line, start, dir, byUnit);
5721
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos];
5722
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
5723
+
5724
+ for (;;) {
5725
+ if (target > part.from && target < part.to) return target;
5726
+ if (target == part.from || target == part.to) {
5727
+ if (getBidiPartAt(bidi, target) == pos) return target;
5728
+ part = bidi[pos += dir];
5729
+ return (dir > 0) == part.level % 2 ? part.to : part.from;
5730
+ } else {
5731
+ part = bidi[pos += dir];
5732
+ if (!part) return null;
5733
+ if ((dir > 0) == part.level % 2)
5734
+ target = moveInLine(line, part.to, -1, byUnit);
5735
+ else
5736
+ target = moveInLine(line, part.from, 1, byUnit);
5737
+ }
5738
+ }
5739
+ }
5740
+
5741
+ function moveLogically(line, start, dir, byUnit) {
5742
+ var target = start + dir;
5743
+ if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
5744
+ return target < 0 || target > line.text.length ? null : target;
5745
+ }
5746
+
5747
+ // Bidirectional ordering algorithm
5748
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
5749
+ // that this (partially) implements.
5750
+
5751
+ // One-char codes used for character types:
5752
+ // L (L): Left-to-Right
5753
+ // R (R): Right-to-Left
5754
+ // r (AL): Right-to-Left Arabic
5755
+ // 1 (EN): European Number
5756
+ // + (ES): European Number Separator
5757
+ // % (ET): European Number Terminator
5758
+ // n (AN): Arabic Number
5759
+ // , (CS): Common Number Separator
5760
+ // m (NSM): Non-Spacing Mark
5761
+ // b (BN): Boundary Neutral
5762
+ // s (B): Paragraph Separator
5763
+ // t (S): Segment Separator
5764
+ // w (WS): Whitespace
5765
+ // N (ON): Other Neutrals
5766
+
5767
+ // Returns null if characters are ordered as they appear
5768
+ // (left-to-right), or an array of sections ({from, to, level}
5769
+ // objects) in the order in which they occur visually.
5770
+ var bidiOrdering = (function() {
5771
+ // Character types for codepoints 0 to 0xff
5772
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
5773
+ // Character types for codepoints 0x600 to 0x6ff
5774
+ var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
5775
+ function charType(code) {
5776
+ if (code <= 0xff) return lowTypes.charAt(code);
5777
+ else if (0x590 <= code && code <= 0x5f4) return "R";
5778
+ else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
5779
+ else if (0x700 <= code && code <= 0x8ac) return "r";
5780
+ else return "L";
5781
+ }
5782
+
5783
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
5784
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
5785
+ // Browsers seem to always treat the boundaries of block elements as being L.
5786
+ var outerType = "L";
5787
+
5788
+ return function(str) {
5789
+ if (!bidiRE.test(str)) return false;
5790
+ var len = str.length, types = [];
5791
+ for (var i = 0, type; i < len; ++i)
5792
+ types.push(type = charType(str.charCodeAt(i)));
5793
+
5794
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
5795
+ // change the type of the NSM to the type of the previous
5796
+ // character. If the NSM is at the start of the level run, it will
5797
+ // get the type of sor.
5798
+ for (var i = 0, prev = outerType; i < len; ++i) {
5799
+ var type = types[i];
5800
+ if (type == "m") types[i] = prev;
5801
+ else prev = type;
5802
+ }
5803
+
5804
+ // W2. Search backwards from each instance of a European number
5805
+ // until the first strong type (R, L, AL, or sor) is found. If an
5806
+ // AL is found, change the type of the European number to Arabic
5807
+ // number.
5808
+ // W3. Change all ALs to R.
5809
+ for (var i = 0, cur = outerType; i < len; ++i) {
5810
+ var type = types[i];
5811
+ if (type == "1" && cur == "r") types[i] = "n";
5812
+ else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
5813
+ }
5814
+
5815
+ // W4. A single European separator between two European numbers
5816
+ // changes to a European number. A single common separator between
5817
+ // two numbers of the same type changes to that type.
5818
+ for (var i = 1, prev = types[0]; i < len - 1; ++i) {
5819
+ var type = types[i];
5820
+ if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
5821
+ else if (type == "," && prev == types[i+1] &&
5822
+ (prev == "1" || prev == "n")) types[i] = prev;
5823
+ prev = type;
5824
+ }
5825
+
5826
+ // W5. A sequence of European terminators adjacent to European
5827
+ // numbers changes to all European numbers.
5828
+ // W6. Otherwise, separators and terminators change to Other
5829
+ // Neutral.
5830
+ for (var i = 0; i < len; ++i) {
5831
+ var type = types[i];
5832
+ if (type == ",") types[i] = "N";
5833
+ else if (type == "%") {
5834
+ for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
5835
+ var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
5836
+ for (var j = i; j < end; ++j) types[j] = replace;
5837
+ i = end - 1;
5838
+ }
5839
+ }
5840
+
5841
+ // W7. Search backwards from each instance of a European number
5842
+ // until the first strong type (R, L, or sor) is found. If an L is
5843
+ // found, then change the type of the European number to L.
5844
+ for (var i = 0, cur = outerType; i < len; ++i) {
5845
+ var type = types[i];
5846
+ if (cur == "L" && type == "1") types[i] = "L";
5847
+ else if (isStrong.test(type)) cur = type;
5848
+ }
5849
+
5850
+ // N1. A sequence of neutrals takes the direction of the
5851
+ // surrounding strong text if the text on both sides has the same
5852
+ // direction. European and Arabic numbers act as if they were R in
5853
+ // terms of their influence on neutrals. Start-of-level-run (sor)
5854
+ // and end-of-level-run (eor) are used at level run boundaries.
5855
+ // N2. Any remaining neutrals take the embedding direction.
5856
+ for (var i = 0; i < len; ++i) {
5857
+ if (isNeutral.test(types[i])) {
5858
+ for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
5859
+ var before = (i ? types[i-1] : outerType) == "L";
5860
+ var after = (end < len - 1 ? types[end] : outerType) == "L";
5861
+ var replace = before || after ? "L" : "R";
5862
+ for (var j = i; j < end; ++j) types[j] = replace;
5863
+ i = end - 1;
5864
+ }
5865
+ }
5866
+
5867
+ // Here we depart from the documented algorithm, in order to avoid
5868
+ // building up an actual levels array. Since there are only three
5869
+ // levels (0, 1, 2) in an implementation that doesn't take
5870
+ // explicit embedding into account, we can build up the order on
5871
+ // the fly, without following the level-based algorithm.
5872
+ var order = [], m;
5873
+ for (var i = 0; i < len;) {
5874
+ if (countsAsLeft.test(types[i])) {
5875
+ var start = i;
5876
+ for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
5877
+ order.push({from: start, to: i, level: 0});
5878
+ } else {
5879
+ var pos = i, at = order.length;
5880
+ for (++i; i < len && types[i] != "L"; ++i) {}
5881
+ for (var j = pos; j < i;) {
5882
+ if (countsAsNum.test(types[j])) {
5883
+ if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
5884
+ var nstart = j;
5885
+ for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
5886
+ order.splice(at, 0, {from: nstart, to: j, level: 2});
5887
+ pos = j;
5888
+ } else ++j;
5889
+ }
5890
+ if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
5891
+ }
5892
+ }
5893
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
5894
+ order[0].from = m[0].length;
5895
+ order.unshift({from: 0, to: m[0].length, level: 0});
5896
+ }
5897
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
5898
+ lst(order).to -= m[0].length;
5899
+ order.push({from: len - m[0].length, to: len, level: 0});
5900
+ }
5901
+ if (order[0].level != lst(order).level)
5902
+ order.push({from: len, to: len, level: order[0].level});
5903
+
5904
+ return order;
5905
+ };
5906
+ })();
5907
+
5908
+ // THE END
5909
+
5910
+ CodeMirror.version = "3.19.0";
5911
+
5912
+ return CodeMirror;
5913
+ })();
5914
+
5915
+ CodeMirror.defineMode("clike", function(config, parserConfig) {
5916
+ var indentUnit = config.indentUnit,
5917
+ statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
5918
+ dontAlignCalls = parserConfig.dontAlignCalls,
5919
+ keywords = parserConfig.keywords || {},
5920
+ builtin = parserConfig.builtin || {},
5921
+ blockKeywords = parserConfig.blockKeywords || {},
5922
+ atoms = parserConfig.atoms || {},
5923
+ hooks = parserConfig.hooks || {},
5924
+ multiLineStrings = parserConfig.multiLineStrings;
5925
+ var isOperatorChar = /[+\-*&%=<>!?|\/]/;
5926
+
5927
+ var curPunc;
5928
+
5929
+ function tokenBase(stream, state) {
5930
+ var ch = stream.next();
5931
+ if (hooks[ch]) {
5932
+ var result = hooks[ch](stream, state);
5933
+ if (result !== false) return result;
5934
+ }
5935
+ if (ch == '"' || ch == "'") {
5936
+ state.tokenize = tokenString(ch);
5937
+ return state.tokenize(stream, state);
5938
+ }
5939
+ if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
5940
+ curPunc = ch;
5941
+ return null;
5942
+ }
5943
+ if (/\d/.test(ch)) {
5944
+ stream.eatWhile(/[\w\.]/);
5945
+ return "number";
5946
+ }
5947
+ if (ch == "/") {
5948
+ if (stream.eat("*")) {
5949
+ state.tokenize = tokenComment;
5950
+ return tokenComment(stream, state);
5951
+ }
5952
+ if (stream.eat("/")) {
5953
+ stream.skipToEnd();
5954
+ return "comment";
5955
+ }
5956
+ }
5957
+ if (isOperatorChar.test(ch)) {
5958
+ stream.eatWhile(isOperatorChar);
5959
+ return "operator";
5960
+ }
5961
+ stream.eatWhile(/[\w\$_]/);
5962
+ var cur = stream.current();
5963
+ if (keywords.propertyIsEnumerable(cur)) {
5964
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
5965
+ return "keyword";
5966
+ }
5967
+ if (builtin.propertyIsEnumerable(cur)) {
5968
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
5969
+ return "builtin";
5970
+ }
5971
+ if (atoms.propertyIsEnumerable(cur)) return "atom";
5972
+ return "variable";
5973
+ }
5974
+
5975
+ function tokenString(quote) {
5976
+ return function(stream, state) {
5977
+ var escaped = false, next, end = false;
5978
+ while ((next = stream.next()) != null) {
5979
+ if (next == quote && !escaped) {end = true; break;}
5980
+ escaped = !escaped && next == "\\";
5981
+ }
5982
+ if (end || !(escaped || multiLineStrings))
5983
+ state.tokenize = null;
5984
+ return "string";
5985
+ };
5986
+ }
5987
+
5988
+ function tokenComment(stream, state) {
5989
+ var maybeEnd = false, ch;
5990
+ while (ch = stream.next()) {
5991
+ if (ch == "/" && maybeEnd) {
5992
+ state.tokenize = null;
5993
+ break;
5994
+ }
5995
+ maybeEnd = (ch == "*");
5996
+ }
5997
+ return "comment";
5998
+ }
5999
+
6000
+ function Context(indented, column, type, align, prev) {
6001
+ this.indented = indented;
6002
+ this.column = column;
6003
+ this.type = type;
6004
+ this.align = align;
6005
+ this.prev = prev;
6006
+ }
6007
+ function pushContext(state, col, type) {
6008
+ var indent = state.indented;
6009
+ if (state.context && state.context.type == "statement")
6010
+ indent = state.context.indented;
6011
+ return state.context = new Context(indent, col, type, null, state.context);
6012
+ }
6013
+ function popContext(state) {
6014
+ var t = state.context.type;
6015
+ if (t == ")" || t == "]" || t == "}")
6016
+ state.indented = state.context.indented;
6017
+ return state.context = state.context.prev;
6018
+ }
6019
+
6020
+ // Interface
6021
+
6022
+ return {
6023
+ startState: function(basecolumn) {
6024
+ return {
6025
+ tokenize: null,
6026
+ context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
6027
+ indented: 0,
6028
+ startOfLine: true
6029
+ };
6030
+ },
6031
+
6032
+ token: function(stream, state) {
6033
+ var ctx = state.context;
6034
+ if (stream.sol()) {
6035
+ if (ctx.align == null) ctx.align = false;
6036
+ state.indented = stream.indentation();
6037
+ state.startOfLine = true;
6038
+ }
6039
+ if (stream.eatSpace()) return null;
6040
+ curPunc = null;
6041
+ var style = (state.tokenize || tokenBase)(stream, state);
6042
+ if (style == "comment" || style == "meta") return style;
6043
+ if (ctx.align == null) ctx.align = true;
6044
+
6045
+ if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
6046
+ else if (curPunc == "{") pushContext(state, stream.column(), "}");
6047
+ else if (curPunc == "[") pushContext(state, stream.column(), "]");
6048
+ else if (curPunc == "(") pushContext(state, stream.column(), ")");
6049
+ else if (curPunc == "}") {
6050
+ while (ctx.type == "statement") ctx = popContext(state);
6051
+ if (ctx.type == "}") ctx = popContext(state);
6052
+ while (ctx.type == "statement") ctx = popContext(state);
6053
+ }
6054
+ else if (curPunc == ctx.type) popContext(state);
6055
+ else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
6056
+ pushContext(state, stream.column(), "statement");
6057
+ state.startOfLine = false;
6058
+ return style;
6059
+ },
6060
+
6061
+ indent: function(state, textAfter) {
6062
+ if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
6063
+ var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
6064
+ if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
6065
+ var closing = firstChar == ctx.type;
6066
+ if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
6067
+ else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
6068
+ else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
6069
+ else return ctx.indented + (closing ? 0 : indentUnit);
6070
+ },
6071
+
6072
+ electricChars: "{}",
6073
+ blockCommentStart: "/*",
6074
+ blockCommentEnd: "*/",
6075
+ lineComment: "//",
6076
+ fold: "brace"
6077
+ };
6078
  });
6079
+
6080
+ (function() {
6081
+ function words(str) {
6082
+ var obj = {}, words = str.split(" ");
6083
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
6084
+ return obj;
6085
+ }
6086
+ var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
6087
+ "double static else struct entry switch extern typedef float union for unsigned " +
6088
+ "goto while enum void const signed volatile";
6089
+
6090
+ function cppHook(stream, state) {
6091
+ if (!state.startOfLine) return false;
6092
+ for (;;) {
6093
+ if (stream.skipTo("\\")) {
6094
+ stream.next();
6095
+ if (stream.eol()) {
6096
+ state.tokenize = cppHook;
6097
+ break;
6098
+ }
6099
+ } else {
6100
+ stream.skipToEnd();
6101
+ state.tokenize = null;
6102
+ break;
6103
+ }
6104
+ }
6105
+ return "meta";
6106
+ }
6107
+
6108
+ // C#-style strings where "" escapes a quote.
6109
+ function tokenAtString(stream, state) {
6110
+ var next;
6111
+ while ((next = stream.next()) != null) {
6112
+ if (next == '"' && !stream.eat('"')) {
6113
+ state.tokenize = null;
6114
+ break;
6115
+ }
6116
+ }
6117
+ return "string";
6118
+ }
6119
+
6120
+ function mimes(ms, mode) {
6121
+ for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode);
6122
+ }
6123
+
6124
+ mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], {
6125
+ name: "clike",
6126
+ keywords: words(cKeywords),
6127
+ blockKeywords: words("case do else for if switch while struct"),
6128
+ atoms: words("null"),
6129
+ hooks: {"#": cppHook}
6130
+ });
6131
+ mimes(["text/x-c++src", "text/x-c++hdr"], {
6132
+ name: "clike",
6133
+ keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
6134
+ "static_cast typeid catch operator template typename class friend private " +
6135
+ "this using const_cast inline public throw virtual delete mutable protected " +
6136
+ "wchar_t"),
6137
+ blockKeywords: words("catch class do else finally for if struct switch try while"),
6138
+ atoms: words("true false null"),
6139
+ hooks: {"#": cppHook}
6140
+ });
6141
+ CodeMirror.defineMIME("text/x-java", {
6142
+ name: "clike",
6143
+ keywords: words("abstract assert boolean break byte case catch char class const continue default " +
6144
+ "do double else enum extends final finally float for goto if implements import " +
6145
+ "instanceof int interface long native new package private protected public " +
6146
+ "return short static strictfp super switch synchronized this throw throws transient " +
6147
+ "try void volatile while"),
6148
+ blockKeywords: words("catch class do else finally for if switch try while"),
6149
+ atoms: words("true false null"),
6150
+ hooks: {
6151
+ "@": function(stream) {
6152
+ stream.eatWhile(/[\w\$_]/);
6153
+ return "meta";
6154
+ }
6155
+ }
6156
+ });
6157
+ CodeMirror.defineMIME("text/x-csharp", {
6158
+ name: "clike",
6159
+ keywords: words("abstract as base break case catch checked class const continue" +
6160
+ " default delegate do else enum event explicit extern finally fixed for" +
6161
+ " foreach goto if implicit in interface internal is lock namespace new" +
6162
+ " operator out override params private protected public readonly ref return sealed" +
6163
+ " sizeof stackalloc static struct switch this throw try typeof unchecked" +
6164
+ " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
6165
+ " global group into join let orderby partial remove select set value var yield"),
6166
+ blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
6167
+ builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
6168
+ " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
6169
+ " UInt64 bool byte char decimal double short int long object" +
6170
+ " sbyte float string ushort uint ulong"),
6171
+ atoms: words("true false null"),
6172
+ hooks: {
6173
+ "@": function(stream, state) {
6174
+ if (stream.eat('"')) {
6175
+ state.tokenize = tokenAtString;
6176
+ return tokenAtString(stream, state);
6177
+ }
6178
+ stream.eatWhile(/[\w\$_]/);
6179
+ return "meta";
6180
+ }
6181
+ }
6182
+ });
6183
+ CodeMirror.defineMIME("text/x-scala", {
6184
+ name: "clike",
6185
+ keywords: words(
6186
+
6187
+ /* scala */
6188
+ "abstract case catch class def do else extends false final finally for forSome if " +
6189
+ "implicit import lazy match new null object override package private protected return " +
6190
+ "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
6191
+ "<% >: # @ " +
6192
+
6193
+ /* package scala */
6194
+ "assert assume require print println printf readLine readBoolean readByte readShort " +
6195
+ "readChar readInt readLong readFloat readDouble " +
6196
+
6197
+ "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
6198
+ "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
6199
+ "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
6200
+ "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
6201
+ "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
6202
+
6203
+ /* package java.lang */
6204
+ "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
6205
+ "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
6206
+ "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
6207
+ "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
6208
+
6209
+
6210
+ ),
6211
+ blockKeywords: words("catch class do else finally for forSome if match switch try while"),
6212
+ atoms: words("true false null"),
6213
+ hooks: {
6214
+ "@": function(stream) {
6215
+ stream.eatWhile(/[\w\$_]/);
6216
+ return "meta";
6217
+ }
6218
+ }
6219
+ });
6220
+ mimes(["x-shader/x-vertex", "x-shader/x-fragment"], {
6221
+ name: "clike",
6222
+ keywords: words("float int bool void " +
6223
+ "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
6224
+ "mat2 mat3 mat4 " +
6225
+ "sampler1D sampler2D sampler3D samplerCube " +
6226
+ "sampler1DShadow sampler2DShadow" +
6227
+ "const attribute uniform varying " +
6228
+ "break continue discard return " +
6229
+ "for while do if else struct " +
6230
+ "in out inout"),
6231
+ blockKeywords: words("for while do if else struct"),
6232
+ builtin: words("radians degrees sin cos tan asin acos atan " +
6233
+ "pow exp log exp2 sqrt inversesqrt " +
6234
+ "abs sign floor ceil fract mod min max clamp mix step smootstep " +
6235
+ "length distance dot cross normalize ftransform faceforward " +
6236
+ "reflect refract matrixCompMult " +
6237
+ "lessThan lessThanEqual greaterThan greaterThanEqual " +
6238
+ "equal notEqual any all not " +
6239
+ "texture1D texture1DProj texture1DLod texture1DProjLod " +
6240
+ "texture2D texture2DProj texture2DLod texture2DProjLod " +
6241
+ "texture3D texture3DProj texture3DLod texture3DProjLod " +
6242
+ "textureCube textureCubeLod " +
6243
+ "shadow1D shadow2D shadow1DProj shadow2DProj " +
6244
+ "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
6245
+ "dFdx dFdy fwidth " +
6246
+ "noise1 noise2 noise3 noise4"),
6247
+ atoms: words("true false " +
6248
+ "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
6249
+ "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
6250
+ "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
6251
+ "gl_FogCoord " +
6252
+ "gl_Position gl_PointSize gl_ClipVertex " +
6253
+ "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
6254
+ "gl_TexCoord gl_FogFragCoord " +
6255
+ "gl_FragCoord gl_FrontFacing " +
6256
+ "gl_FragColor gl_FragData gl_FragDepth " +
6257
+ "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
6258
+ "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
6259
+ "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
6260
+ "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
6261
+ "gl_ProjectionMatrixInverseTranspose " +
6262
+ "gl_ModelViewProjectionMatrixInverseTranspose " +
6263
+ "gl_TextureMatrixInverseTranspose " +
6264
+ "gl_NormalScale gl_DepthRange gl_ClipPlane " +
6265
+ "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
6266
+ "gl_FrontLightModelProduct gl_BackLightModelProduct " +
6267
+ "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
6268
+ "gl_FogParameters " +
6269
+ "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
6270
+ "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
6271
+ "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
6272
+ "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
6273
+ "gl_MaxDrawBuffers"),
6274
+ hooks: {"#": cppHook}
6275
+ });
6276
+ }());
6277
+
6278
+ (function() {
6279
+ function keywords(str) {
6280
+ var obj = {}, words = str.split(" ");
6281
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
6282
+ return obj;
6283
+ }
6284
+ function heredoc(delim) {
6285
+ return function(stream, state) {
6286
+ if (stream.match(delim)) state.tokenize = null;
6287
+ else stream.skipToEnd();
6288
+ return "string";
6289
+ };
6290
+ }
6291
+ var phpConfig = {
6292
+ name: "clike",
6293
+ keywords: keywords("abstract and array as break case catch class clone const continue declare default " +
6294
+ "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +
6295
+ "for foreach function global goto if implements interface instanceof namespace " +
6296
+ "new or private protected public static switch throw trait try use var while xor " +
6297
+ "die echo empty exit eval include include_once isset list require require_once return " +
6298
+ "print unset __halt_compiler self static parent yield insteadof finally"),
6299
+ blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"),
6300
+ atoms: keywords("true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__"),
6301
+ builtin: keywords("func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once"),
6302
+ multiLineStrings: true,
6303
+ hooks: {
6304
+ "$": function(stream) {
6305
+ stream.eatWhile(/[\w\$_]/);
6306
+ return "variable-2";
6307
+ },
6308
+ "<": function(stream, state) {
6309
+ if (stream.match(/<</)) {
6310
+ stream.eatWhile(/[\w\.]/);
6311
+ state.tokenize = heredoc(stream.current().slice(3));
6312
+ return state.tokenize(stream, state);
6313
+ }
6314
+ return false;
6315
+ },
6316
+ "#": function(stream) {
6317
+ while (!stream.eol() && !stream.match("?>", false)) stream.next();
6318
+ return "comment";
6319
+ },
6320
+ "/": function(stream) {
6321
+ if (stream.eat("/")) {
6322
+ while (!stream.eol() && !stream.match("?>", false)) stream.next();
6323
+ return "comment";
6324
+ }
6325
+ return false;
6326
+ }
6327
+ }
6328
+ };
6329
+
6330
+ CodeMirror.defineMode("php", function(config, parserConfig) {
6331
+ var htmlMode = CodeMirror.getMode(config, "text/html");
6332
+ var phpMode = CodeMirror.getMode(config, phpConfig);
6333
+
6334
+ function dispatch(stream, state) {
6335
+ var isPHP = state.curMode == phpMode;
6336
+ if (stream.sol() && state.pending != '"') state.pending = null;
6337
+ if (!isPHP) {
6338
+ if (stream.match(/^<\?\w*/)) {
6339
+ state.curMode = phpMode;
6340
+ state.curState = state.php;
6341
+ return "meta";
6342
+ }
6343
+ if (state.pending == '"') {
6344
+ while (!stream.eol() && stream.next() != '"') {}
6345
+ var style = "string";
6346
+ } else if (state.pending && stream.pos < state.pending.end) {
6347
+ stream.pos = state.pending.end;
6348
+ var style = state.pending.style;
6349
+ } else {
6350
+ var style = htmlMode.token(stream, state.curState);
6351
+ }
6352
+ state.pending = null;
6353
+ var cur = stream.current(), openPHP = cur.search(/<\?/);
6354
+ if (openPHP != -1) {
6355
+ if (style == "string" && /\"$/.test(cur) && !/\?>/.test(cur)) state.pending = '"';
6356
+ else state.pending = {end: stream.pos, style: style};
6357
+ stream.backUp(cur.length - openPHP);
6358
+ }
6359
+ return style;
6360
+ } else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
6361
+ state.curMode = htmlMode;
6362
+ state.curState = state.html;
6363
+ return "meta";
6364
+ } else {
6365
+ return phpMode.token(stream, state.curState);
6366
+ }
6367
+ }
6368
+
6369
+ return {
6370
+ startState: function() {
6371
+ var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
6372
+ return {html: html,
6373
+ php: php,
6374
+ curMode: parserConfig.startOpen ? phpMode : htmlMode,
6375
+ curState: parserConfig.startOpen ? php : html,
6376
+ pending: null};
6377
+ },
6378
+
6379
+ copyState: function(state) {
6380
+ var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
6381
+ php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
6382
+ if (state.curMode == htmlMode) cur = htmlNew;
6383
+ else cur = phpNew;
6384
+ return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
6385
+ pending: state.pending};
6386
+ },
6387
+
6388
+ token: dispatch,
6389
+
6390
+ indent: function(state, textAfter) {
6391
+ if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) ||
6392
+ (state.curMode == phpMode && /^\?>/.test(textAfter)))
6393
+ return htmlMode.indent(state.html, textAfter);
6394
+ return state.curMode.indent(state.curState, textAfter);
6395
+ },
6396
+
6397
+ electricChars: "/{}:",
6398
+ blockCommentStart: "/*",
6399
+ blockCommentEnd: "*/",
6400
+ lineComment: "//",
6401
+
6402
+ innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
6403
+ };
6404
+ }, "htmlmixed", "clike");
6405
+
6406
+ CodeMirror.defineMIME("application/x-httpd-php", "php");
6407
+ CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
6408
+ CodeMirror.defineMIME("text/x-php", phpConfig);
6409
+ })();
6410
+
6411
+ (function(){
6412
+ var Pos = CodeMirror.Pos;
6413
+
6414
+ function SearchCursor(doc, query, pos, caseFold) {
6415
+ this.atOccurrence = false; this.doc = doc;
6416
+ if (caseFold == null && typeof query == "string") caseFold = false;
6417
+
6418
+ pos = pos ? doc.clipPos(pos) : Pos(0, 0);
6419
+ this.pos = {from: pos, to: pos};
6420
+
6421
+ // The matches method is filled in based on the type of query.
6422
+ // It takes a position and a direction, and returns an object
6423
+ // describing the next occurrence of the query, or null if no
6424
+ // more matches were found.
6425
+ if (typeof query != "string") { // Regexp match
6426
+ if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
6427
+ this.matches = function(reverse, pos) {
6428
+ if (reverse) {
6429
+ query.lastIndex = 0;
6430
+ var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
6431
+ for (;;) {
6432
+ query.lastIndex = cutOff;
6433
+ var newMatch = query.exec(line);
6434
+ if (!newMatch) break;
6435
+ match = newMatch;
6436
+ start = match.index;
6437
+ cutOff = match.index + (match[0].length || 1);
6438
+ if (cutOff == line.length) break;
6439
+ }
6440
+ var matchLen = (match && match[0].length) || 0;
6441
+ if (!matchLen) {
6442
+ if (start == 0 && line.length == 0) {match = undefined;}
6443
+ else if (start != doc.getLine(pos.line).length) {
6444
+ matchLen++;
6445
+ }
6446
+ }
6447
+ } else {
6448
+ query.lastIndex = pos.ch;
6449
+ var line = doc.getLine(pos.line), match = query.exec(line);
6450
+ var matchLen = (match && match[0].length) || 0;
6451
+ var start = match && match.index;
6452
+ if (start + matchLen != line.length && !matchLen) matchLen = 1;
6453
+ }
6454
+ if (match && matchLen)
6455
+ return {from: Pos(pos.line, start),
6456
+ to: Pos(pos.line, start + matchLen),
6457
+ match: match};
6458
+ };
6459
+ } else { // String query
6460
+ if (caseFold) query = query.toLowerCase();
6461
+ var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
6462
+ var target = query.split("\n");
6463
+ // Different methods for single-line and multi-line queries
6464
+ if (target.length == 1) {
6465
+ if (!query.length) {
6466
+ // Empty string would match anything and never progress, so
6467
+ // we define it to match nothing instead.
6468
+ this.matches = function() {};
6469
+ } else {
6470
+ this.matches = function(reverse, pos) {
6471
+ var line = fold(doc.getLine(pos.line)), len = query.length, match;
6472
+ if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
6473
+ : (match = line.indexOf(query, pos.ch)) != -1)
6474
+ return {from: Pos(pos.line, match),
6475
+ to: Pos(pos.line, match + len)};
6476
+ };
6477
+ }
6478
+ } else {
6479
+ this.matches = function(reverse, pos) {
6480
+ var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln));
6481
+ var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
6482
+ if (reverse ? offsetA > pos.ch || offsetA != match.length
6483
+ : offsetA < pos.ch || offsetA != line.length - match.length)
6484
+ return;
6485
+ for (;;) {
6486
+ if (reverse ? !ln : ln == doc.lineCount() - 1) return;
6487
+ line = fold(doc.getLine(ln += reverse ? -1 : 1));
6488
+ match = target[reverse ? --idx : ++idx];
6489
+ if (idx > 0 && idx < target.length - 1) {
6490
+ if (line != match) return;
6491
+ else continue;
6492
+ }
6493
+ var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
6494
+ if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
6495
+ return;
6496
+ var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB);
6497
+ return {from: reverse ? end : start, to: reverse ? start : end};
6498
+ }
6499
+ };
6500
+ }
6501
+ }
6502
+ }
6503
+
6504
+ SearchCursor.prototype = {
6505
+ findNext: function() {return this.find(false);},
6506
+ findPrevious: function() {return this.find(true);},
6507
+
6508
+ find: function(reverse) {
6509
+ var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
6510
+ function savePosAndFail(line) {
6511
+ var pos = Pos(line, 0);
6512
+ self.pos = {from: pos, to: pos};
6513
+ self.atOccurrence = false;
6514
+ return false;
6515
+ }
6516
+
6517
+ for (;;) {
6518
+ if (this.pos = this.matches(reverse, pos)) {
6519
+ if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); }
6520
+ this.atOccurrence = true;
6521
+ return this.pos.match || true;
6522
+ }
6523
+ if (reverse) {
6524
+ if (!pos.line) return savePosAndFail(0);
6525
+ pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
6526
+ }
6527
+ else {
6528
+ var maxLine = this.doc.lineCount();
6529
+ if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
6530
+ pos = Pos(pos.line + 1, 0);
6531
+ }
6532
+ }
6533
+ },
6534
+
6535
+ from: function() {if (this.atOccurrence) return this.pos.from;},
6536
+ to: function() {if (this.atOccurrence) return this.pos.to;},
6537
+
6538
+ replace: function(newText) {
6539
+ if (!this.atOccurrence) return;
6540
+ var lines = CodeMirror.splitLines(newText);
6541
+ this.doc.replaceRange(lines, this.pos.from, this.pos.to);
6542
+ this.pos.to = Pos(this.pos.from.line + lines.length - 1,
6543
+ lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
6544
+ }
6545
+ };
6546
+
6547
+ CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
6548
+ return new SearchCursor(this.doc, query, pos, caseFold);
6549
+ });
6550
+ CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
6551
+ return new SearchCursor(this, query, pos, caseFold);
6552
+ });
6553
+ })();
6554
+
6555
+ // Define search commands. Depends on dialog.js or another
6556
+ // implementation of the openDialog method.
6557
+
6558
+ // Replace works a little oddly -- it will do the replace on the next
6559
+ // Ctrl-G (or whatever is bound to findNext) press. You prevent a
6560
+ // replace by making sure the match is no longer selected when hitting
6561
+ // Ctrl-G.
6562
+
6563
+ (function() {
6564
+ function searchOverlay(query) {
6565
+ if (typeof query == "string") return {token: function(stream) {
6566
+ if (stream.match(query)) return "searching";
6567
+ stream.next();
6568
+ stream.skipTo(query.charAt(0)) || stream.skipToEnd();
6569
+ }};
6570
+ return {token: function(stream) {
6571
+ if (stream.match(query)) return "searching";
6572
+ while (!stream.eol()) {
6573
+ stream.next();
6574
+ if (stream.match(query, false)) break;
6575
+ }
6576
+ }};
6577
+ }
6578
+
6579
+ function SearchState() {
6580
+ this.posFrom = this.posTo = this.query = null;
6581
+ this.overlay = null;
6582
+ }
6583
+ function getSearchState(cm) {
6584
+ return cm.state.search || (cm.state.search = new SearchState());
6585
+ }
6586
+ function getSearchCursor(cm, query, pos) {
6587
+ // Heuristic: if the query string is all lowercase, do a case insensitive search.
6588
+ return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase());
6589
+ }
6590
+ function dialog(cm, text, shortText, f) {
6591
+ if (cm.openDialog) cm.openDialog(text, f);
6592
+ else f(prompt(shortText, ""));
6593
+ }
6594
+ function confirmDialog(cm, text, shortText, fs) {
6595
+ if (cm.openConfirm) cm.openConfirm(text, fs);
6596
+ else if (confirm(shortText)) fs[0]();
6597
+ }
6598
+ function parseQuery(query) {
6599
+ var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
6600
+ return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
6601
+ }
6602
+ var queryDialog =
6603
+ 'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
6604
+ function doSearch(cm, rev) {
6605
+ var state = getSearchState(cm);
6606
+ if (state.query) return findNext(cm, rev);
6607
+ dialog(cm, queryDialog, "Search for:", function(query) {
6608
+ cm.operation(function() {
6609
+ if (!query || state.query) return;
6610
+ state.query = parseQuery(query);
6611
+ cm.removeOverlay(state.overlay);
6612
+ state.overlay = searchOverlay(state.query);
6613
+ cm.addOverlay(state.overlay);
6614
+ state.posFrom = state.posTo = cm.getCursor();
6615
+ findNext(cm, rev);
6616
+ });
6617
+ });
6618
+ }
6619
+ function findNext(cm, rev) {cm.operation(function() {
6620
+ var state = getSearchState(cm);
6621
+ var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
6622
+ if (!cursor.find(rev)) {
6623
+ cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
6624
+ if (!cursor.find(rev)) return;
6625
+ }
6626
+ cm.setSelection(cursor.from(), cursor.to());
6627
+ cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
6628
+ state.posFrom = cursor.from(); state.posTo = cursor.to();
6629
+ });}
6630
+ function clearSearch(cm) {cm.operation(function() {
6631
+ var state = getSearchState(cm);
6632
+ if (!state.query) return;
6633
+ state.query = null;
6634
+ cm.removeOverlay(state.overlay);
6635
+ });}
6636
+
6637
+ var replaceQueryDialog =
6638
+ 'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
6639
+ var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
6640
+ var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
6641
+ function replace(cm, all) {
6642
+ dialog(cm, replaceQueryDialog, "Replace:", function(query) {
6643
+ if (!query) return;
6644
+ query = parseQuery(query);
6645
+ dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
6646
+ if (all) {
6647
+ cm.operation(function() {
6648
+ for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
6649
+ if (typeof query != "string") {
6650
+ var match = cm.getRange(cursor.from(), cursor.to()).match(query);
6651
+ cursor.replace(text.replace(/\$(\d)/, function(_, i) {return match[i];}));
6652
+ } else cursor.replace(text);
6653
+ }
6654
+ });
6655
+ } else {
6656
+ clearSearch(cm);
6657
+ var cursor = getSearchCursor(cm, query, cm.getCursor());
6658
+ var advance = function() {
6659
+ var start = cursor.from(), match;
6660
+ if (!(match = cursor.findNext())) {
6661
+ cursor = getSearchCursor(cm, query);
6662
+ if (!(match = cursor.findNext()) ||
6663
+ (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
6664
+ }
6665
+ cm.setSelection(cursor.from(), cursor.to());
6666
+ cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
6667
+ confirmDialog(cm, doReplaceConfirm, "Replace?",
6668
+ [function() {doReplace(match);}, advance]);
6669
+ };
6670
+ var doReplace = function(match) {
6671
+ cursor.replace(typeof query == "string" ? text :
6672
+ text.replace(/\$(\d)/, function(_, i) {return match[i];}));
6673
+ advance();
6674
+ };
6675
+ advance();
6676
+ }
6677
+ });
6678
+ });
6679
+ }
6680
+
6681
+ CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
6682
+ CodeMirror.commands.findNext = doSearch;
6683
+ CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
6684
+ CodeMirror.commands.clearSearch = clearSearch;
6685
+ CodeMirror.commands.replace = replace;
6686
+ CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
6687
+ })();
6688
+
6689
+ (function() {
6690
+ var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
6691
+ (document.documentMode == null || document.documentMode < 8);
6692
+
6693
+ var Pos = CodeMirror.Pos;
6694
+
6695
+ var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
6696
+ function findMatchingBracket(cm, where, strict) {
6697
+ var state = cm.state.matchBrackets;
6698
+ var maxScanLen = (state && state.maxScanLineLength) || 10000;
6699
+
6700
+ var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
6701
+ var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
6702
+ if (!match) return null;
6703
+ var forward = match.charAt(1) == ">", d = forward ? 1 : -1;
6704
+ if (strict && forward != (pos == cur.ch)) return null;
6705
+ var style = cm.getTokenTypeAt(Pos(cur.line, pos + 1));
6706
+
6707
+ var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
6708
+ function scan(line, lineNo, start) {
6709
+ if (!line.text) return;
6710
+ var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;
6711
+ if (line.text.length > maxScanLen) return null;
6712
+ if (start != null) pos = start + d;
6713
+ for (; pos != end; pos += d) {
6714
+ var ch = line.text.charAt(pos);
6715
+ if (re.test(ch) && cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style) {
6716
+ var match = matching[ch];
6717
+ if (match.charAt(1) == ">" == forward) stack.push(ch);
6718
+ else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
6719
+ else if (!stack.length) return {pos: pos, match: true};
6720
+ }
6721
+ }
6722
+ }
6723
+ for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
6724
+ if (i == cur.line) found = scan(line, i, pos);
6725
+ else found = scan(cm.getLineHandle(i), i);
6726
+ if (found) break;
6727
+ }
6728
+ return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos),
6729
+ match: found && found.match, forward: forward};
6730
+ }
6731
+
6732
+ function matchBrackets(cm, autoclear) {
6733
+ // Disable brace matching in long lines, since it'll cause hugely slow updates
6734
+ var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
6735
+ var found = findMatchingBracket(cm);
6736
+ if (!found || cm.getLine(found.from.line).length > maxHighlightLen ||
6737
+ found.to && cm.getLine(found.to.line).length > maxHighlightLen)
6738
+ return;
6739
+
6740
+ var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
6741
+ var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style});
6742
+ var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style});
6743
+ // Kludge to work around the IE bug from issue #1193, where text
6744
+ // input stops going to the textare whever this fires.
6745
+ if (ie_lt8 && cm.state.focused) cm.display.input.focus();
6746
+ var clear = function() {
6747
+ cm.operation(function() { one.clear(); two && two.clear(); });
6748
+ };
6749
+ if (autoclear) setTimeout(clear, 800);
6750
+ else return clear;
6751
+ }
6752
+
6753
+ var currentlyHighlighted = null;
6754
+ function doMatchBrackets(cm) {
6755
+ cm.operation(function() {
6756
+ if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
6757
+ if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);
6758
+ });
6759
+ }
6760
+
6761
+ CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
6762
+ if (old && old != CodeMirror.Init)
6763
+ cm.off("cursorActivity", doMatchBrackets);
6764
+ if (val) {
6765
+ cm.state.matchBrackets = typeof val == "object" ? val : {};
6766
+ cm.on("cursorActivity", doMatchBrackets);
6767
+ }
6768
+ });
6769
+
6770
+ CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
6771
+ CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){
6772
+ return findMatchingBracket(this, pos, strict);
6773
+ });
6774
+ })();
6775
+
6776
+
6777
+ var atts = {
6778
+ lineNumbers: true,
6779
+ matchBrackets: true,
6780
+ lineWrapping: true,
6781
+ mode: "text/x-php",
6782
+ indentUnit: 4,
6783
+ indentWithTabs: true,
6784
+ enterMode: "keep",
6785
+ tabMode: "shift"
6786
+ };
6787
+
6788
+ var editor = CodeMirror.fromTextArea(document.getElementById("snippet_code"), atts);
6789
+
6790
+ })();
assets/js/admin-single.min.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ !function(){window.CodeMirror=function(){"use strict";function a(c,d){if(!(this instanceof a))return new a(c,d);this.options=d=d||{};for(var e in ff)!d.hasOwnProperty(e)&&ff.hasOwnProperty(e)&&(d[e]=ff[e]);m(d);var f="string"==typeof d.value?0:d.value.first,g=this.display=b(c,f);g.wrapper.CodeMirror=this,j(this),d.autofocus&&!Ne&&ob(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,draggingText:!1,highlight:new Vd},h(this),d.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap");var i=d.value;"string"==typeof i&&(i=new uf(d.value,d.mode)),gb(this,md)(this,i),Ae&&setTimeout(ce(nb,this,!0),20),qb(this);var k;try{k=document.activeElement==g.input}catch(l){}k||d.autofocus&&!Ne?setTimeout(ce(Ib,this),20):Jb(this),gb(this,function(){for(var a in ef)ef.propertyIsEnumerable(a)&&ef[a](this,d[a],gf);for(var b=0;b<lf.length;++b)lf[b](this)})()}function b(a,b){var c={},d=c.input=fe("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");return De?d.style.width="1000px":d.setAttribute("wrap","off"),Me&&(d.style.border="1px solid black"),d.setAttribute("autocorrect","off"),d.setAttribute("autocapitalize","off"),d.setAttribute("spellcheck","false"),c.inputDiv=fe("div",[d],null,"overflow: hidden; position: relative; width: 3px; height: 0px;"),c.scrollbarH=fe("div",[fe("div",null,null,"height: 1px")],"CodeMirror-hscrollbar"),c.scrollbarV=fe("div",[fe("div",null,null,"width: 1px")],"CodeMirror-vscrollbar"),c.scrollbarFiller=fe("div",null,"CodeMirror-scrollbar-filler"),c.gutterFiller=fe("div",null,"CodeMirror-gutter-filler"),c.lineDiv=fe("div",null,"CodeMirror-code"),c.selectionDiv=fe("div",null,null,"position: relative; z-index: 1"),c.cursor=fe("div"," ","CodeMirror-cursor"),c.otherCursor=fe("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"),c.measure=fe("div",null,"CodeMirror-measure"),c.lineSpace=fe("div",[c.measure,c.selectionDiv,c.lineDiv,c.cursor,c.otherCursor],null,"position: relative; outline: none"),c.mover=fe("div",[fe("div",[c.lineSpace],"CodeMirror-lines")],null,"position: relative"),c.sizer=fe("div",[c.mover],"CodeMirror-sizer"),c.heightForcer=fe("div",null,null,"position: absolute; height: "+zf+"px; width: 1px;"),c.gutters=fe("div",null,"CodeMirror-gutters"),c.lineGutter=null,c.scroller=fe("div",[c.sizer,c.heightForcer,c.gutters],"CodeMirror-scroll"),c.scroller.setAttribute("tabIndex","-1"),c.wrapper=fe("div",[c.inputDiv,c.scrollbarH,c.scrollbarV,c.scrollbarFiller,c.gutterFiller,c.scroller],"CodeMirror"),Be&&(c.gutters.style.zIndex=-1,c.scroller.style.paddingRight=0),a.appendChild?a.appendChild(c.wrapper):a(c.wrapper),Me&&(d.style.width="0px"),De||(c.scroller.draggable=!0),Ie?(c.inputDiv.style.height="1px",c.inputDiv.style.position="absolute"):Be&&(c.scrollbarH.style.minWidth=c.scrollbarV.style.minWidth="18px"),c.viewOffset=c.lastSizeC=0,c.showingFrom=c.showingTo=b,c.lineNumWidth=c.lineNumInnerWidth=c.lineNumChars=null,c.prevInput="",c.alignWidgets=!1,c.pollingFast=!1,c.poll=new Vd,c.cachedCharWidth=c.cachedTextHeight=null,c.measureLineCache=[],c.measureLineCachePos=0,c.inaccurateSelection=!1,c.maxLine=null,c.maxLineLength=0,c.maxLineChanged=!1,c.wheelDX=c.wheelDY=c.wheelStartX=c.wheelStartY=null,c}function c(b){b.doc.mode=a.getMode(b.options,b.doc.modeOption),b.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),b.doc.frontier=b.doc.first,G(b,100),b.state.modeGen++,b.curOp&&jb(b)}function d(a){a.options.lineWrapping?(a.display.wrapper.className+=" CodeMirror-wrap",a.display.sizer.style.minWidth=""):(a.display.wrapper.className=a.display.wrapper.className.replace(" CodeMirror-wrap",""),l(a)),f(a),jb(a),U(a),setTimeout(function(){n(a)},100)}function e(a){var b=cb(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/db(a.display)-3);return function(e){return Qc(a.doc,e)?0:c?(Math.ceil(e.text.length/d)||1)*b:b}}function f(a){var b=a.doc,c=e(a);b.iter(function(a){var b=c(a);b!=a.height&&qd(a,b)})}function g(a){var b=of[a.options.keyMap],c=b.style;a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-keymap-\S+/g,"")+(c?" cm-keymap-"+c:""),a.state.disableInput=b.disableInput}function h(a){a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+a.options.theme.replace(/(^|\s)\s*/g," cm-s-"),U(a)}function i(a){j(a),jb(a),setTimeout(function(){p(a)},20)}function j(a){var b=a.display.gutters,c=a.options.gutters;ge(b);for(var d=0;d<c.length;++d){var e=c[d],f=b.appendChild(fe("div",null,"CodeMirror-gutter "+e));"CodeMirror-linenumbers"==e&&(a.display.lineGutter=f,f.style.width=(a.display.lineNumWidth||1)+"px")}b.style.display=d?"":"none"}function k(a,b){if(0==b.height)return 0;for(var c,d=b.text.length,e=b;c=Nc(e);){var f=c.find();e=nd(a,f.from.line),d+=f.from.ch-f.to.ch}for(e=b;c=Oc(e);){var f=c.find();d-=e.text.length-f.from.ch,e=nd(a,f.to.line),d+=e.text.length-f.to.ch}return d}function l(a){var b=a.display,c=a.doc;b.maxLine=nd(c,c.first),b.maxLineLength=k(c,b.maxLine),b.maxLineChanged=!0,c.iter(function(a){var d=k(c,a);d>b.maxLineLength&&(b.maxLineLength=d,b.maxLine=a)})}function m(a){var b=$d(a.gutters,"CodeMirror-linenumbers");-1==b&&a.lineNumbers?a.gutters=a.gutters.concat(["CodeMirror-linenumbers"]):b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function n(a){var b=a.display,c=a.doc.height,d=c+L(b);b.sizer.style.minHeight=b.heightForcer.style.top=d+"px",b.gutters.style.height=Math.max(d,b.scroller.clientHeight-zf)+"px";var e=Math.max(d,b.scroller.scrollHeight),f=b.scroller.scrollWidth>b.scroller.clientWidth+1,g=e>b.scroller.clientHeight+1;g?(b.scrollbarV.style.display="block",b.scrollbarV.style.bottom=f?le(b.measure)+"px":"0",b.scrollbarV.firstChild.style.height=e-b.scroller.clientHeight+b.scrollbarV.clientHeight+"px"):(b.scrollbarV.style.display="",b.scrollbarV.firstChild.style.height="0"),f?(b.scrollbarH.style.display="block",b.scrollbarH.style.right=g?le(b.measure)+"px":"0",b.scrollbarH.firstChild.style.width=b.scroller.scrollWidth-b.scroller.clientWidth+b.scrollbarH.clientWidth+"px"):(b.scrollbarH.style.display="",b.scrollbarH.firstChild.style.width="0"),f&&g?(b.scrollbarFiller.style.display="block",b.scrollbarFiller.style.height=b.scrollbarFiller.style.width=le(b.measure)+"px"):b.scrollbarFiller.style.display="",f&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(b.gutterFiller.style.display="block",b.gutterFiller.style.height=le(b.measure)+"px",b.gutterFiller.style.width=b.gutters.offsetWidth+"px"):b.gutterFiller.style.display="",Je&&0===le(b.measure)&&(b.scrollbarV.style.minWidth=b.scrollbarH.style.minHeight=Ke?"18px":"12px",b.scrollbarV.style.pointerEvents=b.scrollbarH.style.pointerEvents="none")}function o(a,b,c){var d=a.scroller.scrollTop,e=a.wrapper.clientHeight;"number"==typeof c?d=c:c&&(d=c.top,e=c.bottom-c.top),d=Math.floor(d-K(a));var f=Math.ceil(d+e);return{from:sd(b,d),to:sd(b,f)}}function p(a){var b=a.display;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var c=s(b)-b.scroller.scrollLeft+a.doc.scrollLeft,d=b.gutters.offsetWidth,e=c+"px",f=b.lineDiv.firstChild;f;f=f.nextSibling)if(f.alignable)for(var g=0,h=f.alignable;g<h.length;++g)h[g].style.left=e;a.options.fixedGutter&&(b.gutters.style.left=c+d+"px")}}function q(a){if(!a.options.lineNumbers)return!1;var b=a.doc,c=r(a.options,b.first+b.size-1),d=a.display;if(c.length!=d.lineNumChars){var e=d.measure.appendChild(fe("div",[fe("div",c)],"CodeMirror-linenumber CodeMirror-gutter-elt")),f=e.firstChild.offsetWidth,g=e.offsetWidth-f;return d.lineGutter.style.width="",d.lineNumInnerWidth=Math.max(f,d.lineGutter.offsetWidth-g),d.lineNumWidth=d.lineNumInnerWidth+g,d.lineNumChars=d.lineNumInnerWidth?c.length:-1,d.lineGutter.style.width=d.lineNumWidth+"px",!0}return!1}function r(a,b){return String(a.lineNumberFormatter(b+a.firstLineNumber))}function s(a){return je(a.scroller).left-je(a.sizer).left}function t(a,b,c,d){for(var e,f=a.display.showingFrom,g=a.display.showingTo,h=o(a.display,a.doc,c),i=!0;;i=!1){var j=a.display.scroller.clientWidth;if(!u(a,b,h,d))break;if(e=!0,b=[],C(a),n(a),i&&a.options.lineWrapping&&j!=a.display.scroller.clientWidth)d=!0;else if(d=!1,c&&(c=Math.min(a.display.scroller.scrollHeight-a.display.scroller.clientHeight,"number"==typeof c?c:c.top)),h=o(a.display,a.doc,c),h.from>=a.display.showingFrom&&h.to<=a.display.showingTo)break}return e&&(Qd(a,"update",a),(a.display.showingFrom!=f||a.display.showingTo!=g)&&Qd(a,"viewportChange",a,a.display.showingFrom,a.display.showingTo)),e}function u(a,b,c,d){var e=a.display,f=a.doc;if(!e.wrapper.clientWidth)return e.showingFrom=e.showingTo=f.first,e.viewOffset=0,void 0;if(!(!d&&0==b.length&&c.from>e.showingFrom&&c.to<e.showingTo)){q(a)&&(b=[{from:f.first,to:f.first+f.size}]);var g=e.sizer.style.marginLeft=e.gutters.offsetWidth+"px";e.scrollbarH.style.left=a.options.fixedGutter?g:"0";var h=1/0;if(a.options.lineNumbers)for(var i=0;i<b.length;++i)b[i].diff&&b[i].from<h&&(h=b[i].from);var j=f.first+f.size,k=Math.max(c.from-a.options.viewportMargin,f.first),l=Math.min(j,c.to+a.options.viewportMargin);if(e.showingFrom<k&&k-e.showingFrom<20&&(k=Math.max(f.first,e.showingFrom)),e.showingTo>l&&e.showingTo-l<20&&(l=Math.min(j,e.showingTo)),Xe)for(k=rd(Pc(f,nd(f,k)));j>l&&Qc(f,nd(f,l));)++l;var m=[{from:Math.max(e.showingFrom,f.first),to:Math.min(e.showingTo,j)}];if(m=m[0].from>=m[0].to?[]:x(m,b),Xe)for(var i=0;i<m.length;++i)for(var n,o=m[i];n=Oc(nd(f,o.to-1));){var p=n.find().from.line;if(!(p>o.from)){m.splice(i--,1);break}o.to=p}for(var r=0,i=0;i<m.length;++i){var o=m[i];o.from<k&&(o.from=k),o.to>l&&(o.to=l),o.from>=o.to?m.splice(i--,1):r+=o.to-o.from}if(!d&&r==l-k&&k==e.showingFrom&&l==e.showingTo)return w(a),void 0;m.sort(function(a,b){return a.from-b.from});try{var s=document.activeElement}catch(t){}.7*(l-k)>r&&(e.lineDiv.style.display="none"),z(a,k,l,m,h),e.lineDiv.style.display="",s&&document.activeElement!=s&&s.offsetHeight&&s.focus();var u=k!=e.showingFrom||l!=e.showingTo||e.lastSizeC!=e.wrapper.clientHeight;return u&&(e.lastSizeC=e.wrapper.clientHeight,G(a,400)),e.showingFrom=k,e.showingTo=l,v(a),w(a),!0}}function v(a){for(var b,c=a.display,d=c.lineDiv.offsetTop,e=c.lineDiv.firstChild;e;e=e.nextSibling)if(e.lineObj){if(Be){var f=e.offsetTop+e.offsetHeight;b=f-d,d=f}else{var g=je(e);b=g.bottom-g.top}var h=e.lineObj.height-b;if(2>b&&(b=cb(c)),h>.001||-.001>h){qd(e.lineObj,b);var i=e.lineObj.widgets;if(i)for(var j=0;j<i.length;++j)i[j].height=i[j].node.offsetHeight}}}function w(a){var b=a.display.viewOffset=td(a,nd(a.doc,a.display.showingFrom));a.display.mover.style.top=b+"px"}function x(a,b){for(var c=0,d=b.length||0;d>c;++c){for(var e=b[c],f=[],g=e.diff||0,h=0,i=a.length;i>h;++h){var j=a[h];e.to<=j.from&&e.diff?f.push({from:j.from+g,to:j.to+g}):e.to<=j.from||e.from>=j.to?f.push(j):(e.from>j.from&&f.push({from:j.from,to:e.from}),e.to<j.to&&f.push({from:e.to+g,to:j.to+g}))}a=f}return a}function y(a){for(var b=a.display,c={},d={},e=b.gutters.firstChild,f=0;e;e=e.nextSibling,++f)c[a.options.gutters[f]]=e.offsetLeft,d[a.options.gutters[f]]=e.offsetWidth;return{fixedPos:s(b),gutterTotalWidth:b.gutters.offsetWidth,gutterLeft:c,gutterWidth:d,wrapperWidth:b.wrapper.clientWidth}}function z(a,b,c,d,e){function f(b){var c=b.nextSibling;return De&&Oe&&a.display.currentWheelTarget==b?(b.style.display="none",b.lineObj=null):b.parentNode.removeChild(b),c}var g=y(a),h=a.display,i=a.options.lineNumbers;d.length||De&&a.display.currentWheelTarget||ge(h.lineDiv);var j=h.lineDiv,k=j.firstChild,l=d.shift(),m=b;for(a.doc.iter(b,c,function(b){if(l&&l.to==m&&(l=d.shift()),Qc(a.doc,b)){if(0!=b.height&&qd(b,0),b.widgets&&k&&k.previousSibling)for(var c=0;c<b.widgets.length;++c){var h=b.widgets[c];if(h.showIfHidden){var n=k.previousSibling;if(/pre/i.test(n.nodeName)){var o=fe("div",null,null,"position: relative");n.parentNode.replaceChild(o,n),o.appendChild(n),n=o}var p=n.appendChild(fe("div",[h.node],"CodeMirror-linewidget"));h.handleMouseEvents||(p.ignoreEvents=!0),B(h,p,n,g)}}}else if(l&&l.from<=m&&l.to>m){for(;k.lineObj!=b;)k=f(k);i&&m>=e&&k.lineNumber&&ie(k.lineNumber,r(a.options,m)),k=k.nextSibling}else{if(b.widgets)for(var q,s=0,t=k;t&&20>s;++s,t=t.nextSibling)if(t.lineObj==b&&/div/i.test(t.nodeName)){q=t;break}var u=A(a,b,m,g,q);if(u!=q)j.insertBefore(u,k);else{for(;k!=q;)k=f(k);k=k.nextSibling}u.lineObj=b}++m});k;)k=f(k)}function A(a,b,c,d,e){var f,g=cd(a,b),h=g.pre,i=b.gutterMarkers,j=a.display,k=g.bgClass?g.bgClass+" "+(b.bgClass||""):b.bgClass;if(!(a.options.lineNumbers||i||k||b.wrapClass||b.widgets))return h;if(e){e.alignable=null;for(var l,m=!0,n=0,o=null,p=e.firstChild;p;p=l)if(l=p.nextSibling,/\bCodeMirror-linewidget\b/.test(p.className)){for(var q=0;q<b.widgets.length;++q){var s=b.widgets[q];if(s.node==p.firstChild){s.above||o||(o=p),B(s,p,e,d),++n;break}}if(q==b.widgets.length){m=!1;break}}else e.removeChild(p);e.insertBefore(h,o),m&&n==b.widgets.length&&(f=e,e.className=b.wrapClass||"")}if(f||(f=fe("div",null,b.wrapClass,"position: relative"),f.appendChild(h)),k&&f.insertBefore(fe("div",null,k+" CodeMirror-linebackground"),f.firstChild),a.options.lineNumbers||i){var t=f.insertBefore(fe("div",null,null,"position: absolute; left: "+(a.options.fixedGutter?d.fixedPos:-d.gutterTotalWidth)+"px"),f.firstChild);if(a.options.fixedGutter&&(f.alignable||(f.alignable=[])).push(t),!a.options.lineNumbers||i&&i["CodeMirror-linenumbers"]||(f.lineNumber=t.appendChild(fe("div",r(a.options,c),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+d.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+j.lineNumInnerWidth+"px"))),i)for(var u=0;u<a.options.gutters.length;++u){var v=a.options.gutters[u],w=i.hasOwnProperty(v)&&i[v];w&&t.appendChild(fe("div",[w],"CodeMirror-gutter-elt","left: "+d.gutterLeft[v]+"px; width: "+d.gutterWidth[v]+"px"))}}if(Be&&(f.style.zIndex=2),b.widgets&&f!=e)for(var q=0,x=b.widgets;q<x.length;++q){var s=x[q],y=fe("div",[s.node],"CodeMirror-linewidget");s.handleMouseEvents||(y.ignoreEvents=!0),B(s,y,f,d),s.above?f.insertBefore(y,a.options.lineNumbers&&0!=b.height?t:h):f.appendChild(y),Qd(s,"redraw")}return f}function B(a,b,c,d){if(a.noHScroll){(c.alignable||(c.alignable=[])).push(b);var e=d.wrapperWidth;b.style.left=d.fixedPos+"px",a.coverGutter||(e-=d.gutterTotalWidth,b.style.paddingLeft=d.gutterTotalWidth+"px"),b.style.width=e+"px"}a.coverGutter&&(b.style.zIndex=5,b.style.position="relative",a.noHScroll||(b.style.marginLeft=-d.gutterTotalWidth+"px"))}function C(a){var b=a.display,c=Wb(a.doc.sel.from,a.doc.sel.to);if(c||a.options.showCursorWhenSelecting?D(a):b.cursor.style.display=b.otherCursor.style.display="none",c?b.selectionDiv.style.display="none":E(a),a.options.moveInputWithCursor){var d=$(a,a.doc.sel.head,"div"),e=je(b.wrapper),f=je(b.lineDiv);b.inputDiv.style.top=Math.max(0,Math.min(b.wrapper.clientHeight-10,d.top+f.top-e.top))+"px",b.inputDiv.style.left=Math.max(0,Math.min(b.wrapper.clientWidth-10,d.left+f.left-e.left))+"px"}}function D(a){var b=a.display,c=$(a,a.doc.sel.head,"div");b.cursor.style.left=c.left+"px",b.cursor.style.top=c.top+"px",b.cursor.style.height=Math.max(0,c.bottom-c.top)*a.options.cursorHeight+"px",b.cursor.style.display="",c.other?(b.otherCursor.style.display="",b.otherCursor.style.left=c.other.left+"px",b.otherCursor.style.top=c.other.top+"px",b.otherCursor.style.height=.85*(c.other.bottom-c.other.top)+"px"):b.otherCursor.style.display="none"}function E(a){function b(a,b,c,d){0>b&&(b=0),g.appendChild(fe("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px; top: "+b+"px; width: "+(null==c?h-a:c)+"px; height: "+(d-b)+"px"))}function c(c,d,f){function g(b,d){return Z(a,Vb(c,b),"div",l,d)}var j,k,l=nd(e,c),m=l.text.length;return ne(ud(l),d||0,null==f?m:f,function(a,c,e){var l,n,o,p=g(a,"left");if(a==c)l=p,n=o=p.left;else{if(l=g(c-1,"right"),"rtl"==e){var q=p;p=l,l=q}n=p.left,o=l.right}null==d&&0==a&&(n=i),l.top-p.top>3&&(b(n,p.top,null,p.bottom),n=i,p.bottom<l.top&&b(n,p.bottom,null,l.top)),null==f&&c==m&&(o=h),(!j||p.top<j.top||p.top==j.top&&p.left<j.left)&&(j=p),(!k||l.bottom>k.bottom||l.bottom==k.bottom&&l.right>k.right)&&(k=l),i+1>n&&(n=i),b(n,l.top,o-n,l.bottom)}),{start:j,end:k}}var d=a.display,e=a.doc,f=a.doc.sel,g=document.createDocumentFragment(),h=d.lineSpace.offsetWidth,i=M(a.display);if(f.from.line==f.to.line)c(f.from.line,f.from.ch,f.to.ch);else{var j=nd(e,f.from.line),k=nd(e,f.to.line),l=Pc(e,j)==Pc(e,k),m=c(f.from.line,f.from.ch,l?j.text.length:null).end,n=c(f.to.line,l?0:null,f.to.ch).start;l&&(m.top<n.top-2?(b(m.right,m.top,null,m.bottom),b(i,n.top,n.left,n.bottom)):b(m.right,m.top,n.left-m.right,m.bottom)),m.bottom<n.top&&b(i,m.bottom,null,n.top)}he(d.selectionDiv,g),d.selectionDiv.style.display=""}function F(a){if(a.state.focused){var b=a.display;clearInterval(b.blinker);var c=!0;b.cursor.style.visibility=b.otherCursor.style.visibility="",a.options.cursorBlinkRate>0&&(b.blinker=setInterval(function(){b.cursor.style.visibility=b.otherCursor.style.visibility=(c=!c)?"":"hidden"},a.options.cursorBlinkRate))}}function G(a,b){a.doc.mode.startState&&a.doc.frontier<a.display.showingTo&&a.state.highlight.set(b,ce(H,a))}function H(a){var b=a.doc;if(b.frontier<b.first&&(b.frontier=b.first),!(b.frontier>=a.display.showingTo)){var c,d=+new Date+a.options.workTime,e=tc(b.mode,J(a,b.frontier)),f=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.showingTo+500),function(g){if(b.frontier>=a.display.showingFrom){var h=g.styles;g.styles=$c(a,g,e);for(var i=!h||h.length!=g.styles.length,j=0;!i&&j<h.length;++j)i=h[j]!=g.styles[j];i&&(c&&c.end==b.frontier?c.end++:f.push(c={start:b.frontier,end:b.frontier+1})),g.stateAfter=tc(b.mode,e)}else ad(a,g,e),g.stateAfter=0==b.frontier%5?tc(b.mode,e):null;return++b.frontier,+new Date>d?(G(a,a.options.workDelay),!0):void 0}),f.length&&gb(a,function(){for(var a=0;a<f.length;++a)jb(this,f[a].start,f[a].end)})()}}function I(a,b,c){for(var d,e,f=a.doc,g=c?-1:b-(a.doc.mode.innerMode?1e3:100),h=b;h>g;--h){if(h<=f.first)return f.first;var i=nd(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=Wd(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function J(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=I(a,b,c),g=f>d.first&&nd(d,f-1).stateAfter;return g=g?tc(d.mode,g):uc(d.mode),d.iter(f,b,function(c){ad(a,c,g);var h=f==b-1||0==f%5||f>=e.showingFrom&&f<e.showingTo;c.stateAfter=h?tc(d.mode,g):null,++f}),c&&(d.frontier=f),g}function K(a){return a.lineSpace.offsetTop}function L(a){return a.mover.offsetHeight-a.lineSpace.offsetHeight}function M(a){var b=he(a.measure,fe("pre",null,null,"text-align: left")).appendChild(fe("span","x"));return b.offsetLeft}function N(a,b,c,d,e){var f=-1;if(d=d||Q(a,b),d.crude){var g=d.left+c*d.width;return{left:g,right:g+d.width,top:d.top,bottom:d.bottom}}for(var h=c;;h+=f){var i=d[h];if(i)break;0>f&&0==h&&(f=1)}return e=h>c?"left":c>h?"right":e,"left"==e&&i.leftSide?i=i.leftSide:"right"==e&&i.rightSide&&(i=i.rightSide),{left:c>h?i.right:i.left,right:h>c?i.left:i.right,top:i.top,bottom:i.bottom}}function O(a,b){for(var c=a.display.measureLineCache,d=0;d<c.length;++d){var e=c[d];if(e.text==b.text&&e.markedSpans==b.markedSpans&&a.display.scroller.clientWidth==e.width&&e.classes==b.textClass+"|"+b.wrapClass)return e}}function P(a,b){var c=O(a,b);c&&(c.text=c.measure=c.markedSpans=null)}function Q(a,b){var c=O(a,b);if(c)return c.measure;var d=R(a,b),e=a.display.measureLineCache,f={text:b.text,width:a.display.scroller.clientWidth,markedSpans:b.markedSpans,measure:d,classes:b.textClass+"|"+b.wrapClass};return 16==e.length?e[++a.display.measureLineCachePos%16]=f:e.push(f),d}function R(a,b){function c(a){var b=a.top-o.top,c=a.bottom-o.top;c>r&&(c=r),0>b&&(b=0);for(var d=p.length-2;d>=0;d-=2){var e=p[d],f=p[d+1];if(!(e>c||b>f)&&(b>=e&&f>=c||e>=b&&c>=f||Math.min(c,f)-Math.max(b,e)>=c-b>>1)){p[d]=Math.min(b,e),p[d+1]=Math.max(c,f);break}}return 0>d&&(d=p.length,p.push(b,c)),{left:a.left-o.left,right:a.right-o.left,top:d,bottom:null}}function d(a){a.bottom=p[a.top+1],a.top=p[a.top]}if(!a.options.lineWrapping&&b.text.length>=a.options.crudeMeasuringFrom)return S(a,b);var e=a.display,f=be(b.text.length),g=cd(a,b,f,!0).pre;if(Ae&&!Be&&!a.options.lineWrapping&&g.childNodes.length>100){for(var h=document.createDocumentFragment(),i=10,j=g.childNodes.length,k=0,l=Math.ceil(j/i);l>k;++k){for(var m=fe("div",null,null,"display: inline-block"),n=0;i>n&&j;++n)m.appendChild(g.firstChild),--j;h.appendChild(m)}g.appendChild(h)}he(e.measure,g);var o=je(e.lineDiv),p=[],q=be(b.text.length),r=g.offsetHeight;Ce&&e.measure.first!=g&&he(e.measure,g);for(var s,k=0;k<f.length;++k)if(s=f[k]){var t=s,u=null;if(/\bCodeMirror-widget\b/.test(s.className)&&s.getClientRects){1==s.firstChild.nodeType&&(t=s.firstChild);var v=t.getClientRects();v.length>1&&(u=q[k]=c(v[0]),u.rightSide=c(v[v.length-1]))}u||(u=q[k]=c(je(t))),s.measureRight&&(u.right=je(s.measureRight).left),s.leftSide&&(u.leftSide=c(je(s.leftSide)))}ge(a.display.measure);for(var s,k=0;k<q.length;++k)(s=q[k])&&(d(s),s.leftSide&&d(s.leftSide),s.rightSide&&d(s.rightSide));return q}function S(a,b){var c=new qf(b.text.slice(0,100),null);b.textClass&&(c.textClass=b.textClass);var d=R(a,c),e=N(a,c,0,d,"left"),f=N(a,c,99,d,"right");return{crude:!0,top:e.top,left:e.left,bottom:e.bottom,width:(f.right-e.left)/100}}function T(a,b){var c=!1;if(b.markedSpans)for(var d=0;d<b.markedSpans;++d){var e=b.markedSpans[d];!e.collapsed||null!=e.to&&e.to!=b.text.length||(c=!0)}var f=!c&&O(a,b);if(f||b.text.length>=a.options.crudeMeasuringFrom)return N(a,b,b.text.length,f&&f.measure,"right").right;var g=cd(a,b,null,!0).pre,h=g.appendChild(me(a.display.measure));return he(a.display.measure,g),je(h).right-je(a.display.lineDiv).left}function U(a){a.display.measureLineCache.length=a.display.measureLineCachePos=0,a.display.cachedCharWidth=a.display.cachedTextHeight=null,a.options.lineWrapping||(a.display.maxLineChanged=!0),a.display.lineNumChars=null}function V(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function W(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function X(a,b,c,d){if(b.widgets)for(var e=0;e<b.widgets.length;++e)if(b.widgets[e].above){var f=Vc(b.widgets[e]);c.top+=f,c.bottom+=f}if("line"==d)return c;d||(d="local");var g=td(a,b);if("local"==d?g+=K(a.display):g-=a.display.viewOffset,"page"==d||"window"==d){var h=je(a.display.lineSpace);g+=h.top+("window"==d?0:W());var i=h.left+("window"==d?0:V());c.left+=i,c.right+=i}return c.top+=g,c.bottom+=g,c}function Y(a,b,c){if("div"==c)return b;var d=b.left,e=b.top;if("page"==c)d-=V(),e-=W();else if("local"==c||!c){var f=je(a.display.sizer);d+=f.left,e+=f.top}var g=je(a.display.lineSpace);return{left:d-g.left,top:e-g.top}}function Z(a,b,c,d,e){return d||(d=nd(a.doc,b.line)),X(a,d,N(a,d,b.ch,null,e),c)}function $(a,b,c,d,e){function f(b,f){var g=N(a,d,b,e,f?"right":"left");return f?g.left=g.right:g.right=g.left,X(a,d,g,c)}function g(a,b){var c=h[b],d=c.level%2;return a==oe(c)&&b&&c.level<h[b-1].level?(c=h[--b],a=pe(c)-(c.level%2?0:1),d=!0):a==pe(c)&&b<h.length-1&&c.level<h[b+1].level&&(c=h[++b],a=oe(c)-c.level%2,d=!1),d&&a==c.to&&a>c.from?f(a-1):f(a,d)}d=d||nd(a.doc,b.line),e||(e=Q(a,d));var h=ud(d),i=b.ch;if(!h)return f(i);var j=ve(h,i),k=g(i,j);return null!=Lf&&(k.other=g(i,Lf)),k}function _(a,b,c,d){var e=new Vb(a,b);return e.xRel=d,c&&(e.outside=!0),e}function ab(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return _(d.first,0,!0,-1);var e=sd(d,c),f=d.first+d.size-1;if(e>f)return _(d.first+d.size-1,nd(d,f).text.length,!0,1);for(0>b&&(b=0);;){var g=nd(d,e),h=bb(a,g,e,b,c),i=Oc(g),j=i&&i.find();if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=j.to.line}}function bb(a,b,c,d,e){function f(d){var e=$(a,Vb(c,d),"line",b,j);return h=!0,g>e.bottom?e.left-i:g<e.top?e.left+i:(h=!1,e.left)}var g=e-td(a,b),h=!1,i=2*a.display.wrapper.clientWidth,j=Q(a,b),k=ud(b),l=b.text.length,m=qe(b),n=re(b),o=f(m),p=h,q=f(n),r=h;if(d>q)return _(c,n,r,1);for(;;){if(k?n==m||n==xe(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);Df.test(b.text.charAt(s));)++s;var u=_(c,s,s==m?p:r,0>t?-1:t?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=xe(b,w,1)}var y=f(w);y>d?(n=w,q=y,(r=h)&&(q+=1e3),l=v):(m=w,o=y,p=h,l-=v)}}function cb(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==Re){Re=fe("pre");for(var b=0;49>b;++b)Re.appendChild(document.createTextNode("x")),Re.appendChild(fe("br"));Re.appendChild(document.createTextNode("x"))}he(a.measure,Re);var c=Re.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),ge(a.measure),c||1}function db(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=fe("span","x"),c=fe("pre",[b]);he(a.measure,c);var d=b.offsetWidth;return d>2&&(a.cachedCharWidth=d),d||10}function eb(a){a.curOp={changes:[],forceUpdate:!1,updateInput:null,userSelChange:null,textChanged:null,selectionChanged:!1,cursorActivity:!1,updateMaxLine:!1,updateScrollPos:!1,id:++Ye},yf++||(xf=[])}function fb(a){var b=a.curOp,c=a.doc,d=a.display;if(a.curOp=null,b.updateMaxLine&&l(a),d.maxLineChanged&&!a.options.lineWrapping&&d.maxLine){var e=T(a,d.maxLine);d.sizer.style.minWidth=Math.max(0,e+3+zf)+"px",d.maxLineChanged=!1;var f=Math.max(0,d.sizer.offsetLeft+d.sizer.offsetWidth-d.scroller.clientWidth);f<c.scrollLeft&&!b.updateScrollPos&&Ab(a,Math.min(d.scroller.scrollLeft,f),!0)}var g,h;if(b.updateScrollPos)g=b.updateScrollPos;else if(b.selectionChanged&&d.scroller.clientHeight){var i=$(a,c.sel.head);g=jc(a,i.left,i.top,i.left,i.bottom)}(b.changes.length||b.forceUpdate||g&&null!=g.scrollTop)&&(h=t(a,b.changes,g&&g.scrollTop,b.forceUpdate),a.display.scroller.offsetHeight&&(a.doc.scrollTop=a.display.scroller.scrollTop)),!h&&b.selectionChanged&&C(a),b.updateScrollPos?(d.scroller.scrollTop=d.scrollbarV.scrollTop=c.scrollTop=g.scrollTop,d.scroller.scrollLeft=d.scrollbarH.scrollLeft=c.scrollLeft=g.scrollLeft,p(a),b.scrollToPos&&hc(a,$b(a.doc,b.scrollToPos.from),$b(a.doc,b.scrollToPos.to),b.scrollToPos.margin)):g&&gc(a),b.selectionChanged&&F(a),a.state.focused&&b.updateInput&&nb(a,b.userSelChange);var j=b.maybeHiddenMarkers,k=b.maybeUnhiddenMarkers;if(j)for(var m=0;m<j.length;++m)j[m].lines.length||Pd(j[m],"hide");if(k)for(var m=0;m<k.length;++m)k[m].lines.length&&Pd(k[m],"unhide");var n;if(--yf||(n=xf,xf=null),b.textChanged&&Pd(a,"change",a,b.textChanged),b.cursorActivity&&Pd(a,"cursorActivity",a),n)for(var m=0;m<n.length;++m)n[m]()}function gb(a,b){return function(){var c=a||this,d=!c.curOp;d&&eb(c);try{var e=b.apply(c,arguments)}finally{d&&fb(c)}return e}}function hb(a){return function(){var b,c=this.cm&&!this.cm.curOp;c&&eb(this.cm);try{b=a.apply(this,arguments)}finally{c&&fb(this.cm)}return b}}function ib(a,b){var c,d=!a.curOp;d&&eb(a);try{c=b()}finally{d&&fb(a)}return c}function jb(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),a.curOp.changes.push({from:b,to:c,diff:d})}function kb(a){a.display.pollingFast||a.display.poll.set(a.options.pollInterval,function(){mb(a),a.state.focused&&kb(a)})}function lb(a){function b(){var d=mb(a);d||c?(a.display.pollingFast=!1,kb(a)):(c=!0,a.display.poll.set(60,b))}var c=!1;a.display.pollingFast=!0,a.display.poll.set(20,b)}function mb(a){var b=a.display.input,c=a.display.prevInput,d=a.doc,e=d.sel;if(!a.state.focused||If(b)||pb(a)||a.state.disableInput)return!1;a.state.pasteIncoming&&a.state.fakedLastChar&&(b.value=b.value.substring(0,b.value.length-1),a.state.fakedLastChar=!1);var f=b.value;if(f==c&&Wb(e.from,e.to))return!1;if(Ae&&!Ce&&a.display.inputHasSelection===f)return nb(a,!0),!1;var g=!a.curOp;g&&eb(a),e.shift=!1;for(var h=0,i=Math.min(c.length,f.length);i>h&&c.charCodeAt(h)==f.charCodeAt(h);)++h;var j=e.from,k=e.to;h<c.length?j=Vb(j.line,j.ch-(c.length-h)):a.state.overwrite&&Wb(j,k)&&!a.state.pasteIncoming&&(k=Vb(k.line,Math.min(nd(d,k.line).text.length,k.ch+(f.length-h))));var l=a.curOp.updateInput,m={from:j,to:k,text:Hf(f.slice(h)),origin:a.state.pasteIncoming?"paste":"+input"};return Ob(a.doc,m,"end"),a.curOp.updateInput=l,Qd(a,"inputRead",a,m),f.length>1e3||f.indexOf("\n")>-1?b.value=a.display.prevInput="":a.display.prevInput=f,g&&fb(a),a.state.pasteIncoming=!1,!0}function nb(a,b){var c,d,e=a.doc;if(Wb(e.sel.from,e.sel.to))b&&(a.display.prevInput=a.display.input.value="",Ae&&!Ce&&(a.display.inputHasSelection=null));else{a.display.prevInput="",c=Jf&&(e.sel.to.line-e.sel.from.line>100||(d=a.getSelection()).length>1e3);var f=c?"-":d||a.getSelection();a.display.input.value=f,a.state.focused&&Zd(a.display.input),Ae&&!Ce&&(a.display.inputHasSelection=f)}a.display.inaccurateSelection=c}function ob(a){"nocursor"==a.options.readOnly||Ne&&document.activeElement==a.display.input||a.display.input.focus()}function pb(a){return a.options.readOnly||a.doc.cantEdit}function qb(a){function b(){a.state.focused&&setTimeout(ce(ob,a),0)}function c(){null==h&&(h=setTimeout(function(){h=null,g.cachedCharWidth=g.cachedTextHeight=Ff=null,U(a),ib(a,ce(jb,a))},100))}function d(){for(var a=g.wrapper.parentNode;a&&a!=document.body;a=a.parentNode);a?setTimeout(d,5e3):Od(window,"resize",c)}function e(b){Rd(a,b)||a.options.onDragEvent&&a.options.onDragEvent(a,Gd(b))||Kd(b)}function f(){g.inaccurateSelection&&(g.prevInput="",g.inaccurateSelection=!1,g.input.value=a.getSelection(),Zd(g.input))}var g=a.display;Nd(g.scroller,"mousedown",gb(a,tb)),Ae?Nd(g.scroller,"dblclick",gb(a,function(b){if(!Rd(a,b)){var c=sb(a,b);if(c&&!wb(a,b)&&!rb(a.display,b)){Hd(b);var d=qc(nd(a.doc,c.line).text,c);bc(a.doc,d.from,d.to)}}})):Nd(g.scroller,"dblclick",function(b){Rd(a,b)||Hd(b)}),Nd(g.lineSpace,"selectstart",function(a){rb(g,a)||Hd(a)}),Ve||Nd(g.scroller,"contextmenu",function(b){Kb(a,b)}),Nd(g.scroller,"scroll",function(){g.scroller.clientHeight&&(zb(a,g.scroller.scrollTop),Ab(a,g.scroller.scrollLeft,!0),Pd(a,"scroll",a))}),Nd(g.scrollbarV,"scroll",function(){g.scroller.clientHeight&&zb(a,g.scrollbarV.scrollTop)}),Nd(g.scrollbarH,"scroll",function(){g.scroller.clientHeight&&Ab(a,g.scrollbarH.scrollLeft)}),Nd(g.scroller,"mousewheel",function(b){Bb(a,b)}),Nd(g.scroller,"DOMMouseScroll",function(b){Bb(a,b)}),Nd(g.scrollbarH,"mousedown",b),Nd(g.scrollbarV,"mousedown",b),Nd(g.wrapper,"scroll",function(){g.wrapper.scrollTop=g.wrapper.scrollLeft=0});var h;Nd(window,"resize",c),setTimeout(d,5e3),Nd(g.input,"keyup",gb(a,function(b){Rd(a,b)||a.options.onKeyEvent&&a.options.onKeyEvent(a,Gd(b))||16==b.keyCode&&(a.doc.sel.shift=!1)})),Nd(g.input,"input",function(){Ae&&!Ce&&a.display.inputHasSelection&&(a.display.inputHasSelection=null),lb(a)}),Nd(g.input,"keydown",gb(a,Gb)),Nd(g.input,"keypress",gb(a,Hb)),Nd(g.input,"focus",ce(Ib,a)),Nd(g.input,"blur",ce(Jb,a)),a.options.dragDrop&&(Nd(g.scroller,"dragstart",function(b){yb(a,b)}),Nd(g.scroller,"dragenter",e),Nd(g.scroller,"dragover",e),Nd(g.scroller,"drop",gb(a,xb))),Nd(g.scroller,"paste",function(b){rb(g,b)||(ob(a),lb(a))}),Nd(g.input,"paste",function(){if(De&&!a.state.fakedLastChar&&!(new Date-a.state.lastMiddleDown<200)){var b=g.input.selectionStart,c=g.input.selectionEnd;g.input.value+="$",g.input.selectionStart=b,g.input.selectionEnd=c,a.state.fakedLastChar=!0}a.state.pasteIncoming=!0,lb(a)}),Nd(g.input,"cut",f),Nd(g.input,"copy",f),Ie&&Nd(g.sizer,"mouseup",function(){document.activeElement==g.input&&g.input.blur(),ob(a)})}function rb(a,b){for(var c=Ld(b);c!=a.wrapper;c=c.parentNode)if(!c||c.ignoreEvents||c.parentNode==a.sizer&&c!=a.mover)return!0}function sb(a,b,c){var d=a.display;if(!c){var e=Ld(b);if(e==d.scrollbarH||e==d.scrollbarH.firstChild||e==d.scrollbarV||e==d.scrollbarV.firstChild||e==d.scrollbarFiller||e==d.gutterFiller)return null}var f,g,h=je(d.lineSpace);try{f=b.clientX,g=b.clientY}catch(b){return null}return ab(a,f-h.left,g-h.top)}function tb(a){function b(a){if(!Wb(r,a)){if(r=a,"single"==k)return bc(e.doc,$b(g,i),a),void 0;if(p=$b(g,p),q=$b(g,q),"double"==k){var b=qc(nd(g,a.line).text,a);Xb(a,p)?bc(e.doc,b.from,q):bc(e.doc,p,b.to)
2
+ }else"triple"==k&&(Xb(a,p)?bc(e.doc,q,$b(g,Vb(a.line,0))):bc(e.doc,p,$b(g,Vb(a.line+1,0))))}}function c(a){var d=++t,h=sb(e,a,!0);if(h)if(Wb(h,m)){var i=a.clientY<s.top?-20:a.clientY>s.bottom?20:0;i&&setTimeout(gb(e,function(){t==d&&(f.scroller.scrollTop+=i,c(a))}),50)}else{e.state.focused||Ib(e),m=h,b(h);var j=o(f,g);(h.line>=j.to||h.line<j.from)&&setTimeout(gb(e,function(){t==d&&c(a)}),150)}}function d(a){t=1/0,Hd(a),ob(e),Od(document,"mousemove",u),Od(document,"mouseup",v)}if(!Rd(this,a)){var e=this,f=e.display,g=e.doc,h=g.sel;if(h.shift=a.shiftKey,rb(f,a))return De||(f.scroller.draggable=!1,setTimeout(function(){f.scroller.draggable=!0},100)),void 0;if(!wb(e,a)){var i=sb(e,a);switch(Md(a)){case 3:return Ve&&Kb.call(e,e,a),void 0;case 2:return De&&(e.state.lastMiddleDown=+new Date),i&&bc(e.doc,i),setTimeout(ce(ob,e),20),Hd(a),void 0}if(!i)return Ld(a)==f.scroller&&Hd(a),void 0;e.state.focused||Ib(e);var j=+new Date,k="single";if(Te&&Te.time>j-400&&Wb(Te.pos,i))k="triple",Hd(a),setTimeout(ce(ob,e),20),rc(e,i.line);else if(Se&&Se.time>j-400&&Wb(Se.pos,i)){k="double",Te={time:j,pos:i},Hd(a);var l=qc(nd(g,i.line).text,i);bc(e.doc,l.from,l.to)}else Se={time:j,pos:i};var m=i;if(e.options.dragDrop&&Ef&&!pb(e)&&!Wb(h.from,h.to)&&!Xb(i,h.from)&&!Xb(h.to,i)&&"single"==k){var n=gb(e,function(b){De&&(f.scroller.draggable=!1),e.state.draggingText=!1,Od(document,"mouseup",n),Od(f.scroller,"drop",n),Math.abs(a.clientX-b.clientX)+Math.abs(a.clientY-b.clientY)<10&&(Hd(b),bc(e.doc,i),ob(e))});return De&&(f.scroller.draggable=!0),e.state.draggingText=n,f.scroller.dragDrop&&f.scroller.dragDrop(),Nd(document,"mouseup",n),Nd(f.scroller,"drop",n),void 0}Hd(a),"single"==k&&bc(e.doc,$b(g,i));var p=h.from,q=h.to,r=i,s=je(f.wrapper),t=0,u=gb(e,function(a){Ae||Md(a)?c(a):d(a)}),v=gb(e,d);Nd(document,"mousemove",u),Nd(document,"mouseup",v)}}}function ub(a,b,c,d,e){try{var f=b.clientX,g=b.clientY}catch(b){return!1}if(f>=Math.floor(je(a.display.gutters).right))return!1;d&&Hd(b);var h=a.display,i=je(h.lineDiv);if(g>i.bottom||!Td(a,c))return Jd(b);g-=i.top-h.viewOffset;for(var j=0;j<a.options.gutters.length;++j){var k=h.gutters.childNodes[j];if(k&&je(k).right>=f){var l=sd(a.doc,g),m=a.options.gutters[j];return e(a,c,a,l,m,b),Jd(b)}}}function vb(a,b){return Td(a,"gutterContextMenu")?ub(a,b,"gutterContextMenu",!1,Pd):!1}function wb(a,b){return ub(a,b,"gutterClick",!0,Qd)}function xb(a){var b=this;if(!(Rd(b,a)||rb(b.display,a)||b.options.onDragEvent&&b.options.onDragEvent(b,Gd(a)))){Hd(a),Ae&&(Ze=+new Date);var c=sb(b,a,!0),d=a.dataTransfer.files;if(c&&!pb(b))if(d&&d.length&&window.FileReader&&window.File)for(var e=d.length,f=Array(e),g=0,h=function(a,d){var h=new FileReader;h.onload=function(){f[d]=h.result,++g==e&&(c=$b(b.doc,c),Ob(b.doc,{from:c,to:c,text:Hf(f.join("\n")),origin:"paste"},"around"))},h.readAsText(a)},i=0;e>i;++i)h(d[i],i);else{if(b.state.draggingText&&!Xb(c,b.doc.sel.from)&&!Xb(b.doc.sel.to,c))return b.state.draggingText(a),setTimeout(ce(ob,b),20),void 0;try{var f=a.dataTransfer.getData("Text");if(f){var j=b.doc.sel.from,k=b.doc.sel.to;dc(b.doc,c,c),b.state.draggingText&&Ub(b.doc,"",j,k,"paste"),b.replaceSelection(f,null,"paste"),ob(b),Ib(b)}}catch(a){}}}}function yb(a,b){if(Ae&&(!a.state.draggingText||+new Date-Ze<100))return Kd(b),void 0;if(!Rd(a,b)&&!rb(a.display,b)){var c=a.getSelection();if(b.dataTransfer.setData("Text",c),b.dataTransfer.setDragImage&&!He){var d=fe("img",null,null,"position: fixed; left: 0; top: 0;");d.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",Ge&&(d.width=d.height=1,a.display.wrapper.appendChild(d),d._top=d.offsetTop),b.dataTransfer.setDragImage(d,0,0),Ge&&d.parentNode.removeChild(d)}}}function zb(a,b){Math.abs(a.doc.scrollTop-b)<2||(a.doc.scrollTop=b,ze||t(a,[],b),a.display.scroller.scrollTop!=b&&(a.display.scroller.scrollTop=b),a.display.scrollbarV.scrollTop!=b&&(a.display.scrollbarV.scrollTop=b),ze&&t(a,[]),G(a,100))}function Ab(a,b,c){(c?b==a.doc.scrollLeft:Math.abs(a.doc.scrollLeft-b)<2)||(b=Math.min(b,a.display.scroller.scrollWidth-a.display.scroller.clientWidth),a.doc.scrollLeft=b,p(a),a.display.scroller.scrollLeft!=b&&(a.display.scroller.scrollLeft=b),a.display.scrollbarH.scrollLeft!=b&&(a.display.scrollbarH.scrollLeft=b))}function Bb(a,b){var c=b.wheelDeltaX,d=b.wheelDeltaY;null==c&&b.detail&&b.axis==b.HORIZONTAL_AXIS&&(c=b.detail),null==d&&b.detail&&b.axis==b.VERTICAL_AXIS?d=b.detail:null==d&&(d=b.wheelDelta);var e=a.display,f=e.scroller;if(c&&f.scrollWidth>f.clientWidth||d&&f.scrollHeight>f.clientHeight){if(d&&Oe&&De)for(var g=b.target;g!=f;g=g.parentNode)if(g.lineObj){a.display.currentWheelTarget=g;break}if(c&&!ze&&!Ge&&null!=_e)return d&&zb(a,Math.max(0,Math.min(f.scrollTop+d*_e,f.scrollHeight-f.clientHeight))),Ab(a,Math.max(0,Math.min(f.scrollLeft+c*_e,f.scrollWidth-f.clientWidth))),Hd(b),e.wheelStartX=null,void 0;if(d&&null!=_e){var h=d*_e,i=a.doc.scrollTop,j=i+e.wrapper.clientHeight;0>h?i=Math.max(0,i+h-50):j=Math.min(a.doc.height,j+h+50),t(a,[],{top:i,bottom:j})}20>$e&&(null==e.wheelStartX?(e.wheelStartX=f.scrollLeft,e.wheelStartY=f.scrollTop,e.wheelDX=c,e.wheelDY=d,setTimeout(function(){if(null!=e.wheelStartX){var a=f.scrollLeft-e.wheelStartX,b=f.scrollTop-e.wheelStartY,c=b&&e.wheelDY&&b/e.wheelDY||a&&e.wheelDX&&a/e.wheelDX;e.wheelStartX=e.wheelStartY=null,c&&(_e=(_e*$e+c)/($e+1),++$e)}},200)):(e.wheelDX+=c,e.wheelDY+=d))}}function Cb(a,b,c){if("string"==typeof b&&(b=nf[b],!b))return!1;a.display.pollingFast&&mb(a)&&(a.display.pollingFast=!1);var d=a.doc,e=d.sel.shift,f=!1;try{pb(a)&&(a.state.suppressEdits=!0),c&&(d.sel.shift=!1),f=b(a)!=Af}finally{d.sel.shift=e,a.state.suppressEdits=!1}return f}function Db(a){var b=a.state.keyMaps.slice(0);return a.options.extraKeys&&b.push(a.options.extraKeys),b.push(a.options.keyMap),b}function Eb(a,b){var c=vc(a.options.keyMap),d=c.auto;clearTimeout(af),d&&!xc(b)&&(af=setTimeout(function(){vc(a.options.keyMap)==c&&(a.options.keyMap=d.call?d.call(null,a):d,g(a))},50));var e=yc(b,!0),f=!1;if(!e)return!1;var h=Db(a);return f=b.shiftKey?wc("Shift-"+e,h,function(b){return Cb(a,b,!0)})||wc(e,h,function(b){return("string"==typeof b?/^go[A-Z]/.test(b):b.motion)?Cb(a,b):void 0}):wc(e,h,function(b){return Cb(a,b)}),f&&(Hd(b),F(a),Ce&&(b.oldKeyCode=b.keyCode,b.keyCode=0),Qd(a,"keyHandled",a,e,b)),f}function Fb(a,b,c){var d=wc("'"+c+"'",Db(a),function(b){return Cb(a,b,!0)});return d&&(Hd(b),F(a),Qd(a,"keyHandled",a,"'"+c+"'",b)),d}function Gb(a){var b=this;if(b.state.focused||Ib(b),!(Rd(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Gd(a)))){Ae&&27==a.keyCode&&(a.returnValue=!1);var c=a.keyCode;b.doc.sel.shift=16==c||a.shiftKey;var d=Eb(b,a);Ge&&(cf=d?c:null,!d&&88==c&&!Jf&&(Oe?a.metaKey:a.ctrlKey)&&b.replaceSelection(""))}}function Hb(a){var b=this;if(!(Rd(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Gd(a)))){var c=a.keyCode,d=a.charCode;if(Ge&&c==cf)return cf=null,Hd(a),void 0;if(!(Ge&&(!a.which||a.which<10)||Ie)||!Eb(b,a)){var e=String.fromCharCode(null==d?c:d);this.options.electricChars&&this.doc.mode.electricChars&&this.options.smartIndent&&!pb(this)&&this.doc.mode.electricChars.indexOf(e)>-1&&setTimeout(gb(b,function(){mc(b,b.doc.sel.to.line,"smart")}),75),Fb(b,a,e)||(Ae&&!Ce&&(b.display.inputHasSelection=null),lb(b))}}}function Ib(a){"nocursor"!=a.options.readOnly&&(a.state.focused||(Pd(a,"focus",a),a.state.focused=!0,-1==a.display.wrapper.className.search(/\bCodeMirror-focused\b/)&&(a.display.wrapper.className+=" CodeMirror-focused"),a.curOp||(nb(a,!0),De&&setTimeout(ce(nb,a,!0),0))),kb(a),F(a))}function Jb(a){a.state.focused&&(Pd(a,"blur",a),a.state.focused=!1,a.display.wrapper.className=a.display.wrapper.className.replace(" CodeMirror-focused","")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.doc.sel.shift=!1)},150)}function Kb(a,b){function c(){if(null!=e.input.selectionStart){var a=e.input.value="​"+(Wb(f.from,f.to)?"":e.input.value);e.prevInput="​",e.input.selectionStart=1,e.input.selectionEnd=a.length}}function d(){if(e.inputDiv.style.position="relative",e.input.style.cssText=j,Ce&&(e.scrollbarV.scrollTop=e.scroller.scrollTop=h),kb(a),null!=e.input.selectionStart){(!Ae||Ce)&&c(),clearTimeout(bf);var b=0,d=function(){" "==e.prevInput&&0==e.input.selectionStart?gb(a,nf.selectAll)(a):b++<10?bf=setTimeout(d,500):nb(a)};bf=setTimeout(d,200)}}if(!Rd(a,b,"contextmenu")){var e=a.display,f=a.doc.sel;if(!rb(e,b)&&!vb(a,b)){var g=sb(a,b),h=e.scroller.scrollTop;if(g&&!Ge){var i=a.options.resetSelectionOnContextMenu;i&&(Wb(f.from,f.to)||Xb(g,f.from)||!Xb(g,f.to))&&gb(a,dc)(a.doc,g,g);var j=e.input.style.cssText;if(e.inputDiv.style.position="absolute",e.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(b.clientY-5)+"px; left: "+(b.clientX-5)+"px; z-index: 1000; background: white; outline: none;"+"border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);",ob(a),nb(a,!0),Wb(f.from,f.to)&&(e.input.value=e.prevInput=" "),Ae&&!Ce&&c(),Ve){Kd(b);var k=function(){Od(window,"mouseup",k),setTimeout(d,20)};Nd(window,"mouseup",k)}else setTimeout(d,50)}}}}function Lb(a,b,c){if(!Xb(b.from,c))return $b(a,c);var d=b.text.length-1-(b.to.line-b.from.line);if(c.line>b.to.line+d){var e=c.line-d,f=a.first+a.size-1;return e>f?Vb(f,nd(a,f).text.length):_b(c,nd(a,e).text.length)}if(c.line==b.to.line+d)return _b(c,Yd(b.text).length+(1==b.text.length?b.from.ch:0)+nd(a,b.to.line).text.length-b.to.ch);var g=c.line-b.from.line;return _b(c,b.text[g].length+(g?0:b.from.ch))}function Mb(a,b,c){if(c&&"object"==typeof c)return{anchor:Lb(a,b,c.anchor),head:Lb(a,b,c.head)};if("start"==c)return{anchor:b.from,head:b.from};var d=df(b);if("around"==c)return{anchor:b.from,head:d};if("end"==c)return{anchor:d,head:d};var e=function(a){if(Xb(a,b.from))return a;if(!Xb(b.to,a))return d;var c=a.line+b.text.length-(b.to.line-b.from.line)-1,e=a.ch;return a.line==b.to.line&&(e+=d.ch-b.to.ch),Vb(c,e)};return{anchor:e(a.sel.anchor),head:e(a.sel.head)}}function Nb(a,b,c){var d={canceled:!1,from:b.from,to:b.to,text:b.text,origin:b.origin,cancel:function(){this.canceled=!0}};return c&&(d.update=function(b,c,d,e){b&&(this.from=$b(a,b)),c&&(this.to=$b(a,c)),d&&(this.text=d),void 0!==e&&(this.origin=e)}),Pd(a,"beforeChange",a,d),a.cm&&Pd(a.cm,"beforeChange",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function Ob(a,b,c,d){if(a.cm){if(!a.cm.curOp)return gb(a.cm,Ob)(a,b,c,d);if(a.cm.state.suppressEdits)return}if(!(Td(a,"beforeChange")||a.cm&&Td(a.cm,"beforeChange"))||(b=Nb(a,b,!0))){var e=We&&!d&&Lc(a,b.from,b.to);if(e){for(var f=e.length-1;f>=1;--f)Pb(a,{from:e[f].from,to:e[f].to,text:[""]});e.length&&Pb(a,{from:e[0].from,to:e[0].to,text:b.text},c)}else Pb(a,b,c)}}function Pb(a,b,c){if(1!=b.text.length||""!=b.text[0]||!Wb(b.from,b.to)){var d=Mb(a,b,c);yd(a,b,d,a.cm?a.cm.curOp.id:0/0),Sb(a,b,d,Jc(a,b));var e=[];ld(a,function(a,c){c||-1!=$d(e,a.history)||(Ed(a.history,b),e.push(a.history)),Sb(a,b,null,Jc(a,b))})}}function Qb(a,b){if(!a.cm||!a.cm.state.suppressEdits){var c=a.history,d=("undo"==b?c.done:c.undone).pop();if(d){var e={changes:[],anchorBefore:d.anchorAfter,headBefore:d.headAfter,anchorAfter:d.anchorBefore,headAfter:d.headBefore,generation:c.generation};("undo"==b?c.undone:c.done).push(e),c.generation=d.generation||++c.maxGeneration;for(var f=Td(a,"beforeChange")||a.cm&&Td(a.cm,"beforeChange"),g=d.changes.length-1;g>=0;--g){var h=d.changes[g];if(h.origin=b,f&&!Nb(a,h,!1))return("undo"==b?c.done:c.undone).length=0,void 0;e.changes.push(xd(a,h));var i=g?Mb(a,h,null):{anchor:d.anchorBefore,head:d.headBefore};Sb(a,h,i,Kc(a,h));var j=[];ld(a,function(a,b){b||-1!=$d(j,a.history)||(Ed(a.history,h),j.push(a.history)),Sb(a,h,null,Kc(a,h))})}}}}function Rb(a,b){function c(a){return Vb(a.line+b,a.ch)}a.first+=b,a.cm&&jb(a.cm,a.first,a.first,b),a.sel.head=c(a.sel.head),a.sel.anchor=c(a.sel.anchor),a.sel.from=c(a.sel.from),a.sel.to=c(a.sel.to)}function Sb(a,b,c,d){if(a.cm&&!a.cm.curOp)return gb(a.cm,Sb)(a,b,c,d);if(b.to.line<a.first)return Rb(a,b.text.length-1-(b.to.line-b.from.line)),void 0;if(!(b.from.line>a.lastLine())){if(b.from.line<a.first){var e=b.text.length-1-(a.first-b.from.line);Rb(a,e),b={from:Vb(a.first,0),to:Vb(b.to.line+e,b.to.ch),text:[Yd(b.text)],origin:b.origin}}var f=a.lastLine();b.to.line>f&&(b={from:b.from,to:Vb(f,nd(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=od(a,b.from,b.to),c||(c=Mb(a,b,null)),a.cm?Tb(a.cm,b,d,c):id(a,b,d,c)}}function Tb(a,b,c,d){var f=a.doc,g=a.display,h=b.from,i=b.to,j=!1,l=h.line;a.options.lineWrapping||(l=rd(Pc(f,nd(f,h.line))),f.iter(l,i.line+1,function(a){return a==g.maxLine?(j=!0,!0):void 0})),Xb(f.sel.head,b.from)||Xb(b.to,f.sel.head)||(a.curOp.cursorActivity=!0),id(f,b,c,d,e(a)),a.options.lineWrapping||(f.iter(l,h.line+b.text.length,function(a){var b=k(f,a);b>g.maxLineLength&&(g.maxLine=a,g.maxLineLength=b,g.maxLineChanged=!0,j=!1)}),j&&(a.curOp.updateMaxLine=!0)),f.frontier=Math.min(f.frontier,h.line),G(a,400);var m=b.text.length-(i.line-h.line)-1;if(jb(a,h.line,i.line+1,m),Td(a,"change")){var n={from:h,to:i,text:b.text,removed:b.removed,origin:b.origin};if(a.curOp.textChanged){for(var o=a.curOp.textChanged;o.next;o=o.next);o.next=n}else a.curOp.textChanged=n}}function Ub(a,b,c,d,e){if(d||(d=c),Xb(d,c)){var f=d;d=c,c=f}"string"==typeof b&&(b=Hf(b)),Ob(a,{from:c,to:d,text:b,origin:e},null)}function Vb(a,b){return this instanceof Vb?(this.line=a,this.ch=b,void 0):new Vb(a,b)}function Wb(a,b){return a.line==b.line&&a.ch==b.ch}function Xb(a,b){return a.line<b.line||a.line==b.line&&a.ch<b.ch}function Yb(a){return Vb(a.line,a.ch)}function Zb(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function $b(a,b){if(b.line<a.first)return Vb(a.first,0);var c=a.first+a.size-1;return b.line>c?Vb(c,nd(a,c).text.length):_b(b,nd(a,b.line).text.length)}function _b(a,b){var c=a.ch;return null==c||c>b?Vb(a.line,b):0>c?Vb(a.line,0):a}function ac(a,b){return b>=a.first&&b<a.first+a.size}function bc(a,b,c,d){if(a.sel.shift||a.sel.extend){var e=a.sel.anchor;if(c){var f=Xb(b,e);f!=Xb(c,e)?(e=b,b=c):f!=Xb(b,c)&&(b=c)}dc(a,e,b,d)}else dc(a,b,c||b,d);a.cm&&(a.cm.curOp.userSelChange=!0)}function cc(a,b,c){var d={anchor:b,head:c};return Pd(a,"beforeSelectionChange",a,d),a.cm&&Pd(a.cm,"beforeSelectionChange",a.cm,d),d.anchor=$b(a,d.anchor),d.head=$b(a,d.head),d}function dc(a,b,c,d,e){if(!e&&Td(a,"beforeSelectionChange")||a.cm&&Td(a.cm,"beforeSelectionChange")){var f=cc(a,b,c);c=f.head,b=f.anchor}var g=a.sel;if(g.goalColumn=null,null==d&&(d=Xb(c,g.head)?-1:1),(e||!Wb(b,g.anchor))&&(b=fc(a,b,d,"push"!=e)),(e||!Wb(c,g.head))&&(c=fc(a,c,d,"push"!=e)),!Wb(g.anchor,b)||!Wb(g.head,c)){g.anchor=b,g.head=c;var h=Xb(c,b);g.from=h?c:b,g.to=h?b:c,a.cm&&(a.cm.curOp.updateInput=a.cm.curOp.selectionChanged=a.cm.curOp.cursorActivity=!0),Qd(a,"cursorActivity",a)}}function ec(a){dc(a.doc,a.doc.sel.from,a.doc.sel.to,null,"push")}function fc(a,b,c,d){var e=!1,f=b,g=c||1;a.cantEdit=!1;a:for(;;){var h=nd(a,f.line);if(h.markedSpans)for(var i=0;i<h.markedSpans.length;++i){var j=h.markedSpans[i],k=j.marker;if((null==j.from||(k.inclusiveLeft?j.from<=f.ch:j.from<f.ch))&&(null==j.to||(k.inclusiveRight?j.to>=f.ch:j.to>f.ch))){if(d&&(Pd(k,"beforeCursorEnter"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find()[0>g?"from":"to"];if(Wb(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?$b(a,Vb(l.line-1)):null:l.ch>h.text.length&&(l=l.line<a.first+a.size-1?Vb(l.line+1,0):null),!l)){if(e)return d?(a.cantEdit=!0,Vb(a.first,0)):fc(a,b,c,!0);e=!0,l=b,g=-g}f=l;continue a}}return f}}function gc(a){var b=hc(a,a.doc.sel.head,null,a.options.cursorScrollMargin);if(a.state.focused){var c=a.display,d=je(c.sizer),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!Le){var f="none"==c.cursor.style.display;f&&(c.cursor.style.display="",c.cursor.style.left=b.left+"px",c.cursor.style.top=b.top-c.viewOffset+"px"),c.cursor.scrollIntoView(e),f&&(c.cursor.style.display="none")}}}function hc(a,b,c,d){for(null==d&&(d=0);;){var e=!1,f=$(a,b),g=c&&c!=b?$(a,c):f,h=jc(a,Math.min(f.left,g.left),Math.min(f.top,g.top)-d,Math.max(f.left,g.left),Math.max(f.bottom,g.bottom)+d),i=a.doc.scrollTop,j=a.doc.scrollLeft;if(null!=h.scrollTop&&(zb(a,h.scrollTop),Math.abs(a.doc.scrollTop-i)>1&&(e=!0)),null!=h.scrollLeft&&(Ab(a,h.scrollLeft),Math.abs(a.doc.scrollLeft-j)>1&&(e=!0)),!e)return f}}function ic(a,b,c,d,e){var f=jc(a,b,c,d,e);null!=f.scrollTop&&zb(a,f.scrollTop),null!=f.scrollLeft&&Ab(a,f.scrollLeft)}function jc(a,b,c,d,e){var f=a.display,g=cb(a.display);0>c&&(c=0);var h=f.scroller.clientHeight-zf,i=f.scroller.scrollTop,j={},k=a.doc.height+L(f),l=g>c,m=e>k-g;if(i>c)j.scrollTop=l?0:c;else if(e>i+h){var n=Math.min(c,(m?k:e)-h);n!=i&&(j.scrollTop=n)}var o=f.scroller.clientWidth-zf,p=f.scroller.scrollLeft;b+=f.gutters.offsetWidth,d+=f.gutters.offsetWidth;var q=f.gutters.offsetWidth,r=q+10>b;return p+q>b||r?(r&&(b=0),j.scrollLeft=Math.max(0,b-10-q)):d>o+p-3&&(j.scrollLeft=d+10-o),j}function kc(a,b,c){a.curOp.updateScrollPos={scrollLeft:null==b?a.doc.scrollLeft:b,scrollTop:null==c?a.doc.scrollTop:c}}function lc(a,b,c){var d=a.curOp.updateScrollPos||(a.curOp.updateScrollPos={scrollLeft:a.doc.scrollLeft,scrollTop:a.doc.scrollTop}),e=a.display.scroller;d.scrollTop=Math.max(0,Math.min(e.scrollHeight-e.clientHeight,d.scrollTop+c)),d.scrollLeft=Math.max(0,Math.min(e.scrollWidth-e.clientWidth,d.scrollLeft+b))}function mc(a,b,c,d){var e=a.doc;if(null==c&&(c="add"),"smart"==c)if(a.doc.mode.indent)var f=J(a,b);else c="prev";var g,h=a.options.tabSize,i=nd(e,b),j=Wd(i.text,null,h),k=i.text.match(/^\s*/)[0];if("smart"==c&&(g=a.doc.mode.indent(f,i.text.slice(k.length),i.text),g==Af)){if(!d)return;c="prev"}"prev"==c?g=b>e.first?Wd(nd(e,b-1).text,null,h):0:"add"==c?g=j+a.options.indentUnit:"subtract"==c?g=j-a.options.indentUnit:"number"==typeof c&&(g=j+c),g=Math.max(0,g);var l="",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(g/h);n;--n)m+=h,l+=" ";g>m&&(l+=Xd(g-m)),l!=k&&Ub(a.doc,l,Vb(b,0),Vb(b,k.length),"+input"),i.stateAfter=null}function nc(a,b,c){var d=b,e=b,f=a.doc;return"number"==typeof b?e=nd(f,Zb(f,b)):d=rd(b),null==d?null:c(e,d)?(jb(a,d,d+1),e):null}function oc(a,b,c,d,e){function f(){var b=h+c;return b<a.first||b>=a.first+a.size?l=!1:(h=b,k=nd(a,b))}function g(a){var b=(e?xe:ye)(k,i,c,!0);if(null==b){if(a||!f())return l=!1;i=e?(0>c?re:qe)(k):0>c?k.text.length:0}else i=b;return!0}var h=b.line,i=b.ch,j=c,k=nd(a,h),l=!0;if("char"==d)g();else if("column"==d)g(!0);else if("word"==d||"group"==d)for(var m=null,n="group"==d,o=!0;!(0>c)||g(!o);o=!1){var p=k.text.charAt(i)||"\n",q=de(p)?"w":n?/\s/.test(p)?null:"p":null;if(m&&m!=q){0>c&&(c=1,g());break}if(q&&(m=q),c>0&&!g(!o))break}var r=fc(a,Vb(h,i),j,!0);return l||(r.hitSide=!0),r}function pc(a,b,c,d){var e,f=a.doc,g=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);e=b.top+c*(h-(0>c?1.5:.5)*cb(a.display))}else"line"==d&&(e=c>0?b.bottom+3:b.top-3);for(;;){var i=ab(a,g,e);if(!i.outside)break;if(0>c?0>=e:e>=f.height){i.hitSide=!0;break}e+=5*c}return i}function qc(a,b){var c=b.ch,d=b.ch;if(a){(b.xRel<0||d==a.length)&&c?--c:++d;for(var e=a.charAt(c),f=de(e)?de:/\s/.test(e)?function(a){return/\s/.test(a)}:function(a){return!/\s/.test(a)&&!de(a)};c>0&&f(a.charAt(c-1));)--c;for(;d<a.length&&f(a.charAt(d));)++d}return{from:Vb(b.line,c),to:Vb(b.line,d)}}function rc(a,b){bc(a.doc,Vb(b,0),$b(a.doc,Vb(b+1,0)))}function sc(b,c,d,e){a.defaults[b]=c,d&&(ef[b]=e?function(a,b,c){c!=gf&&d(a,b,c)}:d)}function tc(a,b){if(b===!0)return b;if(a.copyState)return a.copyState(b);var c={};for(var d in b){var e=b[d];e instanceof Array&&(e=e.concat([])),c[d]=e}return c}function uc(a,b,c){return a.startState?a.startState(b,c):!0}function vc(a){return"string"==typeof a?of[a]:a}function wc(a,b,c){function d(b){b=vc(b);var e=b[a];if(e===!1)return"stop";if(null!=e&&c(e))return!0;if(b.nofallthrough)return"stop";var f=b.fallthrough;if(null==f)return!1;if("[object Array]"!=Object.prototype.toString.call(f))return d(f);for(var g=0,h=f.length;h>g;++g){var i=d(f[g]);if(i)return i}return!1}for(var e=0;e<b.length;++e){var f=d(b[e]);if(f)return"stop"!=f}}function xc(a){var b=Kf[a.keyCode];return"Ctrl"==b||"Alt"==b||"Shift"==b||"Mod"==b}function yc(a,b){if(Ge&&34==a.keyCode&&a["char"])return!1;var c=Kf[a.keyCode];return null==c||a.altGraphKey?!1:(a.altKey&&(c="Alt-"+c),(Ue?a.metaKey:a.ctrlKey)&&(c="Ctrl-"+c),(Ue?a.ctrlKey:a.metaKey)&&(c="Cmd-"+c),!b&&a.shiftKey&&(c="Shift-"+c),c)}function zc(a,b){this.pos=this.start=0,this.string=a,this.tabSize=b||8,this.lastColumnPos=this.lastColumnValue=0}function Ac(a,b){this.lines=[],this.type=b,this.doc=a}function Bc(a,b,c,d,e){if(d&&d.shared)return Dc(a,b,c,d,e);if(a.cm&&!a.cm.curOp)return gb(a.cm,Bc)(a,b,c,d,e);var f=new Ac(a,e);if("range"==e&&!Xb(b,c))return f;d&&ae(d,f),f.replacedWith&&(f.collapsed=!0,f.replacedWith=fe("span",[f.replacedWith],"CodeMirror-widget"),d.handleMouseEvents||(f.replacedWith.ignoreEvents=!0)),f.collapsed&&(Xe=!0),f.addToHistory&&yd(a,{from:b,to:c,origin:"markText"},{head:a.sel.head,anchor:a.sel.anchor},0/0);var g,h,i,j=b.line,k=0,l=a.cm;if(a.iter(j,c.line+1,function(d){l&&f.collapsed&&!l.options.lineWrapping&&Pc(a,d)==l.display.maxLine&&(i=!0);var e={from:null,to:null,marker:f};k+=d.text.length,j==b.line&&(e.from=b.ch,k-=b.ch),j==c.line&&(e.to=c.ch,k-=d.text.length-c.ch),f.collapsed&&(j==c.line&&(h=Mc(d,c.ch)),j==b.line?g=Mc(d,b.ch):qd(d,0)),Gc(d,e),++j}),f.collapsed&&a.iter(b.line,c.line+1,function(b){Qc(a,b)&&qd(b,0)}),f.clearOnEnter&&Nd(f,"beforeCursorEnter",function(){f.clear()}),f.readOnly&&(We=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed){if(g!=h)throw new Error("Inserting collapsed marker overlapping an existing one");f.size=k,f.atomic=!0}return l&&(i&&(l.curOp.updateMaxLine=!0),(f.className||f.title||f.startStyle||f.endStyle||f.collapsed)&&jb(l,b.line,c.line+1),f.atomic&&ec(l)),f}function Cc(a,b){this.markers=a,this.primary=b;for(var c=0,d=this;c<a.length;++c)a[c].parent=this,Nd(a[c],"clear",function(){d.clear()})}function Dc(a,b,c,d,e){d=ae(d),d.shared=!1;var f=[Bc(a,b,c,d,e)],g=f[0],h=d.replacedWith;return ld(a,function(a){h&&(d.replacedWith=h.cloneNode(!0)),f.push(Bc(a,$b(a,b),$b(a,c),d,e));for(var i=0;i<a.linked.length;++i)if(a.linked[i].isParent)return;g=Yd(f)}),new Cc(f,g)}function Ec(a,b){if(a)for(var c=0;c<a.length;++c){var d=a[c];if(d.marker==b)return d}}function Fc(a,b){for(var c,d=0;d<a.length;++d)a[d]!=b&&(c||(c=[])).push(a[d]);return c}function Gc(a,b){a.markedSpans=a.markedSpans?a.markedSpans.concat([b]):[b],b.marker.attachLine(a)}function Hc(a,b,c){if(a)for(var d,e=0;e<a.length;++e){var f=a[e],g=f.marker,h=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);if(h||"bookmark"==g.type&&f.from==b&&(!c||!f.marker.insertLeft)){var i=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);(d||(d=[])).push({from:f.from,to:i?null:f.to,marker:g})}}return d}function Ic(a,b,c){if(a)for(var d,e=0;e<a.length;++e){var f=a[e],g=f.marker,h=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);if(h||"bookmark"==g.type&&f.from==b&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);(d||(d=[])).push({from:i?null:f.from-b,to:null==f.to?null:f.to-b,marker:g})}}return d}function Jc(a,b){var c=ac(a,b.from.line)&&nd(a,b.from.line).markedSpans,d=ac(a,b.to.line)&&nd(a,b.to.line).markedSpans;if(!c&&!d)return null;var e=b.from.ch,f=b.to.ch,g=Wb(b.from,b.to),h=Hc(c,e,g),i=Ic(d,f,g),j=1==b.text.length,k=Yd(b.text).length+(j?e:0);if(h)for(var l=0;l<h.length;++l){var m=h[l];if(null==m.to){var n=Ec(i,m.marker);n?j&&(m.to=null==n.to?null:n.to+k):m.to=e}}if(i)for(var l=0;l<i.length;++l){var m=i[l];if(null!=m.to&&(m.to+=k),null==m.from){var n=Ec(h,m.marker);n||(m.from=k,j&&(h||(h=[])).push(m))}else m.from+=k,j&&(h||(h=[])).push(m)}if(j&&h){for(var l=0;l<h.length;++l)null!=h[l].from&&h[l].from==h[l].to&&"bookmark"!=h[l].marker.type&&h.splice(l--,1);h.length||(h=null)}var o=[h];if(!j){var p,q=b.text.length-2;if(q>0&&h)for(var l=0;l<h.length;++l)null==h[l].to&&(p||(p=[])).push({from:null,to:null,marker:h[l].marker});for(var l=0;q>l;++l)o.push(p);o.push(i)}return o}function Kc(a,b){var c=Ad(a,b),d=Jc(a,b);if(!c)return d;if(!d)return c;for(var e=0;e<c.length;++e){var f=c[e],g=d[e];if(f&&g)a:for(var h=0;h<g.length;++h){for(var i=g[h],j=0;j<f.length;++j)if(f[j].marker==i.marker)continue a;f.push(i)}else g&&(c[e]=g)}return c}function Lc(a,b,c){var d=null;if(a.iter(b.line,c.line+1,function(a){if(a.markedSpans)for(var b=0;b<a.markedSpans.length;++b){var c=a.markedSpans[b].marker;!c.readOnly||d&&-1!=$d(d,c)||(d||(d=[])).push(c)}}),!d)return null;for(var e=[{from:b,to:c}],f=0;f<d.length;++f)for(var g=d[f],h=g.find(),i=0;i<e.length;++i){var j=e[i];if(!Xb(j.to,h.from)&&!Xb(h.to,j.from)){var k=[i,1];(Xb(j.from,h.from)||!g.inclusiveLeft&&Wb(j.from,h.from))&&k.push({from:j.from,to:h.from}),(Xb(h.to,j.to)||!g.inclusiveRight&&Wb(j.to,h.to))&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function Mc(a,b){var c,d=Xe&&a.markedSpans;if(d)for(var e,f=0;f<d.length;++f)e=d[f],e.marker.collapsed&&(null==e.from||e.from<b)&&(null==e.to||e.to>b)&&(!c||c.width<e.marker.width)&&(c=e.marker);return c}function Nc(a){return Mc(a,-1)}function Oc(a){return Mc(a,a.text.length+1)}function Pc(a,b){for(var c;c=Nc(b);)b=nd(a,c.find().from.line);return b}function Qc(a,b){var c=Xe&&b.markedSpans;if(c)for(var d,e=0;e<c.length;++e)if(d=c[e],d.marker.collapsed){if(null==d.from)return!0;if(!d.marker.replacedWith&&0==d.from&&d.marker.inclusiveLeft&&Rc(a,b,d))return!0}}function Rc(a,b,c){if(null==c.to){var d=c.marker.find().to,e=nd(a,d.line);return Rc(a,e,Ec(e.markedSpans,c.marker))}if(c.marker.inclusiveRight&&c.to==b.text.length)return!0;for(var f,g=0;g<b.markedSpans.length;++g)if(f=b.markedSpans[g],f.marker.collapsed&&!f.marker.replacedWith&&f.from==c.to&&(f.marker.inclusiveLeft||c.marker.inclusiveRight)&&Rc(a,b,f))return!0}function Sc(a){var b=a.markedSpans;if(b){for(var c=0;c<b.length;++c)b[c].marker.detachLine(a);a.markedSpans=null}}function Tc(a,b){if(b){for(var c=0;c<b.length;++c)b[c].marker.attachLine(a);a.markedSpans=b}}function Uc(a){return function(){var b=!this.cm.curOp;b&&eb(this.cm);try{var c=a.apply(this,arguments)}finally{b&&fb(this.cm)}return c}}function Vc(a){return null!=a.height?a.height:(a.node.parentNode&&1==a.node.parentNode.nodeType||he(a.cm.display.measure,fe("div",[a.node],null,"position: relative")),a.height=a.node.offsetHeight)}function Wc(a,b,c,d){var e=new pf(a,c,d);return e.noHScroll&&(a.display.alignWidgets=!0),nc(a,b,function(b){var c=b.widgets||(b.widgets=[]);if(null==e.insertAt?c.push(e):c.splice(Math.min(c.length-1,Math.max(0,e.insertAt)),0,e),e.line=b,!Qc(a.doc,b)||e.showIfHidden){var d=td(a,b)<a.doc.scrollTop;qd(b,b.height+Vc(e)),d&&lc(a,0,e.height)}return!0}),e}function Xc(a,b,c,d){a.text=b,a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null),null!=a.order&&(a.order=null),Sc(a),Tc(a,c);var e=d?d(a):1;e!=a.height&&qd(a,e)}function Yc(a){a.parent=null,Sc(a)}function Zc(a,b,c,d,e){var f=c.flattenSpans;null==f&&(f=a.options.flattenSpans);var g,h=0,i=null,j=new zc(b,a.options.tabSize);for(""==b&&c.blankLine&&c.blankLine(d);!j.eol();)j.pos>a.options.maxHighlightLength?(f=!1,j.pos=b.length,g=null):g=c.token(j,d),f&&i==g||(h<j.start&&e(j.start,i),h=j.start,i=g),j.start=j.pos;for(;h<j.pos;){var k=Math.min(j.pos,h+5e4);e(k,i),h=k}}function $c(a,b,c){var d=[a.state.modeGen];Zc(a,b.text,a.doc.mode,c,function(a,b){d.push(a,b)});for(var e=0;e<a.state.overlays.length;++e){var f=a.state.overlays[e],g=1,h=0;Zc(a,b.text,f.mode,!0,function(a,b){for(var c=g;a>h;){var e=d[g];e>a&&d.splice(g,1,a,d[g+1],e),g+=2,h=Math.min(a,e)}if(b)if(f.opaque)d.splice(c,g-c,a,b),g=c+2;else for(;g>c;c+=2){var i=d[c+1];d[c+1]=i?i+" "+b:b}})}return d}function _c(a,b){return b.styles&&b.styles[0]==a.state.modeGen||(b.styles=$c(a,b,b.stateAfter=J(a,rd(b)))),b.styles}function ad(a,b,c){var d=a.doc.mode,e=new zc(b.text,a.options.tabSize);for(""==b.text&&d.blankLine&&d.blankLine(c);!e.eol()&&e.pos<=a.options.maxHighlightLength;)d.token(e,c),e.start=e.pos}function bd(a,b){if(!a)return null;for(;;){var c=a.match(/(?:^|\s)line-(background-)?(\S+)/);if(!c)break;a=a.slice(0,c.index)+a.slice(c.index+c[0].length);var d=c[1]?"bgClass":"textClass";null==b[d]?b[d]=c[2]:new RegExp("(?:^|s)"+c[2]+"(?:$|s)").test(b[d])||(b[d]+=" "+c[2])}return rf[a]||(rf[a]="cm-"+a.replace(/ +/g," cm-"))}function cd(a,b,c,d){for(var e,f=b,g=!0;e=Nc(f);)f=nd(a.doc,e.find().from.line);var h={pre:fe("pre"),col:0,pos:0,measure:null,measuredSomething:!1,cm:a,copyWidgets:d};do{f.text&&(g=!1),h.measure=f==b&&c,h.pos=0,h.addToken=h.measure?ed:dd,(Ae||De)&&a.getOption("lineWrapping")&&(h.addToken=fd(h.addToken));var i=hd(f,h,_c(a,f));c&&f==b&&!h.measuredSomething&&(c[0]=h.pre.appendChild(me(a.display.measure)),h.measuredSomething=!0),i&&(f=nd(a.doc,i.to.line))}while(i);!c||h.measuredSomething||c[0]||(c[0]=h.pre.appendChild(g?fe("span"," "):me(a.display.measure))),h.pre.firstChild||Qc(a.doc,b)||h.pre.appendChild(document.createTextNode(" "));var j;if(c&&Ae&&(j=ud(f))){var k=j.length-1;j[k].from==j[k].to&&--k;var l=j[k],m=j[k-1];if(l.from+1==l.to&&m&&l.level<m.level){var n=c[h.pos-1];n&&n.parentNode.insertBefore(n.measureRight=me(a.display.measure),n.nextSibling)}}var o=h.textClass?h.textClass+" "+(b.textClass||""):b.textClass;return o&&(h.pre.className=o),Pd(a,"renderLine",a,b,h.pre),h}function dd(a,b,c,d,e,f){if(b){if(sf.test(b))for(var g=document.createDocumentFragment(),h=0;;){sf.lastIndex=h;var i=sf.exec(b),j=i?i.index-h:b.length-h;if(j&&(g.appendChild(document.createTextNode(b.slice(h,h+j))),a.col+=j),!i)break;if(h+=j+1," "==i[0]){var k=a.cm.options.tabSize,l=k-a.col%k;g.appendChild(fe("span",Xd(l),"cm-tab")),a.col+=l}else{var m=fe("span","•","cm-invalidchar");m.title="\\u"+i[0].charCodeAt(0).toString(16),g.appendChild(m),a.col+=1}}else{a.col+=b.length;var g=document.createTextNode(b)}if(c||d||e||a.measure){var n=c||"";d&&(n+=d),e&&(n+=e);var m=fe("span",[g],n);return f&&(m.title=f),a.pre.appendChild(m)}a.pre.appendChild(g)}}function ed(a,b,c,d,e){for(var f=a.cm.options.lineWrapping,g=0;g<b.length;++g){var h=b.charAt(g),i=0==g;h>="���"&&"���">h&&g<b.length-1?(h=b.slice(g,g+2),++g):g&&f&&ke(b,g)&&a.pre.appendChild(fe("wbr"));var j=a.measure[a.pos],k=a.measure[a.pos]=dd(a,h,c,i&&d,g==b.length-1&&e);j&&(k.leftSide=j.leftSide||j),Ae&&f&&" "==h&&g&&!/\s/.test(b.charAt(g-1))&&g<b.length-1&&!/\s/.test(b.charAt(g+1))&&(k.style.whiteSpace="normal"),a.pos+=h.length}b.length&&(a.measuredSomething=!0)}function fd(a){function b(a){for(var b=" ",c=0;c<a.length-2;++c)b+=c%2?" ":" ";return b+=" "}return function(c,d,e,f,g,h){return a(c,d.replace(/ {3,}/g,b),e,f,g,h)}}function gd(a,b,c,d){var e=!d&&c.replacedWith;if(e&&(a.copyWidgets&&(e=e.cloneNode(!0)),a.pre.appendChild(e),a.measure)){if(b)a.measure[a.pos]=e;else{var f=me(a.cm.display.measure);if("bookmark"!=c.type||c.insertLeft){if(a.measure[a.pos])return;a.measure[a.pos]=a.pre.insertBefore(f,e)}else a.measure[a.pos]=a.pre.appendChild(f)}a.measuredSomething=!0}a.pos+=b}function hd(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var g,h,i,j,k,l,m=e.length,n=0,o=1,p="",q=0;;){if(q==n){h=i=j=k="",l=null,q=1/0;for(var r=[],s=0;s<d.length;++s){var t=d[s],u=t.marker;t.from<=n&&(null==t.to||t.to>n)?(null!=t.to&&q>t.to&&(q=t.to,i=""),u.className&&(h+=" "+u.className),u.startStyle&&t.from==n&&(j+=" "+u.startStyle),u.endStyle&&t.to==q&&(i+=" "+u.endStyle),u.title&&!k&&(k=u.title),u.collapsed&&(!l||l.marker.size<u.size)&&(l=t)):t.from>n&&q>t.from&&(q=t.from),"bookmark"==u.type&&t.from==n&&u.replacedWith&&r.push(u)}if(l&&(l.from||0)==n&&(gd(b,(null==l.to?m:l.to)-n,l.marker,null==l.from),null==l.to))return l.marker.find();if(!l&&r.length)for(var s=0;s<r.length;++s)gd(b,0,r[s])}if(n>=m)break;for(var v=Math.min(m,q);;){if(p){var w=n+p.length;if(!l){var x=w>v?p.slice(0,v-n):p;b.addToken(b,x,g?g+h:h,j,n+x.length==q?i:"",k)
3
+ }if(w>=v){p=p.slice(v-n),n=v;break}n=w,j=""}p=e.slice(f,f=c[o++]),g=bd(c[o++],b)}}else for(var o=1;o<c.length;o+=2)b.addToken(b,e.slice(f,f=c[o]),bd(c[o+1],b))}function id(a,b,c,d,e){function f(a){return c?c[a]:null}function g(a,c,d){Xc(a,c,d,e),Qd(a,"change",a,b)}var h=b.from,i=b.to,j=b.text,k=nd(a,h.line),l=nd(a,i.line),m=Yd(j),n=f(j.length-1),o=i.line-h.line;if(0==h.ch&&0==i.ch&&""==m){for(var p=0,q=j.length-1,r=[];q>p;++p)r.push(new qf(j[p],f(p),e));g(l,l.text,n),o&&a.remove(h.line,o),r.length&&a.insert(h.line,r)}else if(k==l)if(1==j.length)g(k,k.text.slice(0,h.ch)+m+k.text.slice(i.ch),n);else{for(var r=[],p=1,q=j.length-1;q>p;++p)r.push(new qf(j[p],f(p),e));r.push(new qf(m+k.text.slice(i.ch),n,e)),g(k,k.text.slice(0,h.ch)+j[0],f(0)),a.insert(h.line+1,r)}else if(1==j.length)g(k,k.text.slice(0,h.ch)+j[0]+l.text.slice(i.ch),f(0)),a.remove(h.line+1,o);else{g(k,k.text.slice(0,h.ch)+j[0],f(0)),g(l,m+l.text.slice(i.ch),n);for(var p=1,q=j.length-1,r=[];q>p;++p)r.push(new qf(j[p],f(p),e));o>1&&a.remove(h.line+1,o-1),a.insert(h.line+1,r)}Qd(a,"change",a,b),dc(a,d.anchor,d.head,null,!0)}function jd(a){this.lines=a,this.parent=null;for(var b=0,c=a.length,d=0;c>b;++b)a[b].parent=this,d+=a[b].height;this.height=d}function kd(a){this.children=a;for(var b=0,c=0,d=0,e=a.length;e>d;++d){var f=a[d];b+=f.chunkSize(),c+=f.height,f.parent=this}this.size=b,this.height=c,this.parent=null}function ld(a,b,c){function d(a,e,f){if(a.linked)for(var g=0;g<a.linked.length;++g){var h=a.linked[g];if(h.doc!=e){var i=f&&h.sharedHist;(!c||i)&&(b(h.doc,i),d(h.doc,a,i))}}}d(a,null,!0)}function md(a,b){if(b.cm)throw new Error("This document is already in use.");a.doc=b,b.cm=a,f(a),c(a),a.options.lineWrapping||l(a),a.options.mode=b.modeOption,jb(a)}function nd(a,b){for(b-=a.first;!a.lines;)for(var c=0;;++c){var d=a.children[c],e=d.chunkSize();if(e>b){a=d;break}b-=e}return a.lines[b]}function od(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function pd(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function qd(a,b){for(var c=b-a.height,d=a;d;d=d.parent)d.height+=c}function rd(a){if(null==a.parent)return null;for(var b=a.parent,c=$d(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function sd(a,b){var c=a.first;a:do{for(var d=0,e=a.children.length;e>d;++d){var f=a.children[d],g=f.height;if(g>b){a=f;continue a}b-=g,c+=f.chunkSize()}return c}while(!a.lines);for(var d=0,e=a.lines.length;e>d;++d){var h=a.lines[d],i=h.height;if(i>b)break;b-=i}return c+d}function td(a,b){b=Pc(a.doc,b);for(var c=0,d=b.parent,e=0;e<d.lines.length;++e){var f=d.lines[e];if(f==b)break;c+=f.height}for(var g=d.parent;g;d=g,g=d.parent)for(var e=0;e<g.children.length;++e){var h=g.children[e];if(h==d)break;c+=h.height}return c}function ud(a){var b=a.order;return null==b&&(b=a.order=Mf(a.text)),b}function vd(a){return{done:[],undone:[],undoDepth:1/0,lastTime:0,lastOp:null,lastOrigin:null,generation:a||1,maxGeneration:a||1}}function wd(a,b,c,d){var e=b["spans_"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b["spans_"+a.id]={}))[f]=c.markedSpans),++f})}function xd(a,b){var c={line:b.from.line,ch:b.from.ch},d={from:c,to:df(b),text:od(a,b.from,b.to)};return wd(a,d,b.from.line,b.to.line+1),ld(a,function(a){wd(a,d,b.from.line,b.to.line+1)},!0),d}function yd(a,b,c,d){var e=a.history;e.undone.length=0;var f=+new Date,g=Yd(e.done);if(g&&(e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&("+"==b.origin.charAt(0)&&a.cm&&e.lastTime>f-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))){var h=Yd(g.changes);Wb(b.from,b.to)&&Wb(b.from,h.to)?h.to=df(b):g.changes.push(xd(a,b)),g.anchorAfter=c.anchor,g.headAfter=c.head}else for(g={changes:[xd(a,b)],generation:e.generation,anchorBefore:a.sel.anchor,headBefore:a.sel.head,anchorAfter:c.anchor,headAfter:c.head},e.done.push(g),e.generation=++e.maxGeneration;e.done.length>e.undoDepth;)e.done.shift();e.lastTime=f,e.lastOp=d,e.lastOrigin=b.origin}function zd(a){if(!a)return null;for(var b,c=0;c<a.length;++c)a[c].marker.explicitlyCleared?b||(b=a.slice(0,c)):b&&b.push(a[c]);return b?b.length?b:null:a}function Ad(a,b){var c=b["spans_"+a.id];if(!c)return null;for(var d=0,e=[];d<b.text.length;++d)e.push(zd(c[d]));return e}function Bd(a,b){for(var c=0,d=[];c<a.length;++c){var e=a[c],f=e.changes,g=[];d.push({changes:g,anchorBefore:e.anchorBefore,headBefore:e.headBefore,anchorAfter:e.anchorAfter,headAfter:e.headAfter});for(var h=0;h<f.length;++h){var i,j=f[h];if(g.push({from:j.from,to:j.to,text:j.text}),b)for(var k in j)(i=k.match(/^spans_(\d+)$/))&&$d(b,Number(i[1]))>-1&&(Yd(g)[k]=j[k],delete j[k])}}return d}function Cd(a,b,c,d){c<a.line?a.line+=d:b<a.line&&(a.line=b,a.ch=0)}function Dd(a,b,c,d){for(var e=0;e<a.length;++e){for(var f=a[e],g=!0,h=0;h<f.changes.length;++h){var i=f.changes[h];if(f.copied||(i.from=Yb(i.from),i.to=Yb(i.to)),c<i.from.line)i.from.line+=d,i.to.line+=d;else if(b<=i.to.line){g=!1;break}}f.copied||(f.anchorBefore=Yb(f.anchorBefore),f.headBefore=Yb(f.headBefore),f.anchorAfter=Yb(f.anchorAfter),f.readAfter=Yb(f.headAfter),f.copied=!0),g?(Cd(f.anchorBefore),Cd(f.headBefore),Cd(f.anchorAfter),Cd(f.headAfter)):(a.splice(0,e+1),e=0)}}function Ed(a,b){var c=b.from.line,d=b.to.line,e=b.text.length-(d-c)-1;Dd(a.done,c,d,e),Dd(a.undone,c,d,e)}function Fd(){Kd(this)}function Gd(a){return a.stop||(a.stop=Fd),a}function Hd(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function Id(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0}function Jd(a){return null!=a.defaultPrevented?a.defaultPrevented:0==a.returnValue}function Kd(a){Hd(a),Id(a)}function Ld(a){return a.target||a.srcElement}function Md(a){var b=a.which;return null==b&&(1&a.button?b=1:2&a.button?b=3:4&a.button&&(b=2)),Oe&&a.ctrlKey&&1==b&&(b=3),b}function Nd(a,b,c){if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var d=a._handlers||(a._handlers={}),e=d[b]||(d[b]=[]);e.push(c)}}function Od(a,b,c){if(a.removeEventListener)a.removeEventListener(b,c,!1);else if(a.detachEvent)a.detachEvent("on"+b,c);else{var d=a._handlers&&a._handlers[b];if(!d)return;for(var e=0;e<d.length;++e)if(d[e]==c){d.splice(e,1);break}}}function Pd(a,b){var c=a._handlers&&a._handlers[b];if(c)for(var d=Array.prototype.slice.call(arguments,2),e=0;e<c.length;++e)c[e].apply(null,d)}function Qd(a,b){function c(a){return function(){a.apply(null,e)}}var d=a._handlers&&a._handlers[b];if(d){var e=Array.prototype.slice.call(arguments,2);xf||(++yf,xf=[],setTimeout(Sd,0));for(var f=0;f<d.length;++f)xf.push(c(d[f]))}}function Rd(a,b,c){return Pd(a,c||b.type,a,b),Jd(b)||b.codemirrorIgnore}function Sd(){--yf;var a=xf;xf=null;for(var b=0;b<a.length;++b)a[b]()}function Td(a,b){var c=a._handlers&&a._handlers[b];return c&&c.length>0}function Ud(a){a.prototype.on=function(a,b){Nd(this,a,b)},a.prototype.off=function(a,b){Od(this,a,b)}}function Vd(){this.id=null}function Wd(a,b,c,d,e){null==b&&(b=a.search(/[^\s\u00a0]/),-1==b&&(b=a.length));for(var f=d||0,g=e||0;b>f;++f)" "==a.charAt(f)?g+=c-g%c:++g;return g}function Xd(a){for(;Bf.length<=a;)Bf.push(Yd(Bf)+" ");return Bf[a]}function Yd(a){return a[a.length-1]}function Zd(a){if(Me)a.selectionStart=0,a.selectionEnd=a.value.length;else try{a.select()}catch(b){}}function $d(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0,d=a.length;d>c;++c)if(a[c]==b)return c;return-1}function _d(a,b){function c(){}c.prototype=a;var d=new c;return b&&ae(b,d),d}function ae(a,b){b||(b={});for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function be(a){for(var b=[],c=0;a>c;++c)b.push(void 0);return b}function ce(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function de(a){return/\w/.test(a)||a>"€"&&(a.toUpperCase()!=a.toLowerCase()||Cf.test(a))}function ee(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function fe(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)ie(e,b);else if(b)for(var f=0;f<b.length;++f)e.appendChild(b[f]);return e}function ge(a){for(var b=a.childNodes.length;b>0;--b)a.removeChild(a.firstChild);return a}function he(a,b){return ge(a).appendChild(b)}function ie(a,b){Ce?(a.innerHTML="",a.appendChild(document.createTextNode(b))):a.textContent=b}function je(a){return a.getBoundingClientRect()}function ke(){return!1}function le(a){if(null!=Ff)return Ff;var b=fe("div",null,null,"width: 50px; height: 50px; overflow-x: scroll");return he(a,b),b.offsetWidth&&(Ff=b.offsetHeight-b.clientHeight),Ff||0}function me(a){if(null==Gf){var b=fe("span","​");he(a,fe("span",[b,document.createTextNode("x")])),0!=a.firstChild.offsetHeight&&(Gf=b.offsetWidth<=1&&b.offsetHeight>2&&!Be)}return Gf?fe("span","​"):fe("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px")}function ne(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;f<a.length;++f){var g=a[f];(g.from<c&&g.to>b||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function oe(a){return a.level%2?a.to:a.from}function pe(a){return a.level%2?a.from:a.to}function qe(a){var b=ud(a);return b?oe(b[0]):0}function re(a){var b=ud(a);return b?pe(Yd(b)):a.text.length}function se(a,b){var c=nd(a.doc,b),d=Pc(a.doc,c);d!=c&&(b=rd(d));var e=ud(d),f=e?e[0].level%2?re(d):qe(d):0;return Vb(b,f)}function te(a,b){for(var c,d;c=Oc(d=nd(a.doc,b));)b=c.find().to.line;var e=ud(d),f=e?e[0].level%2?qe(d):re(d):d.text.length;return Vb(b,f)}function ue(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function ve(a,b){for(var c,d=0;d<a.length;++d){var e=a[d];if(e.from<b&&e.to>b)return Lf=null,d;if(e.from==b||e.to==b){if(null!=c)return ue(a,e.level,a[c].level)?(Lf=c,d):(Lf=d,c);c=d}}return Lf=null,c}function we(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&Df.test(a.text.charAt(b)));return b}function xe(a,b,c,d){var e=ud(a);if(!e)return ye(a,b,c,d);for(var f=ve(e,b),g=e[f],h=we(a,b,g.level%2?-c:c,d);;){if(h>g.from&&h<g.to)return h;if(h==g.from||h==g.to)return ve(e,h)==f?h:(g=e[f+=c],c>0==g.level%2?g.to:g.from);if(g=e[f+=c],!g)return null;h=c>0==g.level%2?we(a,g.to,-1,d):we(a,g.from,1,d)}}function ye(a,b,c,d){var e=b+c;if(d)for(;e>0&&Df.test(a.text.charAt(e));)e+=c;return 0>e||e>a.text.length?null:e}var ze=/gecko\/\d/i.test(navigator.userAgent),Ae=/MSIE \d/.test(navigator.userAgent),Be=Ae&&(null==document.documentMode||document.documentMode<8),Ce=Ae&&(null==document.documentMode||document.documentMode<9),De=/WebKit\//.test(navigator.userAgent),Ee=De&&/Qt\/\d+\.\d+/.test(navigator.userAgent),Fe=/Chrome\//.test(navigator.userAgent),Ge=/Opera\//.test(navigator.userAgent),He=/Apple Computer/.test(navigator.vendor),Ie=/KHTML\//.test(navigator.userAgent),Je=/Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent),Ke=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent),Le=/PhantomJS/.test(navigator.userAgent),Me=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent),Ne=Me||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),Oe=Me||/Mac/.test(navigator.platform),Pe=/win/i.test(navigator.platform),Qe=Ge&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);Qe&&(Qe=Number(Qe[1])),Qe&&Qe>=15&&(Ge=!1,De=!0);var Re,Se,Te,Ue=Oe&&(Ee||Ge&&(null==Qe||12.11>Qe)),Ve=ze||Ae&&!Ce,We=!1,Xe=!1,Ye=0,Ze=0,$e=0,_e=null;Ae?_e=-.53:ze?_e=15:Fe?_e=-.7:He&&(_e=-1/3);var af,bf,cf=null,df=a.changeEnd=function(a){return a.text?Vb(a.from.line+a.text.length-1,Yd(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};a.Pos=Vb,a.prototype={constructor:a,focus:function(){window.focus(),ob(this),Ib(this),lb(this)},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||"mode"==a)&&(c[a]=b,ef.hasOwnProperty(a)&&gb(this,ef[a])(this,b,d))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?"push":"unshift"](a)},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;c<b.length;++c)if(b[c]==a||"string"!=typeof b[c]&&b[c].name==a)return b.splice(c,1),!0},addOverlay:gb(null,function(b,c){var d=b.token?b:a.getMode(this.options,b);if(d.startState)throw new Error("Overlays may not be stateful.");this.state.overlays.push({mode:d,modeSpec:b,opaque:c&&c.opaque}),this.state.modeGen++,jb(this)}),removeOverlay:gb(null,function(a){for(var b=this.state.overlays,c=0;c<b.length;++c){var d=b[c].modeSpec;if(d==a||"string"==typeof a&&d.name==a)return b.splice(c,1),this.state.modeGen++,jb(this),void 0}}),indentLine:gb(null,function(a,b,c){"string"!=typeof b&&"number"!=typeof b&&(b=null==b?this.options.smartIndent?"smart":"prev":b?"add":"subtract"),ac(this.doc,a)&&mc(this,a,b,c)}),indentSelection:gb(null,function(a){var b=this.doc.sel;if(Wb(b.from,b.to))return mc(this,b.from.line,a);for(var c=b.to.line-(b.to.ch?0:1),d=b.from.line;c>=d;++d)mc(this,d,a)}),getTokenAt:function(a,b){var c=this.doc;a=$b(c,a);for(var d=J(this,a.line,b),e=this.doc.mode,f=nd(c,a.line),g=new zc(f.text,this.options.tabSize);g.pos<a.ch&&!g.eol();){g.start=g.pos;var h=e.token(g,d)}return{start:g.start,end:g.pos,string:g.current(),className:h||null,type:h||null,state:d}},getTokenTypeAt:function(a){a=$b(this.doc,a);var b=_c(this,nd(this.doc,a.line)),c=0,d=(b.length-1)/2,e=a.ch;if(0==e)return b[2];for(;;){var f=c+d>>1;if((f?b[2*f-1]:0)>=e)d=f;else{if(!(b[2*f+1]<e))return b[2*f+2];c=f+1}}},getModeAt:function(b){var c=this.doc.mode;return c.innerMode?a.innerMode(c,this.getTokenAt(b).state).mode:c},getHelper:function(a,b){if(mf.hasOwnProperty(b)){var c=mf[b],d=this.getModeAt(a);return d[b]&&c[d[b]]||d.helperType&&c[d.helperType]||c[d.name]}},getStateAfter:function(a,b){var c=this.doc;return a=Zb(c,null==a?c.first+c.size-1:a),J(this,a+1,b)},cursorCoords:function(a,b){var c,d=this.doc.sel;return c=null==a?d.head:"object"==typeof a?$b(this.doc,a):a?d.from:d.to,$(this,c,b||"page")},charCoords:function(a,b){return Z(this,$b(this.doc,a),b||"page")},coordsChar:function(a,b){return a=Y(this,a,b||"page"),ab(this,a.left,a.top)},lineAtHeight:function(a,b){return a=Y(this,{top:a,left:0},b||"page").top,sd(this.doc,a+this.display.viewOffset)},heightAtLine:function(a,b){var c=!1,d=this.doc.first+this.doc.size-1;a<this.doc.first?a=this.doc.first:a>d&&(a=d,c=!0);var e=nd(this.doc,a);return X(this,nd(this.doc,a),{top:0,left:0},b||"page").top+(c?e.height:0)},defaultTextHeight:function(){return cb(this.display)},defaultCharWidth:function(){return db(this.display)},setGutterMarker:gb(null,function(a,b,c){return nc(this,a,function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&ee(d)&&(a.gutterMarkers=null),!0})}),clearGutter:gb(null,function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,jb(b,d,d+1),ee(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),addLineClass:gb(null,function(a,b,c){return nc(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass";if(a[d]){if(new RegExp("(?:^|\\s)"+c+"(?:$|\\s)").test(a[d]))return!1;a[d]+=" "+c}else a[d]=c;return!0})}),removeLineClass:gb(null,function(a,b,c){return nc(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass",e=a[d];if(!e)return!1;if(null==c)a[d]=null;else{var f=e.match(new RegExp("(?:^|\\s+)"+c+"(?:$|\\s+)"));if(!f)return!1;var g=f.index+f[0].length;a[d]=e.slice(0,f.index)+(f.index&&g!=e.length?" ":"")+e.slice(g)||null}return!0})}),addLineWidget:gb(null,function(a,b,c){return Wc(this,a,b,c)}),removeLineWidget:function(a){a.clear()},lineInfo:function(a){if("number"==typeof a){if(!ac(this.doc,a))return null;var b=a;if(a=nd(this.doc,a),!a)return null}else{var b=rd(a);if(null==b)return null}return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},getViewport:function(){return{from:this.display.showingFrom,to:this.display.showingTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=$(this,$b(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position="absolute",f.sizer.appendChild(b),"over"==d)g=a.top;else if("above"==d||"near"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);("above"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+"px",b.style.left=b.style.right="","right"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.style.right="0px"):("left"==e?h=0:"middle"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+"px"),c&&ic(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:gb(null,Gb),execCommand:function(a){return nf[a](this)},findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=$b(this.doc,a);b>f&&(g=oc(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:gb(null,function(a,b){var c,d=this.doc.sel;c=d.shift||d.extend||Wb(d.from,d.to)?oc(this.doc,d.head,a,b,this.options.rtlMoveVisually):0>a?d.from:d.to,bc(this.doc,c,c,a)}),deleteH:gb(null,function(a,b){var c=this.doc.sel;Wb(c.from,c.to)?Ub(this.doc,"",c.from,oc(this.doc,c.head,a,b,!1),"+delete"):Ub(this.doc,"",c.from,c.to,"+delete"),this.curOp.userSelChange=!0}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=$b(this.doc,a);b>g;++g){var i=$(this,h,"div");if(null==f?f=i.left:i.left=f,h=pc(this,i,e,c),h.hitSide)break}return h},moveV:gb(null,function(a,b){var c=this.doc.sel,d=$(this,c.head,"div");null!=c.goalColumn&&(d.left=c.goalColumn);var e=pc(this,d,a,b);"page"==b&&lc(this,0,Z(this,e,"div").top-d.top),bc(this.doc,e,e,a),c.goalColumn=d.left}),toggleOverwrite:function(a){(null==a||a!=this.state.overwrite)&&((this.state.overwrite=!this.state.overwrite)?this.display.cursor.className+=" CodeMirror-overwrite":this.display.cursor.className=this.display.cursor.className.replace(" CodeMirror-overwrite",""))},hasFocus:function(){return this.state.focused},scrollTo:gb(null,function(a,b){kc(this,a,b)}),getScrollInfo:function(){var a=this.display.scroller,b=zf;return{left:a.scrollLeft,top:a.scrollTop,height:a.scrollHeight-b,width:a.scrollWidth-b,clientHeight:a.clientHeight-b,clientWidth:a.clientWidth-b}},scrollIntoView:gb(null,function(a,b){null==a?a={from:this.doc.sel.head,to:null}:"number"==typeof a?a={from:Vb(a,0),to:null}:null==a.from&&(a={from:a,to:null}),a.to||(a.to=a.from),b||(b=0);var c=a;null!=a.from.line&&(this.curOp.scrollToPos={from:a.from,to:a.to,margin:b},c={from:$(this,a.from),to:$(this,a.to)});var d=jc(this,Math.min(c.from.left,c.to.left),Math.min(c.from.top,c.to.top)-b,Math.max(c.from.right,c.to.right),Math.max(c.from.bottom,c.to.bottom)+b);kc(this,d.scrollLeft,d.scrollTop)}),setSize:gb(null,function(a,b){function c(a){return"number"==typeof a||/^\d+$/.test(String(a))?a+"px":a}null!=a&&(this.display.wrapper.style.width=c(a)),null!=b&&(this.display.wrapper.style.height=c(b)),this.options.lineWrapping&&(this.display.measureLineCache.length=this.display.measureLineCachePos=0),this.curOp.forceUpdate=!0}),operation:function(a){return ib(this,a)},refresh:gb(null,function(){var a=null==this.display.cachedTextHeight;U(this),kc(this,this.doc.scrollLeft,this.doc.scrollTop),jb(this),a&&f(this)}),swapDoc:gb(null,function(a){var b=this.doc;return b.cm=null,md(this,a),U(this),nb(this,!0),kc(this,a.scrollLeft,a.scrollTop),Qd(this,"swapDoc",this,b),b}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Ud(a);var ef=a.optionHandlers={},ff=a.defaults={},gf=a.Init={toString:function(){return"CodeMirror.Init"}};sc("value","",function(a,b){a.setValue(b)},!0),sc("mode",null,function(a,b){a.doc.modeOption=b,c(a)},!0),sc("indentUnit",2,c,!0),sc("indentWithTabs",!1),sc("smartIndent",!0),sc("tabSize",4,function(a){c(a),U(a),jb(a)},!0),sc("electricChars",!0),sc("rtlMoveVisually",!Pe),sc("theme","default",function(a){h(a),i(a)},!0),sc("keyMap","default",g),sc("extraKeys",null),sc("onKeyEvent",null),sc("onDragEvent",null),sc("lineWrapping",!1,d,!0),sc("gutters",[],function(a){m(a.options),i(a)},!0),sc("fixedGutter",!0,function(a,b){a.display.gutters.style.left=b?s(a.display)+"px":"0",a.refresh()},!0),sc("coverGutterNextToScrollbar",!1,n,!0),sc("lineNumbers",!1,function(a){m(a.options),i(a)},!0),sc("firstLineNumber",1,i,!0),sc("lineNumberFormatter",function(a){return a},i,!0),sc("showCursorWhenSelecting",!1,C,!0),sc("resetSelectionOnContextMenu",!0),sc("readOnly",!1,function(a,b){"nocursor"==b?(Jb(a),a.display.input.blur()):b||nb(a,!0)}),sc("dragDrop",!0),sc("cursorBlinkRate",530),sc("cursorScrollMargin",0),sc("cursorHeight",1),sc("workTime",100),sc("workDelay",100),sc("flattenSpans",!0),sc("pollInterval",100),sc("undoDepth",40,function(a,b){a.doc.history.undoDepth=b}),sc("historyEventDelay",500),sc("viewportMargin",10,function(a){a.refresh()},!0),sc("maxHighlightLength",1e4,function(a){c(a),a.refresh()},!0),sc("crudeMeasuringFrom",1e4),sc("moveInputWithCursor",!0,function(a,b){b||(a.display.inputDiv.style.top=a.display.inputDiv.style.left=0)}),sc("tabindex",null,function(a,b){a.display.input.tabIndex=b||""}),sc("autofocus",null);var hf=a.modes={},jf=a.mimeModes={};a.defineMode=function(b,c){if(a.defaults.mode||"null"==b||(a.defaults.mode=b),arguments.length>2){c.dependencies=[];for(var d=2;d<arguments.length;++d)c.dependencies.push(arguments[d])}hf[b]=c},a.defineMIME=function(a,b){jf[a]=b},a.resolveMode=function(b){if("string"==typeof b&&jf.hasOwnProperty(b))b=jf[b];else if(b&&"string"==typeof b.name&&jf.hasOwnProperty(b.name)){var c=jf[b.name];b=_d(c,b),b.name=c.name}else if("string"==typeof b&&/^[\w\-]+\/[\w\-]+\+xml$/.test(b))return a.resolveMode("application/xml");return"string"==typeof b?{name:b}:b||{name:"null"}},a.getMode=function(b,c){var c=a.resolveMode(c),d=hf[c.name];if(!d)return a.getMode(b,"text/plain");var e=d(b,c);if(kf.hasOwnProperty(c.name)){var f=kf[c.name];for(var g in f)f.hasOwnProperty(g)&&(e.hasOwnProperty(g)&&(e["_"+g]=e[g]),e[g]=f[g])}return e.name=c.name,e},a.defineMode("null",function(){return{token:function(a){a.skipToEnd()}}}),a.defineMIME("text/plain","null");var kf=a.modeExtensions={};a.extendMode=function(a,b){var c=kf.hasOwnProperty(a)?kf[a]:kf[a]={};ae(b,c)},a.defineExtension=function(b,c){a.prototype[b]=c},a.defineDocExtension=function(a,b){uf.prototype[a]=b},a.defineOption=sc;var lf=[];a.defineInitHook=function(a){lf.push(a)};var mf=a.helpers={};a.registerHelper=function(b,c,d){mf.hasOwnProperty(b)||(mf[b]=a[b]={}),mf[b][c]=d},a.isWordChar=de,a.copyState=tc,a.startState=uc,a.innerMode=function(a,b){for(;a.innerMode;){var c=a.innerMode(b);if(!c||c.mode==a)break;b=c.state,a=c.mode}return c||{mode:a,state:b}};var nf=a.commands={selectAll:function(a){a.setSelection(Vb(a.firstLine(),0),Vb(a.lastLine()))},killLine:function(a){var b=a.getCursor(!0),c=a.getCursor(!1),d=!Wb(b,c);d||a.getLine(b.line).length!=b.ch?a.replaceRange("",b,d?c:Vb(b.line),"+delete"):a.replaceRange("",b,Vb(b.line+1,0),"+delete")},deleteLine:function(a){var b=a.getCursor().line;a.replaceRange("",Vb(b,0),Vb(b),"+delete")},delLineLeft:function(a){var b=a.getCursor();a.replaceRange("",Vb(b.line,0),b,"+delete")},undo:function(a){a.undo()},redo:function(a){a.redo()},goDocStart:function(a){a.extendSelection(Vb(a.firstLine(),0))},goDocEnd:function(a){a.extendSelection(Vb(a.lastLine()))},goLineStart:function(a){a.extendSelection(se(a,a.getCursor().line))},goLineStartSmart:function(a){var b=a.getCursor(),c=se(a,b.line),d=a.getLineHandle(c.line),e=ud(d);if(e&&0!=e[0].level)a.extendSelection(c);else{var f=Math.max(0,d.text.search(/\S/)),g=b.line==c.line&&b.ch<=f&&b.ch;a.extendSelection(Vb(c.line,g?0:f))}},goLineEnd:function(a){a.extendSelection(te(a,a.getCursor().line))},goLineRight:function(a){var b=a.charCoords(a.getCursor(),"div").top+5;a.extendSelection(a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:b},"div"))},goLineLeft:function(a){var b=a.charCoords(a.getCursor(),"div").top+5;a.extendSelection(a.coordsChar({left:0,top:b},"div"))},goLineUp:function(a){a.moveV(-1,"line")},goLineDown:function(a){a.moveV(1,"line")},goPageUp:function(a){a.moveV(-1,"page")},goPageDown:function(a){a.moveV(1,"page")},goCharLeft:function(a){a.moveH(-1,"char")},goCharRight:function(a){a.moveH(1,"char")},goColumnLeft:function(a){a.moveH(-1,"column")},goColumnRight:function(a){a.moveH(1,"column")},goWordLeft:function(a){a.moveH(-1,"word")},goGroupRight:function(a){a.moveH(1,"group")},goGroupLeft:function(a){a.moveH(-1,"group")},goWordRight:function(a){a.moveH(1,"word")},delCharBefore:function(a){a.deleteH(-1,"char")},delCharAfter:function(a){a.deleteH(1,"char")},delWordBefore:function(a){a.deleteH(-1,"word")},delWordAfter:function(a){a.deleteH(1,"word")},delGroupBefore:function(a){a.deleteH(-1,"group")},delGroupAfter:function(a){a.deleteH(1,"group")},indentAuto:function(a){a.indentSelection("smart")},indentMore:function(a){a.indentSelection("add")},indentLess:function(a){a.indentSelection("subtract")},insertTab:function(a){a.replaceSelection(" ","end","+input")},defaultTab:function(a){a.somethingSelected()?a.indentSelection("add"):a.replaceSelection(" ","end","+input")},transposeChars:function(a){var b=a.getCursor(),c=a.getLine(b.line);b.ch>0&&b.ch<c.length-1&&a.replaceRange(c.charAt(b.ch)+c.charAt(b.ch-1),Vb(b.line,b.ch-1),Vb(b.line,b.ch+1))},newlineAndIndent:function(a){gb(a,function(){a.replaceSelection("\n","end","+input"),a.indentLine(a.getCursor().line,null,!0)})()},toggleOverwrite:function(a){a.toggleOverwrite()}},of=a.keyMap={};of.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"},of.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Alt-Up":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Down":"goDocEnd","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore",fallthrough:"basic"},of.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineStart","Cmd-Right":"goLineEnd","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":"delLineLeft",fallthrough:["basic","emacsy"]},of["default"]=Oe?of.macDefault:of.pcDefault,of.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"},a.lookupKey=wc,a.isModifierKey=xc,a.keyName=yc,a.fromTextArea=function(b,c){function d(){b.value=j.getValue()}if(c||(c={}),c.value=b.value,!c.tabindex&&b.tabindex&&(c.tabindex=b.tabindex),!c.placeholder&&b.placeholder&&(c.placeholder=b.placeholder),null==c.autofocus){var e=document.body;try{e=document.activeElement}catch(f){}c.autofocus=e==b||null!=b.getAttribute("autofocus")&&e==document.body}if(b.form&&(Nd(b.form,"submit",d),!c.leaveSubmitMethodAlone)){var g=b.form,h=g.submit;try{var i=g.submit=function(){d(),g.submit=h,g.submit(),g.submit=i}}catch(f){}}b.style.display="none";var j=a(function(a){b.parentNode.insertBefore(a,b.nextSibling)},c);return j.save=d,j.getTextArea=function(){return b},j.toTextArea=function(){d(),b.parentNode.removeChild(j.getWrapperElement()),b.style.display="",b.form&&(Od(b.form,"submit",d),"function"==typeof b.form.submit&&(b.form.submit=h))},j},zc.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return 0==this.pos},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.pos<this.string.length?this.string.charAt(this.pos++):void 0},eat:function(a){var b=this.string.charAt(this.pos);if("string"==typeof a)var c=b==a;else var c=b&&(a.test?a.test(b):a(b));return c?(++this.pos,b):void 0},eatWhile:function(a){for(var b=this.pos;this.eat(a););return this.pos>b},eatSpace:function(){for(var a=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);return b>-1?(this.pos=b,!0):void 0},backUp:function(a){this.pos-=a},column:function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=Wd(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue},indentation:function(){return Wd(this.string,null,this.tabSize)},match:function(a,b,c){if("string"!=typeof a){var d=this.string.slice(this.pos).match(a);return d&&d.index>0?null:(d&&b!==!1&&(this.pos+=d[0].length),d)}var e=function(a){return c?a.toLowerCase():a},f=this.string.substr(this.pos,a.length);return e(f)==e(a)?(b!==!1&&(this.pos+=a.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)}},a.StringStream=zc,a.TextMarker=Ac,Ud(Ac),Ac.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&eb(a),Td(this,"clear")){var c=this.find();c&&Qd(this,"clear",c.from,c.to)}for(var d=null,e=null,f=0;f<this.lines.length;++f){var g=this.lines[f],h=Ec(g.markedSpans,this);null!=h.to&&(e=rd(g)),g.markedSpans=Fc(g.markedSpans,h),null!=h.from?d=rd(g):this.collapsed&&!Qc(this.doc,g)&&a&&qd(g,cb(a.display))}if(a&&this.collapsed&&!a.options.lineWrapping)for(var f=0;f<this.lines.length;++f){var i=Pc(a.doc,this.lines[f]),j=k(a.doc,i);j>a.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&jb(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&ec(a)),b&&fb(a)}},Ac.prototype.find=function(){for(var a,b,c=0;c<this.lines.length;++c){var d=this.lines[c],e=Ec(d.markedSpans,this);if(null!=e.from||null!=e.to){var f=rd(d);null!=e.from&&(a=Vb(f,e.from)),null!=e.to&&(b=Vb(f,e.to))}}return"bookmark"==this.type?a:a&&{from:a,to:b}},Ac.prototype.changed=function(){var a=this.find(),b=this.doc.cm;if(a&&b){"bookmark"!=this.type&&(a=a.from);var c=nd(this.doc,a.line);if(P(b,c),a.line>=b.display.showingFrom&&a.line<b.display.showingTo){for(var d=b.display.lineDiv.firstChild;d;d=d.nextSibling)if(d.lineObj==c){d.offsetHeight!=c.height&&qd(c,d.offsetHeight);break}ib(b,function(){b.curOp.selectionChanged=b.curOp.forceUpdate=b.curOp.updateMaxLine=!0})}}},Ac.prototype.attachLine=function(a){if(!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;b.maybeHiddenMarkers&&-1!=$d(b.maybeHiddenMarkers,this)||(b.maybeUnhiddenMarkers||(b.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(a)},Ac.prototype.detachLine=function(a){if(this.lines.splice($d(this.lines,a),1),!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;(b.maybeHiddenMarkers||(b.maybeHiddenMarkers=[])).push(this)}},a.SharedTextMarker=Cc,Ud(Cc),Cc.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;
4
+ for(var a=0;a<this.markers.length;++a)this.markers[a].clear();Qd(this,"clear")}},Cc.prototype.find=function(){return this.primary.find()};var pf=a.LineWidget=function(a,b,c){if(c)for(var d in c)c.hasOwnProperty(d)&&(this[d]=c[d]);this.cm=a,this.node=b};Ud(pf),pf.prototype.clear=Uc(function(){var a=this.line.widgets,b=rd(this.line);if(null!=b&&a){for(var c=0;c<a.length;++c)a[c]==this&&a.splice(c--,1);a.length||(this.line.widgets=null);var d=td(this.cm,this.line)<this.cm.doc.scrollTop;qd(this.line,Math.max(0,this.line.height-Vc(this))),d&&lc(this.cm,0,-this.height),jb(this.cm,b,b+1)}}),pf.prototype.changed=Uc(function(){var a=this.height;this.height=null;var b=Vc(this)-a;if(b){qd(this.line,this.line.height+b);var c=rd(this.line);jb(this.cm,c,c+1)}});var qf=a.Line=function(a,b,c){this.text=a,Tc(this,b),this.height=c?c(this):1};Ud(qf);var rf={},sf=/[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;jd.prototype={chunkSize:function(){return this.lines.length},removeInner:function(a,b){for(var c=a,d=a+b;d>c;++c){var e=this.lines[c];this.height-=e.height,Yc(e),Qd(e,"delete")}this.lines.splice(a,b)},collapse:function(a){a.splice.apply(a,[a.length,0].concat(this.lines))},insertInner:function(a,b,c){this.height+=c,this.lines=this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var d=0,e=b.length;e>d;++d)b[d].parent=this},iterN:function(a,b,c){for(var d=a+b;d>a;++a)if(c(this.lines[a]))return!0}},kd.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){this.size-=b;for(var c=0;c<this.children.length;++c){var d=this.children[c],e=d.chunkSize();if(e>a){var f=Math.min(b,e-a),g=d.height;if(d.removeInner(a,f),this.height-=g-d.height,e==f&&(this.children.splice(c--,1),d.parent=null),0==(b-=f))break;a=0}else a-=e}if(this.size-b<25){var h=[];this.collapse(h),this.children=[new jd(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0,c=this.children.length;c>b;++b)this.children[b].collapse(a)},insertInner:function(a,b,c){this.size+=b.length,this.height+=c;for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>=a){if(f.insertInner(a,b,c),f.lines&&f.lines.length>50){for(;f.lines.length>50;){var h=f.lines.splice(f.lines.length-25,25),i=new jd(h);f.height-=i.height,this.children.splice(d+1,0,i),i.parent=this}this.maybeSpill()}break}a-=g}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new kd(b);if(a.parent){a.size-=c.size,a.height-=c.height;var d=$d(a.parent.children,a);a.parent.children.splice(d+1,0,c)}else{var e=new kd(a.children);e.parent=a,a.children=[e,c],a=e}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>a){var h=Math.min(b,g-a);if(f.iterN(a,h,c))return!0;if(0==(b-=h))break;a=0}else a-=g}}};var tf=0,uf=a.Doc=function(a,b,c){if(!(this instanceof uf))return new uf(a,b,c);null==c&&(c=0),kd.call(this,[new jd([new qf("",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.history=vd(),this.cleanGeneration=1,this.frontier=c;var d=Vb(c,0);this.sel={from:d,to:d,head:d,anchor:d,shift:!1,extend:!1,goalColumn:null},this.id=++tf,this.modeOption=b,"string"==typeof a&&(a=Hf(a)),id(this,{from:d,to:d,text:a},null,{head:d,anchor:d})};uf.prototype=_d(kd.prototype,{constructor:uf,iter:function(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0,e=b.length;e>d;++d)c+=b[d].height;this.insertInner(a-this.first,b,c)},remove:function(a,b){this.removeInner(a-this.first,b)},getValue:function(a){var b=pd(this,this.first,this.first+this.size);return a===!1?b:b.join(a||"\n")},setValue:function(a){var b=Vb(this.first,0),c=this.first+this.size-1;Ob(this,{from:b,to:Vb(c,nd(this,c).text.length),text:Hf(a),origin:"setValue"},{head:b,anchor:b},!0)},replaceRange:function(a,b,c,d){b=$b(this,b),c=c?$b(this,c):b,Ub(this,a,b,c,d)},getRange:function(a,b,c){var d=od(this,$b(this,a),$b(this,b));return c===!1?d:d.join(c||"\n")},getLine:function(a){var b=this.getLineHandle(a);return b&&b.text},setLine:function(a,b){ac(this,a)&&Ub(this,b,Vb(a,0),$b(this,Vb(a)))},removeLine:function(a){a?Ub(this,"",$b(this,Vb(a-1)),$b(this,Vb(a))):Ub(this,"",Vb(0,0),$b(this,Vb(1,0)))},getLineHandle:function(a){return ac(this,a)?nd(this,a):void 0},getLineNumber:function(a){return rd(a)},getLineHandleVisualStart:function(a){return"number"==typeof a&&(a=nd(this,a)),Pc(this,a)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(a){return $b(this,a)},getCursor:function(a){var b,c=this.sel;return b=null==a||"head"==a?c.head:"anchor"==a?c.anchor:"end"==a||a===!1?c.to:c.from,Yb(b)},somethingSelected:function(){return!Wb(this.sel.head,this.sel.anchor)},setCursor:hb(function(a,b,c){var d=$b(this,"number"==typeof a?Vb(a,b||0):a);c?bc(this,d):dc(this,d,d)}),setSelection:hb(function(a,b,c){dc(this,$b(this,a),$b(this,b||a),c)}),extendSelection:hb(function(a,b,c){bc(this,$b(this,a),b&&$b(this,b),c)}),getSelection:function(a){return this.getRange(this.sel.from,this.sel.to,a)},replaceSelection:function(a,b,c){Ob(this,{from:this.sel.from,to:this.sel.to,text:Hf(a),origin:c},b||"around")},undo:hb(function(){Qb(this,"undo")}),redo:hb(function(){Qb(this,"redo")}),setExtending:function(a){this.sel.extend=a},historySize:function(){var a=this.history;return{undo:a.done.length,redo:a.undone.length}},clearHistory:function(){this.history=vd(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration()},changeGeneration:function(){return this.history.lastOp=this.history.lastOrigin=null,this.history.generation},isClean:function(a){return this.history.generation==(a||this.cleanGeneration)},getHistory:function(){return{done:Bd(this.history.done),undone:Bd(this.history.undone)}},setHistory:function(a){var b=this.history=vd(this.history.maxGeneration);b.done=a.done.slice(0),b.undone=a.undone.slice(0)},markText:function(a,b,c){return Bc(this,$b(this,a),$b(this,b),c,"range")},setBookmark:function(a,b){var c={replacedWith:b&&(null==b.nodeType?b.widget:b),insertLeft:b&&b.insertLeft};return a=$b(this,a),Bc(this,a,a,c,"bookmark")},findMarksAt:function(a){a=$b(this,a);var b=[],c=nd(this,a.line).markedSpans;if(c)for(var d=0;d<c.length;++d){var e=c[d];(null==e.from||e.from<=a.ch)&&(null==e.to||e.to>=a.ch)&&b.push(e.marker.parent||e.marker)}return b},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.markedSpans;if(c)for(var d=0;d<c.length;++d)null!=c[d].from&&a.push(c[d].marker)}),a},posFromIndex:function(a){var b,c=this.first;return this.iter(function(d){var e=d.text.length+1;return e>a?(b=a,!0):(a-=e,++c,void 0)}),$b(this,Vb(c,b))},indexFromPos:function(a){a=$b(this,a);var b=a.ch;return a.line<this.first||a.ch<0?0:(this.iter(this.first,a.line,function(a){b+=a.text.length+1}),b)},copy:function(a){var b=new uf(pd(this,this.first,this.first+this.size),this.modeOption,this.first);return b.scrollTop=this.scrollTop,b.scrollLeft=this.scrollLeft,b.sel={from:this.sel.from,to:this.sel.to,head:this.sel.head,anchor:this.sel.anchor,shift:this.sel.shift,extend:!1,goalColumn:this.sel.goalColumn},a&&(b.history.undoDepth=this.history.undoDepth,b.setHistory(this.getHistory())),b},linkedDoc:function(a){a||(a={});var b=this.first,c=this.first+this.size;null!=a.from&&a.from>b&&(b=a.from),null!=a.to&&a.to<c&&(c=a.to);var d=new uf(pd(this,b,c),a.mode||this.modeOption,b);return a.sharedHist&&(d.history=this.history),(this.linked||(this.linked=[])).push({doc:d,sharedHist:a.sharedHist}),d.linked=[{doc:this,isParent:!0,sharedHist:a.sharedHist}],d},unlinkDoc:function(b){if(b instanceof a&&(b=b.doc),this.linked)for(var c=0;c<this.linked.length;++c){var d=this.linked[c];if(d.doc==b){this.linked.splice(c,1),b.unlinkDoc(this);break}}if(b.history==this.history){var e=[b.id];ld(b,function(a){e.push(a.id)},!0),b.history=vd(),b.history.done=Bd(this.history.done,e),b.history.undone=Bd(this.history.undone,e)}},iterLinkedDocs:function(a){ld(this,a)},getMode:function(){return this.mode},getEditor:function(){return this.cm}}),uf.prototype.eachLine=uf.prototype.iter;var vf="iter insert remove copy getEditor".split(" ");for(var wf in uf.prototype)uf.prototype.hasOwnProperty(wf)&&$d(vf,wf)<0&&(a.prototype[wf]=function(a){return function(){return a.apply(this.doc,arguments)}}(uf.prototype[wf]));Ud(uf),a.e_stop=Kd,a.e_preventDefault=Hd,a.e_stopPropagation=Id;var xf,yf=0;a.on=Nd,a.off=Od,a.signal=Pd;var zf=30,Af=a.Pass={toString:function(){return"CodeMirror.Pass"}};Vd.prototype={set:function(a,b){clearTimeout(this.id),this.id=setTimeout(b,a)}},a.countColumn=Wd;var Bf=[""],Cf=/[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,Df=/[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;a.replaceGetRect=function(a){je=a};var Ef=function(){if(Ce)return!1;var a=fe("div");return"draggable"in a||"dragDrop"in a}();ze?ke=function(a,b){return 36==a.charCodeAt(b-1)&&39==a.charCodeAt(b)}:He&&!/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)?ke=function(a,b){return/\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(a.slice(b-1,b+1))}:De&&/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent)?ke=function(a,b){var c=a.charCodeAt(b-1);return c>=8208&&8212>=c}:De&&(ke=function(a,b){if(b>1&&45==a.charCodeAt(b-1)){if(/\w/.test(a.charAt(b-2))&&/[^\-?\.]/.test(a.charAt(b)))return!0;if(b>2&&/[\d\.,]/.test(a.charAt(b-2))&&/[\d\.,]/.test(a.charAt(b)))return!1}return/[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(a.slice(b-1,b+1))});var Ff,Gf,Hf=3!="\n\nb".split(/\n/).length?function(a){for(var b=0,c=[],d=a.length;d>=b;){var e=a.indexOf("\n",b);-1==e&&(e=a.length);var f=a.slice(b,"\r"==a.charAt(e-1)?e-1:e),g=f.indexOf("\r");-1!=g?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\r\n?|\n/)};a.splitLines=Hf;var If=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){try{var b=a.ownerDocument.selection.createRange()}catch(c){}return b&&b.parentElement()==a?0!=b.compareEndPoints("StartToEnd",b):!1},Jf=function(){var a=fe("div");return"oncopy"in a?!0:(a.setAttribute("oncopy","return;"),"function"==typeof a.oncopy)}(),Kf={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:";",91:"Mod",92:"Mod",93:"Mod",109:"-",107:"=",127:"Delete",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63276:"PageUp",63277:"PageDown",63275:"End",63273:"Home",63234:"Left",63232:"Up",63235:"Right",63233:"Down",63302:"Insert",63272:"Delete"};a.keyNames=Kf,function(){for(var a=0;10>a;a++)Kf[a+48]=String(a);for(var a=65;90>=a;a++)Kf[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)Kf[a+111]=Kf[a+63235]="F"+a}();var Lf,Mf=function(){function a(a){return 255>=a?b.charAt(a):a>=1424&&1524>=a?"R":a>=1536&&1791>=a?c.charAt(a-1536):a>=1792&&2220>=a?"r":"L"}var b="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL",c="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr",d=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,e=/[stwN]/,f=/[LRr]/,g=/[Lb1n]/,h=/[1n]/,i="L";return function(b){if(!d.test(b))return!1;for(var c,j=b.length,k=[],l=0;j>l;++l)k.push(c=a(b.charCodeAt(l)));for(var l=0,m=i;j>l;++l){var c=k[l];"m"==c?k[l]=m:m=c}for(var l=0,n=i;j>l;++l){var c=k[l];"1"==c&&"r"==n?k[l]="n":f.test(c)&&(n=c,"r"==c&&(k[l]="R"))}for(var l=1,m=k[0];j-1>l;++l){var c=k[l];"+"==c&&"1"==m&&"1"==k[l+1]?k[l]="1":","!=c||m!=k[l+1]||"1"!=m&&"n"!=m||(k[l]=m),m=c}for(var l=0;j>l;++l){var c=k[l];if(","==c)k[l]="N";else if("%"==c){for(var o=l+1;j>o&&"%"==k[o];++o);for(var p=l&&"!"==k[l-1]||j-1>o&&"1"==k[o]?"1":"N",q=l;o>q;++q)k[q]=p;l=o-1}}for(var l=0,n=i;j>l;++l){var c=k[l];"L"==n&&"1"==c?k[l]="L":f.test(c)&&(n=c)}for(var l=0;j>l;++l)if(e.test(k[l])){for(var o=l+1;j>o&&e.test(k[o]);++o);for(var r="L"==(l?k[l-1]:i),s="L"==(j-1>o?k[o]:i),p=r||s?"L":"R",q=l;o>q;++q)k[q]=p;l=o-1}for(var t,u=[],l=0;j>l;)if(g.test(k[l])){var v=l;for(++l;j>l&&g.test(k[l]);++l);u.push({from:v,to:l,level:0})}else{var w=l,x=u.length;for(++l;j>l&&"L"!=k[l];++l);for(var q=w;l>q;)if(h.test(k[q])){q>w&&u.splice(x,0,{from:w,to:q,level:1});var y=q;for(++q;l>q&&h.test(k[q]);++q);u.splice(x,0,{from:y,to:q,level:2}),w=q}else++q;l>w&&u.splice(x,0,{from:w,to:l,level:1})}return 1==u[0].level&&(t=b.match(/^\s+/))&&(u[0].from=t[0].length,u.unshift({from:0,to:t[0].length,level:0})),1==Yd(u).level&&(t=b.match(/\s+$/))&&(Yd(u).to-=t[0].length,u.push({from:j-t[0].length,to:j,level:0})),u[0].level!=Yd(u).level&&u.push({from:j,to:j,level:u[0].level}),u}}();return a.version="3.19.0",a}(),CodeMirror.defineMode("clike",function(a,b){function c(a,b){var c=a.next();if(q[c]){var f=q[c](a,b);if(f!==!1)return f}if('"'==c||"'"==c)return b.tokenize=d(c),b.tokenize(a,b);if(/[\[\]{}\(\),;\:\.]/.test(c))return i=c,null;if(/\d/.test(c))return a.eatWhile(/[\w\.]/),"number";if("/"==c){if(a.eat("*"))return b.tokenize=e,e(a,b);if(a.eat("/"))return a.skipToEnd(),"comment"}if(s.test(c))return a.eatWhile(s),"operator";a.eatWhile(/[\w\$_]/);var g=a.current();return m.propertyIsEnumerable(g)?(o.propertyIsEnumerable(g)&&(i="newstatement"),"keyword"):n.propertyIsEnumerable(g)?(o.propertyIsEnumerable(g)&&(i="newstatement"),"builtin"):p.propertyIsEnumerable(g)?"atom":"variable"}function d(a){return function(b,c){for(var d,e=!1,f=!1;null!=(d=b.next());){if(d==a&&!e){f=!0;break}e=!e&&"\\"==d}return(f||!e&&!r)&&(c.tokenize=null),"string"}}function e(a,b){for(var c,d=!1;c=a.next();){if("/"==c&&d){b.tokenize=null;break}d="*"==c}return"comment"}function f(a,b,c,d,e){this.indented=a,this.column=b,this.type=c,this.align=d,this.prev=e}function g(a,b,c){var d=a.indented;return a.context&&"statement"==a.context.type&&(d=a.context.indented),a.context=new f(d,b,c,null,a.context)}function h(a){var b=a.context.type;return(")"==b||"]"==b||"}"==b)&&(a.indented=a.context.indented),a.context=a.context.prev}var i,j=a.indentUnit,k=b.statementIndentUnit||j,l=b.dontAlignCalls,m=b.keywords||{},n=b.builtin||{},o=b.blockKeywords||{},p=b.atoms||{},q=b.hooks||{},r=b.multiLineStrings,s=/[+\-*&%=<>!?|\/]/;return{startState:function(a){return{tokenize:null,context:new f((a||0)-j,0,"top",!1),indented:0,startOfLine:!0}},token:function(a,b){var d=b.context;if(a.sol()&&(null==d.align&&(d.align=!1),b.indented=a.indentation(),b.startOfLine=!0),a.eatSpace())return null;i=null;var e=(b.tokenize||c)(a,b);if("comment"==e||"meta"==e)return e;if(null==d.align&&(d.align=!0),";"!=i&&":"!=i&&","!=i||"statement"!=d.type)if("{"==i)g(b,a.column(),"}");else if("["==i)g(b,a.column(),"]");else if("("==i)g(b,a.column(),")");else if("}"==i){for(;"statement"==d.type;)d=h(b);for("}"==d.type&&(d=h(b));"statement"==d.type;)d=h(b)}else i==d.type?h(b):(("}"==d.type||"top"==d.type)&&";"!=i||"statement"==d.type&&"newstatement"==i)&&g(b,a.column(),"statement");else h(b);return b.startOfLine=!1,e},indent:function(a,b){if(a.tokenize!=c&&null!=a.tokenize)return CodeMirror.Pass;var d=a.context,e=b&&b.charAt(0);"statement"==d.type&&"}"==e&&(d=d.prev);var f=e==d.type;return"statement"==d.type?d.indented+("{"==e?0:k):!d.align||l&&")"==d.type?")"!=d.type||f?d.indented+(f?0:j):d.indented+k:d.column+(f?0:1)},electricChars:"{}",blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",fold:"brace"}}),function(){function a(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}function b(a,c){if(!c.startOfLine)return!1;for(;;){if(!a.skipTo("\\")){a.skipToEnd(),c.tokenize=null;break}if(a.next(),a.eol()){c.tokenize=b;break}}return"meta"}function c(a,b){for(var c;null!=(c=a.next());)if('"'==c&&!a.eat('"')){b.tokenize=null;break}return"string"}function d(a,b){for(var c=0;c<a.length;++c)CodeMirror.defineMIME(a[c],b)}var e="auto if break int case long char register continue return default short do sizeof double static else struct entry switch extern typedef float union for unsigned goto while enum void const signed volatile";d(["text/x-csrc","text/x-c","text/x-chdr"],{name:"clike",keywords:a(e),blockKeywords:a("case do else for if switch while struct"),atoms:a("null"),hooks:{"#":b}}),d(["text/x-c++src","text/x-c++hdr"],{name:"clike",keywords:a(e+" asm dynamic_cast namespace reinterpret_cast try bool explicit new "+"static_cast typeid catch operator template typename class friend private "+"this using const_cast inline public throw virtual delete mutable protected "+"wchar_t"),blockKeywords:a("catch class do else finally for if struct switch try while"),atoms:a("true false null"),hooks:{"#":b}}),CodeMirror.defineMIME("text/x-java",{name:"clike",keywords:a("abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while"),blockKeywords:a("catch class do else finally for if switch try while"),atoms:a("true false null"),hooks:{"@":function(a){return a.eatWhile(/[\w\$_]/),"meta"}}}),CodeMirror.defineMIME("text/x-csharp",{name:"clike",keywords:a("abstract as base break case catch checked class const continue default delegate do else enum event explicit extern finally fixed for foreach goto if implicit in interface internal is lock namespace new operator out override params private protected public readonly ref return sealed sizeof stackalloc static struct switch this throw try typeof unchecked unsafe using virtual void volatile while add alias ascending descending dynamic from get global group into join let orderby partial remove select set value var yield"),blockKeywords:a("catch class do else finally for foreach if struct switch try while"),builtin:a("Boolean Byte Char DateTime DateTimeOffset Decimal Double Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32 UInt64 bool byte char decimal double short int long object sbyte float string ushort uint ulong"),atoms:a("true false null"),hooks:{"@":function(a,b){return a.eat('"')?(b.tokenize=c,c(a,b)):(a.eatWhile(/[\w\$_]/),"meta")}}}),CodeMirror.defineMIME("text/x-scala",{name:"clike",keywords:a("abstract case catch class def do else extends false final finally for forSome if implicit import lazy match new null object override package private protected return sealed super this throw trait try trye type val var while with yield _ : = => <- <: <% >: # @ assert assume require print println printf readLine readBoolean readByte readShort readChar readInt readLong readFloat readDouble AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"),blockKeywords:a("catch class do else finally for forSome if match switch try while"),atoms:a("true false null"),hooks:{"@":function(a){return a.eatWhile(/[\w\$_]/),"meta"}}}),d(["x-shader/x-vertex","x-shader/x-fragment"],{name:"clike",keywords:a("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4 sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadowconst attribute uniform varying break continue discard return for while do if else struct in out inout"),blockKeywords:a("for while do if else struct"),builtin:a("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smootstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shadow1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:a("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragColor gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),hooks:{"#":b}})}(),function(){function a(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}function b(a){return function(b,c){return b.match(a)?c.tokenize=null:b.skipToEnd(),"string"}}var c={name:"clike",keywords:a("abstract and array as break case catch class clone const continue declare default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final for foreach function global goto if implements interface instanceof namespace new or private protected public static switch throw trait try use var while xor die echo empty exit eval include include_once isset list require require_once return print unset __halt_compiler self static parent yield insteadof finally"),blockKeywords:a("catch do else elseif for foreach if switch try while finally"),atoms:a("true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__"),builtin:a("func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once"),multiLineStrings:!0,hooks:{$:function(a){return a.eatWhile(/[\w\$_]/),"variable-2"},"<":function(a,c){return a.match(/<</)?(a.eatWhile(/[\w\.]/),c.tokenize=b(a.current().slice(3)),c.tokenize(a,c)):!1},"#":function(a){for(;!a.eol()&&!a.match("?>",!1);)a.next();return"comment"},"/":function(a){if(a.eat("/")){for(;!a.eol()&&!a.match("?>",!1);)a.next();return"comment"}return!1}}};CodeMirror.defineMode("php",function(a,b){function d(a,b){var c=b.curMode==f;if(a.sol()&&'"'!=b.pending&&(b.pending=null),c)return c&&null==b.php.tokenize&&a.match("?>")?(b.curMode=e,b.curState=b.html,"meta"):f.token(a,b.curState);if(a.match(/^<\?\w*/))return b.curMode=f,b.curState=b.php,"meta";if('"'==b.pending){for(;!a.eol()&&'"'!=a.next(););var d="string"}else if(b.pending&&a.pos<b.pending.end){a.pos=b.pending.end;var d=b.pending.style}else var d=e.token(a,b.curState);b.pending=null;var g=a.current(),h=g.search(/<\?/);return-1!=h&&(b.pending="string"==d&&/\"$/.test(g)&&!/\?>/.test(g)?'"':{end:a.pos,style:d},a.backUp(g.length-h)),d
5
+ }var e=CodeMirror.getMode(a,"text/html"),f=CodeMirror.getMode(a,c);return{startState:function(){var a=CodeMirror.startState(e),c=CodeMirror.startState(f);return{html:a,php:c,curMode:b.startOpen?f:e,curState:b.startOpen?c:a,pending:null}},copyState:function(a){var b,c=a.html,d=CodeMirror.copyState(e,c),g=a.php,h=CodeMirror.copyState(f,g);return b=a.curMode==e?d:h,{html:d,php:h,curMode:a.curMode,curState:b,pending:a.pending}},token:d,indent:function(a,b){return a.curMode!=f&&/^\s*<\//.test(b)||a.curMode==f&&/^\?>/.test(b)?e.indent(a.html,b):a.curMode.indent(a.curState,b)},electricChars:"/{}:",blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",innerMode:function(a){return{state:a.curState,mode:a.curMode}}}},"htmlmixed","clike"),CodeMirror.defineMIME("application/x-httpd-php","php"),CodeMirror.defineMIME("application/x-httpd-php-open",{name:"php",startOpen:!0}),CodeMirror.defineMIME("text/x-php",c)}(),function(){function a(a,c,d,e){if(this.atOccurrence=!1,this.doc=a,null==e&&"string"==typeof c&&(e=!1),d=d?a.clipPos(d):b(0,0),this.pos={from:d,to:d},"string"!=typeof c)c.global||(c=new RegExp(c.source,c.ignoreCase?"ig":"g")),this.matches=function(d,e){if(d){c.lastIndex=0;for(var f,g,h=a.getLine(e.line).slice(0,e.ch),i=0;;){c.lastIndex=i;var j=c.exec(h);if(!j)break;if(f=j,g=f.index,i=f.index+(f[0].length||1),i==h.length)break}var k=f&&f[0].length||0;k||(0==g&&0==h.length?f=void 0:g!=a.getLine(e.line).length&&k++)}else{c.lastIndex=e.ch;var h=a.getLine(e.line),f=c.exec(h),k=f&&f[0].length||0,g=f&&f.index;g+k==h.length||k||(k=1)}return f&&k?{from:b(e.line,g),to:b(e.line,g+k),match:f}:void 0};else{e&&(c=c.toLowerCase());var f=e?function(a){return a.toLowerCase()}:function(a){return a},g=c.split("\n");this.matches=1==g.length?c.length?function(d,e){var g,h=f(a.getLine(e.line)),i=c.length;return(d?e.ch>=i&&-1!=(g=h.lastIndexOf(c,e.ch-i)):-1!=(g=h.indexOf(c,e.ch)))?{from:b(e.line,g),to:b(e.line,g+i)}:void 0}:function(){}:function(c,d){var e=d.line,h=c?g.length-1:0,i=g[h],j=f(a.getLine(e)),k=c?j.indexOf(i)+i.length:j.lastIndexOf(i);if(!(c?k>d.ch||k!=i.length:k<d.ch||k!=j.length-i.length))for(;;){if(c?!e:e==a.lineCount()-1)return;if(j=f(a.getLine(e+=c?-1:1)),i=g[c?--h:++h],!(h>0&&h<g.length-1)){var l=c?j.lastIndexOf(i):j.indexOf(i)+i.length;if(c?l!=j.length-i.length:l!=i.length)return;var m=b(d.line,k),n=b(e,l);return{from:c?n:m,to:c?m:n}}if(j!=i)return}}}}var b=CodeMirror.Pos;a.prototype={findNext:function(){return this.find(!1)},findPrevious:function(){return this.find(!0)},find:function(a){function c(a){var c=b(a,0);return d.pos={from:c,to:c},d.atOccurrence=!1,!1}for(var d=this,e=this.doc.clipPos(a?this.pos.from:this.pos.to);;){if(this.pos=this.matches(a,e))return this.pos.from&&this.pos.to||console.log(this.matches,this.pos),this.atOccurrence=!0,this.pos.match||!0;if(a){if(!e.line)return c(0);e=b(e.line-1,this.doc.getLine(e.line-1).length)}else{var f=this.doc.lineCount();if(e.line==f-1)return c(f);e=b(e.line+1,0)}}},from:function(){return this.atOccurrence?this.pos.from:void 0},to:function(){return this.atOccurrence?this.pos.to:void 0},replace:function(a){if(this.atOccurrence){var c=CodeMirror.splitLines(a);this.doc.replaceRange(c,this.pos.from,this.pos.to),this.pos.to=b(this.pos.from.line+c.length-1,c[c.length-1].length+(1==c.length?this.pos.from.ch:0))}}},CodeMirror.defineExtension("getSearchCursor",function(b,c,d){return new a(this.doc,b,c,d)}),CodeMirror.defineDocExtension("getSearchCursor",function(b,c,d){return new a(this,b,c,d)})}(),function(){function a(a){return"string"==typeof a?{token:function(b){return b.match(a)?"searching":(b.next(),b.skipTo(a.charAt(0))||b.skipToEnd(),void 0)}}:{token:function(b){if(b.match(a))return"searching";for(;!b.eol()&&(b.next(),!b.match(a,!1)););}}}function b(){this.posFrom=this.posTo=this.query=null,this.overlay=null}function c(a){return a.state.search||(a.state.search=new b)}function d(a,b,c){return a.getSearchCursor(b,c,"string"==typeof b&&b==b.toLowerCase())}function e(a,b,c,d){a.openDialog?a.openDialog(b,d):d(prompt(c,""))}function f(a,b,c,d){a.openConfirm?a.openConfirm(b,d):confirm(c)&&d[0]()}function g(a){var b=a.match(/^\/(.*)\/([a-z]*)$/);return b?new RegExp(b[1],-1==b[2].indexOf("i")?"":"i"):a}function h(b,d){var f=c(b);return f.query?i(b,d):(e(b,l,"Search for:",function(c){b.operation(function(){c&&!f.query&&(f.query=g(c),b.removeOverlay(f.overlay),f.overlay=a(f.query),b.addOverlay(f.overlay),f.posFrom=f.posTo=b.getCursor(),i(b,d))})}),void 0)}function i(a,b){a.operation(function(){var e=c(a),f=d(a,e.query,b?e.posFrom:e.posTo);(f.find(b)||(f=d(a,e.query,b?CodeMirror.Pos(a.lastLine()):CodeMirror.Pos(a.firstLine(),0)),f.find(b)))&&(a.setSelection(f.from(),f.to()),a.scrollIntoView({from:f.from(),to:f.to()}),e.posFrom=f.from(),e.posTo=f.to())})}function j(a){a.operation(function(){var b=c(a);b.query&&(b.query=null,a.removeOverlay(b.overlay))})}function k(a,b){e(a,m,"Replace:",function(c){c&&(c=g(c),e(a,n,"Replace with:",function(e){if(b)a.operation(function(){for(var b=d(a,c);b.findNext();)if("string"!=typeof c){var f=a.getRange(b.from(),b.to()).match(c);b.replace(e.replace(/\$(\d)/,function(a,b){return f[b]}))}else b.replace(e)});else{j(a);var g=d(a,c,a.getCursor()),h=function(){var b,e=g.from();!(b=g.findNext())&&(g=d(a,c),!(b=g.findNext())||e&&g.from().line==e.line&&g.from().ch==e.ch)||(a.setSelection(g.from(),g.to()),a.scrollIntoView({from:g.from(),to:g.to()}),f(a,o,"Replace?",[function(){i(b)},h]))},i=function(a){g.replace("string"==typeof c?e:e.replace(/\$(\d)/,function(b,c){return a[c]})),h()};h()}}))})}var l='Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>',m='Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>',n='With: <input type="text" style="width: 10em"/>',o="Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";CodeMirror.commands.find=function(a){j(a),h(a)},CodeMirror.commands.findNext=h,CodeMirror.commands.findPrev=function(a){h(a,!0)},CodeMirror.commands.clearSearch=j,CodeMirror.commands.replace=k,CodeMirror.commands.replaceAll=function(a){k(a,!0)}}(),function(){function a(a,b,c){function d(b,c,d){if(b.text){var g=m?0:b.text.length-1,i=m?b.text.length:-1;if(b.text.length>h)return null;for(null!=d&&(g=d+n);g!=i;g+=n){var j=b.text.charAt(g);if(r.test(j)&&a.getTokenTypeAt(e(c,g+1))==p){var k=f[j];if(">"==k.charAt(1)==m)q.push(j);else{if(q.pop()!=k.charAt(0))return{pos:g,match:!1};if(!q.length)return{pos:g,match:!0}}}}}}var g=a.state.matchBrackets,h=g&&g.maxScanLineLength||1e4,i=b||a.getCursor(),j=a.getLineHandle(i.line),k=i.ch-1,l=k>=0&&f[j.text.charAt(k)]||f[j.text.charAt(++k)];if(!l)return null;var m=">"==l.charAt(1),n=m?1:-1;if(c&&m!=(k==i.ch))return null;for(var o,p=a.getTokenTypeAt(e(i.line,k+1)),q=[j.text.charAt(k)],r=/[(){}[\]]/,s=i.line,t=m?Math.min(s+100,a.lineCount()):Math.max(-1,s-100);s!=t&&!(o=s==i.line?d(j,s,k):d(a.getLineHandle(s),s));s+=n);return{from:e(i.line,k),to:o&&e(s,o.pos),match:o&&o.match,forward:m}}function b(b,c){var f=b.state.matchBrackets.maxHighlightLineLength||1e3,g=a(b);if(!(!g||b.getLine(g.from.line).length>f||g.to&&b.getLine(g.to.line).length>f)){var h=g.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket",i=b.markText(g.from,e(g.from.line,g.from.ch+1),{className:h}),j=g.to&&b.markText(g.to,e(g.to.line,g.to.ch+1),{className:h});d&&b.state.focused&&b.display.input.focus();var k=function(){b.operation(function(){i.clear(),j&&j.clear()})};return c?(setTimeout(k,800),void 0):k}}function c(a){a.operation(function(){g&&(g(),g=null),a.somethingSelected()||(g=b(a,!1))})}var d=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),e=CodeMirror.Pos,f={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"},g=null;CodeMirror.defineOption("matchBrackets",!1,function(a,b,d){d&&d!=CodeMirror.Init&&a.off("cursorActivity",c),b&&(a.state.matchBrackets="object"==typeof b?b:{},a.on("cursorActivity",c))}),CodeMirror.defineExtension("matchBrackets",function(){b(this,!0)}),CodeMirror.defineExtension("findMatchingBracket",function(b,c){return a(this,b,c)})}();var a={lineNumbers:!0,matchBrackets:!0,lineWrapping:!0,mode:"text/x-php",indentUnit:4,indentWithTabs:!0,enterMode:"keep",tabMode:"shift"};CodeMirror.fromTextArea(document.getElementById("snippet_code"),a)}();
assets/scss/admin-single.scss CHANGED
@@ -2,7 +2,7 @@
2
  * Custom styling for the single snippet admin page
3
  */
4
 
5
- @import 'compass/css3';
6
 
7
  h3 {
8
  /* Provide some decent space between the fields and titles */
@@ -14,6 +14,21 @@ label {
14
  cursor: auto;
15
  }
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  /**
18
  * Customize the CodeMirror editor
19
  * to look pretty and support auto-resizing
@@ -22,10 +37,10 @@ label {
22
  min-height: 300px;
23
  height: auto;
24
  border: 1px solid #eee;
25
- @include border-radius(3px);
26
 
27
  /* Tweak things for the MP6 interface */
28
- .admin-color-mp6 & {
29
  width: 100%;
30
  border-color: #dfdfdf;
31
  background-color: #fff;
2
  * Custom styling for the single snippet admin page
3
  */
4
 
5
+ /* import 'codemirror/lib/codemirror.css' */
6
 
7
  h3 {
8
  /* Provide some decent space between the fields and titles */
14
  cursor: auto;
15
  }
16
 
17
+ /* Position the description heading on the same level as the editor buttons */
18
+ label[for="snippet_description"] h3 div {
19
+ position: absolute;
20
+
21
+ /* MP6 fails with TeenyMCE editor */
22
+ .mp6 & {
23
+ position: initial;
24
+ }
25
+ }
26
+
27
+ /* Add spacing in between the action buttons */
28
+ .submit .button {
29
+ margin-right: .5em;
30
+ }
31
+
32
  /**
33
  * Customize the CodeMirror editor
34
  * to look pretty and support auto-resizing
37
  min-height: 300px;
38
  height: auto;
39
  border: 1px solid #eee;
40
+ border-radius: 3px;
41
 
42
  /* Tweak things for the MP6 interface */
43
+ .mp6 & {
44
  width: 100%;
45
  border-color: #dfdfdf;
46
  background-color: #fff;
assets/scss/menu-icon-mp6.scss CHANGED
@@ -4,15 +4,24 @@
4
 
5
  #toplevel_page_snippets div.wp-menu-image {
6
 
7
- &:before {
8
- display: none;
 
9
  }
10
 
11
- background: {
12
- image: inline-image( 'menu-icon-mp6.svg') !important;
13
- position: center center !important;
14
- size: 20px 20px;
15
- repeat: no-repeat;
 
 
 
 
 
 
 
 
 
16
  }
17
- margin-top: 2px;
18
  }
4
 
5
  #toplevel_page_snippets div.wp-menu-image {
6
 
7
+ /* Use the plugins dashicon as a fallback */
8
+ .mp6.no-svg &:before {
9
+ content: '\f106';
10
  }
11
 
12
+ /* If the browser does support SVG, use our custom icon */
13
+ .mp6.svg & {
14
+
15
+ /* Remove the generic dashicon */
16
+ &:before {
17
+ display: none;
18
+ }
19
+
20
+ background: {
21
+ image: inline-image( 'menu-icon-mp6.svg') !important;
22
+ position: center center !important;
23
+ size: 20px 20px;
24
+ repeat: no-repeat;
25
+ }
26
  }
 
27
  }
assets/scss/table-mp6.scss CHANGED
@@ -3,8 +3,6 @@
3
  * and the MP6 interface
4
  */
5
 
6
- @import 'compass/css3';
7
-
8
  .snippets {
9
 
10
  th, td {
@@ -15,7 +13,7 @@
15
  background: #fff;
16
  }
17
 
18
- .row-actions-visible {
19
  color: #ddd;
20
  }
21
 
@@ -42,16 +40,11 @@
42
  a {
43
  color: #579;
44
  }
45
-
46
- .column-name strong {
47
- color: #333;
48
- font-weight: 400;
49
- }
50
  }
51
 
52
  .inactive, .active {
53
  td, th {
54
- @include box-shadow(inset 0 -1px 0 rgba(0,0,0,0.1));
55
  padding: 10px 9px;
56
  border: none;
57
  }
@@ -71,7 +64,7 @@
71
 
72
  tr.active + tr.inactive th,
73
  tr.active + tr.inactive td {
74
- @include box-shadow(inset 0px 1px 0 rgba(0,0,0,0.02), inset 0 -1px 0 #e1e1e1);
75
  border-top: 1px solid rgba(0,0,0,0.03);
76
  }
77
 
3
  * and the MP6 interface
4
  */
5
 
 
 
6
  .snippets {
7
 
8
  th, td {
13
  background: #fff;
14
  }
15
 
16
+ .row-actions {
17
  color: #ddd;
18
  }
19
 
40
  a {
41
  color: #579;
42
  }
 
 
 
 
 
43
  }
44
 
45
  .inactive, .active {
46
  td, th {
47
+ box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
48
  padding: 10px 9px;
49
  border: none;
50
  }
64
 
65
  tr.active + tr.inactive th,
66
  tr.active + tr.inactive td {
67
+ box-shadow: inset 0px 1px 0 rgba(0,0,0,0.02), inset 0 -1px 0 #e1e1e1;
68
  border-top: 1px solid rgba(0,0,0,0.03);
69
  }
70
 
code-snippets.php CHANGED
@@ -7,7 +7,7 @@
7
  * contribute to the localization, please see http://code-snippets.bungeshea.com
8
  *
9
  * @package Code_Snippets
10
- * @version 1.8.1.1
11
  * @author Shea Bunge <http://bungeshea.com/>
12
  * @copyright Copyright (c) 2012-2013, Shea Bunge
13
  * @link http://code-snippets.bungeshea.com
@@ -20,7 +20,7 @@
20
  * Description: An easy, clean and simple way to add code snippets to your site. No need to edit to your theme's functions.php file again!
21
  * Author: Shea Bunge
22
  * Author URI: http://bungeshea.com
23
- * Version: 1.8.1.1
24
  * License: MIT
25
  * License URI: license.txt
26
  * Text Domain: code-snippets
@@ -58,7 +58,7 @@ final class Code_Snippets {
58
  * @access public
59
  * @var string A PHP-standardized version number string
60
  */
61
- public $version = '1.8.1.1';
62
 
63
  /**
64
  * Variables to hold plugin paths
@@ -185,8 +185,8 @@ final class Code_Snippets {
185
  $this->get_include( 'functions' );
186
 
187
  /* Add and remove capabilities from Super Admins if their statuses change */
188
- add_action( 'grant_super_admin', array( $this, 'add_ms_caps' ) );
189
- add_action( 'remove_super_admin', array( $this, 'remove_ms_caps' ) );
190
 
191
  /* Let extension plugins know that it's okay to load */
192
  do_action( 'code_snippets_init' );
@@ -207,6 +207,11 @@ final class Code_Snippets {
207
  $this->plugin_dir = plugin_dir_path( $this->file );
208
  $this->plugin_url = plugin_dir_url ( $this->file );
209
 
 
 
 
 
 
210
  if ( is_admin() ) {
211
 
212
  /* Load our administration class */
@@ -435,8 +440,16 @@ final class Code_Snippets {
435
  /* Skip this if we're on the latest version */
436
  if ( version_compare( $current_version, $this->version, '<' ) ) {
437
 
438
- /* Data in database is unsecapped in 1.8 */
439
- if ( version_compare( $current_version, '1.8', '<' ) ) {
 
 
 
 
 
 
 
 
440
 
441
  $tables = array();
442
 
@@ -453,9 +466,15 @@ final class Code_Snippets {
453
 
454
  foreach ( $snippets as $snippet ) {
455
 
456
- $snippet->name = esc_sql( htmlspecialchars_decode( stripslashes( $snippet->name ) ) );
457
- $snippet->code = esc_sql( htmlspecialchars_decode( stripslashes( $snippet->code ) ) );
458
- $snippet->description = esc_sql( htmlspecialchars_decode( stripslashes( $snippet->description ) ) );
 
 
 
 
 
 
459
 
460
  $wpdb->update( $table,
461
  array(
@@ -474,7 +493,7 @@ final class Code_Snippets {
474
 
475
  /* Register the capabilities once only */
476
  if ( version_compare( $current_version, '1.5', '<' ) ) {
477
- $this->setup_roles( true );
478
  }
479
 
480
  if ( version_compare( $previous_version, '1.2', '<' ) ) {
@@ -494,13 +513,30 @@ final class Code_Snippets {
494
 
495
  if ( version_compare( $current_ms_version, $this->version, '<' ) ) {
496
 
 
 
 
 
 
 
 
 
 
 
 
 
497
  if ( version_compare( $current_ms_version, '1.5', '<' ) ) {
498
  $this->setup_ms_roles( true );
499
  }
500
 
501
  /* Migrate recently_network_activated_snippets to the site options */
502
  if ( get_option( 'recently_network_activated_snippets' ) ) {
503
- add_site_option( 'recently_activated_snippets', get_option( 'recently_network_activated_snippets', array() ) );
 
 
 
 
 
504
  delete_option( 'recently_network_activated_snippets' );
505
  }
506
 
@@ -514,33 +550,38 @@ final class Code_Snippets {
514
  /**
515
  * Register the user roles and capabilities
516
  *
 
517
  * @since 1.5
518
  * @access private
519
- * @param boolean $install true to add the capabilities, false to remove
520
  * @return void
521
  */
522
- function setup_roles( $install = true ) {
523
-
524
- $this->caps = apply_filters( 'code_snippets_caps',
525
- array(
526
- 'manage_snippets',
527
- 'install_snippets',
528
- 'edit_snippets'
529
- )
530
- );
531
 
532
- $this->role = get_role( apply_filters( 'code_snippets_role', 'administrator' ) );
 
533
 
534
- foreach ( $this->caps as $cap ) {
535
- if ( $install )
536
- $this->role->add_cap( $cap );
537
- else
538
- $this->role->remove_cap( $cap );
539
- }
 
 
 
 
 
 
 
 
 
 
 
 
540
  }
541
 
542
  /**
543
- * Register the multisite user roles and capabilities
544
  *
545
  * @since 1.5
546
  * @access private
@@ -552,23 +593,15 @@ final class Code_Snippets {
552
  if ( ! is_multisite() )
553
  return;
554
 
555
- $this->network_caps = apply_filters( 'code_snippets_network_caps',
556
- array(
557
- 'manage_network_snippets',
558
- 'install_network_snippets',
559
- 'edit_network_snippets'
560
- )
561
- );
562
-
563
  $supers = get_super_admins();
564
 
565
  foreach ( $supers as $admin ) {
566
  $user = new WP_User( 0, $admin );
567
 
568
  if ( $install )
569
- $this->grant_ms_caps( $user );
570
  else
571
- $this->remove_ms_caps( $user );
572
  }
573
 
574
  }
@@ -576,39 +609,33 @@ final class Code_Snippets {
576
  /**
577
  * Add the multisite capabilities to a user
578
  *
579
- * @since 1.8.2
580
- * @param object|integer $user An instance of the WP_User class or a user ID
581
  * @return void
582
  */
583
- function add_ms_caps( $user ) {
584
 
585
- /* If a user ID is passed in, convert it to a WP_User */
586
- if ( is_int( $user ) )
587
- $user = new WP_User( $user );
588
 
589
- /* Add the capabilities */
590
- foreach ( $this->network_caps as $cap ) {
591
- $user->add_cap( $cap );
592
- }
593
  }
594
 
595
  /**
596
  * Remove the multisite capabilities from a user
597
  *
598
- * @since 1.8.2
599
- * @param object|integer $user An instance of the WP_User class or a user ID
600
  * @return void
601
  */
602
- function remove_ms_caps( $user ) {
603
 
604
- /* If a user ID is passed in, convert it to a WP_User */
605
- if ( is_int( $user ) )
606
- $user = new WP_User( $user );
607
 
608
- /* Remove the capabilities */
609
- foreach ( $this->network_caps as $cap ) {
610
- $user->remove_cap( $cap );
611
- }
612
  }
613
 
614
  /**
@@ -617,15 +644,16 @@ final class Code_Snippets {
617
  * @uses current_user_can() To check if the current user can perform a task
618
  * @uses $this->get_cap() To get the required capability
619
  *
620
- * @param string $do_what The task to check against.
621
  * @return boolean Whether the current user can perform this task or not
622
  *
 
623
  * @since 1.7.1.1 Moved logic to $this->get_cap() method
624
  * @since 1.7.1
625
  * @access public
626
  */
627
- public function user_can( $do_what ) {
628
- return current_user_can( $this->get_cap( $do_what ) );
629
  }
630
 
631
  /**
@@ -635,23 +663,25 @@ final class Code_Snippets {
635
  * If multisite, checks if *Enable Administration Menus: Snippets* is active
636
  * under the *Settings > Network Settings* network admin menu
637
  *
 
 
638
  * @since 1.7.1.1
639
  * @access public
640
- * @param string $do_what The action to retrieve the capability for
641
  * @return void
642
  */
643
- public function get_cap( $do_what ) {
644
 
645
  if ( is_multisite() ) {
 
646
 
647
- if ( in_array( 'snippets', get_site_option( 'menu_items', array() ) ) )
648
- return "{$do_what}_snippets";
649
- else
650
- return "{$do_what}_network_snippets";
651
 
652
- } else {
653
- return "{$do_what}_snippets";
654
  }
 
 
655
  }
656
 
657
  /**
@@ -754,17 +784,14 @@ final class Code_Snippets {
754
 
755
  $snippet = $this->build_snippet_object( $snippet );
756
 
757
- /* remove the <?php and ?> tags from the snippet */
758
- $snippet->code = trim( $snippet->code );
759
- $snippet->code = ltrim( $snippet->code, '<?php' );
760
- $snippet->code = ltrim( $snippet->code, '<?' );
761
- $snippet->code = rtrim( $snippet->code, '?>' );
762
 
763
- /* escape the data */
764
- $snippet->name = esc_sql( $snippet->name );
765
- $snippet->description = esc_sql( $snippet->description );
766
- $snippet->code = esc_sql( $snippet->code );
767
- $snippet->id = absint ( $snippet->id );
768
 
769
  return apply_filters( 'code_snippets/escape_snippet_data', $snippet );
770
  }
@@ -780,13 +807,7 @@ final class Code_Snippets {
780
  * @return object The resulting snippet object, with data unescaped
781
  */
782
  public function unescape_snippet_data( $snippet ) {
783
-
784
  $snippet = $this->build_snippet_object( $snippet );
785
-
786
- $snippet->name = stripslashes( $snippet->name );
787
- $snippet->code = stripslashes( $snippet->code );
788
- $snippet->description = stripslashes( $snippet->description );
789
-
790
  return apply_filters( 'code_snippets/unescape_snippet_data', $snippet );
791
  }
792
 
@@ -918,10 +939,11 @@ final class Code_Snippets {
918
  public function delete_snippet( $id, $scope = '' ) {
919
  global $wpdb;
920
 
921
- $table = $this->get_table_name( $scope );
922
- $id = absint( $id );
923
-
924
- $wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE id='%d' LIMIT 1", $id ) );
 
925
 
926
  do_action( 'code_snippets/delete_snippet', $id, $scope );
927
  }
@@ -944,8 +966,8 @@ final class Code_Snippets {
944
 
945
  $snippet = $this->escape_snippet_data( $snippet );
946
  $table = $this->get_table_name( $scope );
 
947
 
948
- $fields = '';
949
  foreach ( get_object_vars( $snippet ) as $field => $value ) {
950
  if ( 'id' === $field )
951
  continue;
@@ -953,25 +975,18 @@ final class Code_Snippets {
953
  if ( is_array( $value ) )
954
  $value = maybe_serialize( $value );
955
 
956
- $fields .= "{$field}='{$value}',";
957
  }
958
- $fields = rtrim( $fields, ',' );
959
 
960
  if ( isset( $snippet->id ) && 0 !== $snippet->id ) {
961
 
962
- if ( $fields ) {
963
- $wpdb->query( $wpdb->prepare( "UPDATE $table SET $fields WHERE id='%d' LIMIT 1", $snippet->id ) );
964
- }
965
-
966
  do_action( 'code_snippets/update_snippet', $snippet, $table );
967
  return $snippet->id;
968
 
969
  } else {
970
 
971
- if ( $fields ) {
972
- $wpdb->query( "INSERT INTO $table SET $fields" );
973
- }
974
-
975
  do_action( 'code_snippets/create_snippet', $snippet, $table );
976
  return $wpdb->insert_id;
977
  }
@@ -1002,7 +1017,9 @@ final class Code_Snippets {
1002
  foreach ( $xml->children() as $snippet ) {
1003
  /* force manual build of object to strip out unsupported fields
1004
  by converting snippet object into an array */
1005
- $this->save_snippet( get_object_vars( $snippet ), $scope );
 
 
1006
  }
1007
 
1008
  do_action( 'code_snippets/import', $xml, $scope );
@@ -1016,7 +1033,7 @@ final class Code_Snippets {
1016
  * @since 1.5
1017
  * @access public
1018
  *
1019
- * @uses code_snippets_export() To export selected snippets
1020
  * @uses $this->get_table_name() To dynamically retrieve the name of the snippet table
1021
  *
1022
  * @param array $ids The IDs of the snippets to export
@@ -1027,10 +1044,11 @@ final class Code_Snippets {
1027
 
1028
  $table = $this->get_table_name( $scope );
1029
 
1030
- if ( ! function_exists( 'code_snippets_export' ) )
1031
- $this->get_include( 'export' );
1032
 
1033
- code_snippets_export( $ids, 'xml', $table );
 
1034
  }
1035
 
1036
  /**
@@ -1039,8 +1057,8 @@ final class Code_Snippets {
1039
  * @since 1.5
1040
  * @access public
1041
  *
1042
- * @uses code_snippets_export() To export selected snippets
1043
- * @uses $this->get_table_name() To dynamically retrieve the name of the snippet table
1044
  *
1045
  * @param array $ids The IDs of the snippets to export
1046
  * @param string $scope Is the snippet a network-wide or site-wide snippet?
@@ -1050,10 +1068,15 @@ final class Code_Snippets {
1050
 
1051
  $table = $this->get_table_name( $scope );
1052
 
1053
- if ( ! function_exists( 'code_snippets_export' ) )
1054
- $this->get_include( 'export' );
 
 
 
 
1055
 
1056
- code_snippets_export( $ids, 'php', $table );
 
1057
  }
1058
 
1059
  /**
@@ -1119,13 +1142,12 @@ final class Code_Snippets {
1119
  /* Grab the active snippets from the database */
1120
  $active_snippets = $wpdb->get_col( $sql );
1121
 
1122
- if ( count( $active_snippets ) ) {
1123
- foreach ( $active_snippets as $snippet ) {
1124
- /* Execute the PHP code */
1125
- $this->execute_snippet( htmlspecialchars_decode( stripslashes( $snippet ) ) );
1126
- }
1127
- return true;
1128
  }
 
 
1129
  }
1130
 
1131
  /* If we're made it this far without returning true, assume failure */
@@ -1158,7 +1180,7 @@ final class Code_Snippets {
1158
  delete_option( 'cs_db_version' );
1159
  delete_option( 'recently_activated_snippets' );
1160
  delete_option( 'code_snippets_version' );
1161
- $code_snippets->setup_roles( false );
1162
  }
1163
  restore_current_blog();
1164
  }
@@ -1170,7 +1192,7 @@ final class Code_Snippets {
1170
  $wpdb->query( "DROP TABLE IF EXISTS $wpdb->snippets" );
1171
  delete_option( 'code_snippets_version' );
1172
  delete_option( 'recently_activated_snippets' );
1173
- $code_snippets->setup_roles( false );
1174
  }
1175
  }
1176
 
7
  * contribute to the localization, please see http://code-snippets.bungeshea.com
8
  *
9
  * @package Code_Snippets
10
+ * @version 1.9
11
  * @author Shea Bunge <http://bungeshea.com/>
12
  * @copyright Copyright (c) 2012-2013, Shea Bunge
13
  * @link http://code-snippets.bungeshea.com
20
  * Description: An easy, clean and simple way to add code snippets to your site. No need to edit to your theme's functions.php file again!
21
  * Author: Shea Bunge
22
  * Author URI: http://bungeshea.com
23
+ * Version: 1.9
24
  * License: MIT
25
  * License URI: license.txt
26
  * Text Domain: code-snippets
58
  * @access public
59
  * @var string A PHP-standardized version number string
60
  */
61
+ public $version = '1.9';
62
 
63
  /**
64
  * Variables to hold plugin paths
185
  $this->get_include( 'functions' );
186
 
187
  /* Add and remove capabilities from Super Admins if their statuses change */
188
+ add_action( 'grant_super_admin', array( $this, 'add_ms_cap_to_user' ) );
189
+ add_action( 'remove_super_admin', array( $this, 'remove_ms_cap_from_user' ) );
190
 
191
  /* Let extension plugins know that it's okay to load */
192
  do_action( 'code_snippets_init' );
207
  $this->plugin_dir = plugin_dir_path( $this->file );
208
  $this->plugin_url = plugin_dir_url ( $this->file );
209
 
210
+ /* Roles and capabilities variables */
211
+ $this->role = apply_filters( 'code_snippets_role', 'administrator' );
212
+ $this->cap = apply_filters( 'code_snippets_cap', 'manage_snippets' );
213
+ $this->network_cap = apply_filters( 'code_snippets_network_cap', 'manage_network_snippets' );
214
+
215
  if ( is_admin() ) {
216
 
217
  /* Load our administration class */
440
  /* Skip this if we're on the latest version */
441
  if ( version_compare( $current_version, $this->version, '<' ) ) {
442
 
443
+ /* Remove capabilities that were deprecated in 1.9 */
444
+ if ( version_compare( $current_version, '1.9', '<' ) ) {
445
+ $role = get_role( $this->role );
446
+
447
+ $role->remove_cap( 'install_network_snippets' );
448
+ $role->remove_cap( 'edit_network_snippets' );
449
+ }
450
+
451
+ /* Data in database is unescaped in 1.8; slashes removed in 1.9 */
452
+ if ( version_compare( $current_version, '1.9', '<' ) ) {
453
 
454
  $tables = array();
455
 
466
 
467
  foreach ( $snippets as $snippet ) {
468
 
469
+ $snippet->name = stripslashes( $snippet->name );
470
+ $snippet->code = stripslashes( $snippet->code );
471
+ $snippet->description = stripslashes( $snippet->description );
472
+
473
+ if ( version_compare( $current_version, '1.8', '<' ) ) {
474
+ $snippet->name = htmlspecialchars_decode( $snippet->name );
475
+ $snippet->code = htmlspecialchars_decode( $snippet->code );
476
+ $snippet->description = htmlspecialchars_decode( $snippet->description );
477
+ }
478
 
479
  $wpdb->update( $table,
480
  array(
493
 
494
  /* Register the capabilities once only */
495
  if ( version_compare( $current_version, '1.5', '<' ) ) {
496
+ $this->add_cap();
497
  }
498
 
499
  if ( version_compare( $previous_version, '1.2', '<' ) ) {
513
 
514
  if ( version_compare( $current_ms_version, $this->version, '<' ) ) {
515
 
516
+ /* Remove capabilities that were deprecated in 1.9 */
517
+ if ( version_compare( $current_version, '1.9', '<' ) ) {
518
+ $supers = get_super_admins();
519
+
520
+ foreach ( $supers as $admin ) {
521
+ $user = new WP_User( 0, $admin );
522
+ $user->remove_cap( 'install_network_snippets' );
523
+ $user->remove_cap( 'edit_network_snippets' );
524
+ }
525
+ }
526
+
527
+ /* Add custom capabilities introduced in 1.5 */
528
  if ( version_compare( $current_ms_version, '1.5', '<' ) ) {
529
  $this->setup_ms_roles( true );
530
  }
531
 
532
  /* Migrate recently_network_activated_snippets to the site options */
533
  if ( get_option( 'recently_network_activated_snippets' ) ) {
534
+
535
+ add_site_option(
536
+ 'recently_activated_snippets',
537
+ get_option( 'recently_network_activated_snippets', array() )
538
+ );
539
+
540
  delete_option( 'recently_network_activated_snippets' );
541
  }
542
 
550
  /**
551
  * Register the user roles and capabilities
552
  *
553
+ * @since 1.9 Removed uninstall functionality into a separate method
554
  * @since 1.5
555
  * @access private
 
556
  * @return void
557
  */
558
+ function add_cap() {
 
 
 
 
 
 
 
 
559
 
560
+ /* Retrieve the role object */
561
+ $role = get_role( $this->role );
562
 
563
+ /* Add the capability */
564
+ $role->add_cap( $this->cap );
565
+ }
566
+
567
+ /**
568
+ * Deregister the user roles and capabilities
569
+ *
570
+ * @since 1.9
571
+ * @access private
572
+ * @return void
573
+ */
574
+ function remove_cap() {
575
+
576
+ /* Retrieve the role object */
577
+ $role = get_role( $this->role );
578
+
579
+ /* Remove the capability */
580
+ $role->remove_cap( $this->cap );
581
  }
582
 
583
  /**
584
+ * Register or deregister the multisite user roles and capabilities
585
  *
586
  * @since 1.5
587
  * @access private
593
  if ( ! is_multisite() )
594
  return;
595
 
 
 
 
 
 
 
 
 
596
  $supers = get_super_admins();
597
 
598
  foreach ( $supers as $admin ) {
599
  $user = new WP_User( 0, $admin );
600
 
601
  if ( $install )
602
+ $user->add_cap( $this->network_cap );
603
  else
604
+ $user->remove_cap( $this->network_cap );
605
  }
606
 
607
  }
609
  /**
610
  * Add the multisite capabilities to a user
611
  *
612
+ * @since 1.9
613
+ * @param integer $user_id The ID of the user to add the cap to
614
  * @return void
615
  */
616
+ function add_ms_cap_to_user( $user_id ) {
617
 
618
+ /* Get the user from the ID */
619
+ $user = new WP_User( $user_id );
 
620
 
621
+ /* Add the capability */
622
+ $user->add_cap( $this->network_cap );
 
 
623
  }
624
 
625
  /**
626
  * Remove the multisite capabilities from a user
627
  *
628
+ * @since 1.9
629
+ * @param integer $user_id The ID of the user to remove the cap from
630
  * @return void
631
  */
632
+ function remove_ms_cap_from_user( $user_id ) {
633
 
634
+ /* Get the user from the ID */
635
+ $user = new WP_User( $user_id );
 
636
 
637
+ /* Remove the capability */
638
+ $user->remove_cap( $this->network_cap );
 
 
639
  }
640
 
641
  /**
644
  * @uses current_user_can() To check if the current user can perform a task
645
  * @uses $this->get_cap() To get the required capability
646
  *
647
+ * @param string $deprecated Deprecated in 1.9
648
  * @return boolean Whether the current user can perform this task or not
649
  *
650
+ * @since 1.9 Removed multiple capability support
651
  * @since 1.7.1.1 Moved logic to $this->get_cap() method
652
  * @since 1.7.1
653
  * @access public
654
  */
655
+ public function user_can( $deprecated = '' ) {
656
+ return current_user_can( $this->get_cap() );
657
  }
658
 
659
  /**
663
  * If multisite, checks if *Enable Administration Menus: Snippets* is active
664
  * under the *Settings > Network Settings* network admin menu
665
  *
666
+ * @param string $deprecated Deprecated in 1.9
667
+ * @since 1.9 Removed first parameter
668
  * @since 1.7.1.1
669
  * @access public
 
670
  * @return void
671
  */
672
+ public function get_cap( $deprecated = '' ) {
673
 
674
  if ( is_multisite() ) {
675
+ $active_menus = get_site_option( 'menu_items', array() );
676
 
677
+ /* If multisite is enabled and the snippet menu is not activated,
678
+ restrict snippet operations to super admins only */
679
+ if ( ! in_array( 'snippets', $active_menus ) )
680
+ return $this->network_cap;
681
 
 
 
682
  }
683
+
684
+ return $this->cap;
685
  }
686
 
687
  /**
784
 
785
  $snippet = $this->build_snippet_object( $snippet );
786
 
787
+ /* Remove <?php and <? from beginning of snippet */
788
+ $snippet->code = preg_replace( '|^[\s]*<\?(php)?|', '', $snippet->code );
789
+
790
+ /* Remove ?> from end of snippet */
791
+ $snippet->code = preg_replace( '|\?>[\s]*$|', '', $snippet->code );
792
 
793
+ /* Escape the data */
794
+ $snippet->id = absint ( $snippet->id );
 
 
 
795
 
796
  return apply_filters( 'code_snippets/escape_snippet_data', $snippet );
797
  }
807
  * @return object The resulting snippet object, with data unescaped
808
  */
809
  public function unescape_snippet_data( $snippet ) {
 
810
  $snippet = $this->build_snippet_object( $snippet );
 
 
 
 
 
811
  return apply_filters( 'code_snippets/unescape_snippet_data', $snippet );
812
  }
813
 
939
  public function delete_snippet( $id, $scope = '' ) {
940
  global $wpdb;
941
 
942
+ $wpdb->delete(
943
+ $this->get_table_name( $scope ),
944
+ array( 'id' => $id ),
945
+ array( '%d' )
946
+ );
947
 
948
  do_action( 'code_snippets/delete_snippet', $id, $scope );
949
  }
966
 
967
  $snippet = $this->escape_snippet_data( $snippet );
968
  $table = $this->get_table_name( $scope );
969
+ $data = array();
970
 
 
971
  foreach ( get_object_vars( $snippet ) as $field => $value ) {
972
  if ( 'id' === $field )
973
  continue;
975
  if ( is_array( $value ) )
976
  $value = maybe_serialize( $value );
977
 
978
+ $data[ $field ] = $value;
979
  }
 
980
 
981
  if ( isset( $snippet->id ) && 0 !== $snippet->id ) {
982
 
983
+ $wpdb->update( $table, $data, array( 'id' => $snippet->id ), null, array( '%d' ) );
 
 
 
984
  do_action( 'code_snippets/update_snippet', $snippet, $table );
985
  return $snippet->id;
986
 
987
  } else {
988
 
989
+ $wpdb->insert( $table, $data, '%s' );
 
 
 
990
  do_action( 'code_snippets/create_snippet', $snippet, $table );
991
  return $wpdb->insert_id;
992
  }
1017
  foreach ( $xml->children() as $snippet ) {
1018
  /* force manual build of object to strip out unsupported fields
1019
  by converting snippet object into an array */
1020
+ $snippet = get_object_vars( $snippet );
1021
+ $snippet = array_map( 'htmlspecialchars_decode', $snippet );
1022
+ $this->save_snippet( $snippet, $scope );
1023
  }
1024
 
1025
  do_action( 'code_snippets/import', $xml, $scope );
1033
  * @since 1.5
1034
  * @access public
1035
  *
1036
+ * @uses Code_Snippets_Export To export selected snippets
1037
  * @uses $this->get_table_name() To dynamically retrieve the name of the snippet table
1038
  *
1039
  * @param array $ids The IDs of the snippets to export
1044
 
1045
  $table = $this->get_table_name( $scope );
1046
 
1047
+ if ( ! class_exists( 'Code_Snippets_Export' ) )
1048
+ $this->get_include( 'class-export' );
1049
 
1050
+ $class = new Code_Snippets_Export( $ids, $table );
1051
+ $class->do_export();
1052
  }
1053
 
1054
  /**
1057
  * @since 1.5
1058
  * @access public
1059
  *
1060
+ * @uses Code_Snippets_Export_PHP To export selected snippets
1061
+ * @uses $this->get_table_name() To dynamically retrieve the name of the snippet table
1062
  *
1063
  * @param array $ids The IDs of the snippets to export
1064
  * @param string $scope Is the snippet a network-wide or site-wide snippet?
1068
 
1069
  $table = $this->get_table_name( $scope );
1070
 
1071
+ if ( ! class_exists( 'Code_Snippets_Export' ) )
1072
+ $this->get_include( 'class-export' );
1073
+
1074
+ if ( ! class_exists( 'Code_Snippets_Export_PHP' ) ) {
1075
+ $this->get_include( 'class-export-php' );
1076
+ }
1077
 
1078
+ $class = new Code_Snippets_Export_PHP( $ids, $table );
1079
+ $class->do_export();
1080
  }
1081
 
1082
  /**
1142
  /* Grab the active snippets from the database */
1143
  $active_snippets = $wpdb->get_col( $sql );
1144
 
1145
+ foreach ( $active_snippets as $snippet ) {
1146
+ /* Execute the PHP code */
1147
+ $this->execute_snippet( $snippet );
 
 
 
1148
  }
1149
+
1150
+ return true;
1151
  }
1152
 
1153
  /* If we're made it this far without returning true, assume failure */
1180
  delete_option( 'cs_db_version' );
1181
  delete_option( 'recently_activated_snippets' );
1182
  delete_option( 'code_snippets_version' );
1183
+ $code_snippets->remove_cap();
1184
  }
1185
  restore_current_blog();
1186
  }
1192
  $wpdb->query( "DROP TABLE IF EXISTS $wpdb->snippets" );
1193
  delete_option( 'code_snippets_version' );
1194
  delete_option( 'recently_activated_snippets' );
1195
+ $code_snippets->remove_cap();
1196
  }
1197
  }
1198
 
includes/class-admin.php CHANGED
@@ -89,6 +89,27 @@ class Code_Snippets_Admin {
89
 
90
  /* Allow super admins to control site admins access to snippet admin menus */
91
  add_filter( 'mu_menu_items', array( $this, 'mu_menu_items') );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
93
 
94
  /**
@@ -213,7 +234,7 @@ class Code_Snippets_Admin {
213
  global $code_snippets;
214
 
215
  /* Use a different screen icon for the MP6 interface */
216
- if ( get_user_option( 'admin_color' ) !== 'mp6' ) {
217
  $menu_icon = apply_filters( 'code_snippets/admin/menu_icon_url',
218
  plugins_url( 'assets/images/menu-icon.png', $code_snippets->file )
219
  );
@@ -225,7 +246,7 @@ class Code_Snippets_Admin {
225
  $this->manage_page = add_menu_page(
226
  __( 'Snippets', 'code-snippets' ),
227
  __( 'Snippets', 'code-snippets' ),
228
- $code_snippets->get_cap( 'manage' ),
229
  $this->manage_slug,
230
  array( $this, 'display_manage_menu' ),
231
  $menu_icon,
@@ -236,7 +257,7 @@ class Code_Snippets_Admin {
236
  $this->manage_slug,
237
  __( 'Snippets', 'code-snippets' ),
238
  __( 'Manage', 'code-snippets' ),
239
- $code_snippets->get_cap( 'manage' ),
240
  $this->manage_slug,
241
  array( $this, 'display_manage_menu')
242
  );
@@ -248,7 +269,7 @@ class Code_Snippets_Admin {
248
  $this->manage_slug,
249
  $editing ? __( 'Edit Snippet', 'code-snippets' ) : __( 'Add New Snippet', 'code-snippets' ),
250
  $editing ? __( 'Edit', 'code-snippets' ) : __( 'Add New', 'code-snippets' ),
251
- $code_snippets->get_cap( 'install' ),
252
  $this->single_slug,
253
  array( $this, 'display_single_menu' )
254
  );
@@ -276,7 +297,7 @@ class Code_Snippets_Admin {
276
  $this->manage_slug,
277
  __( 'Import Snippets', 'code-snippets' ),
278
  __( 'Import', 'code-snippets' ),
279
- $code_snippets->get_cap( 'import' ),
280
  'import-code-snippets',
281
  array( $this, 'display_import_menu' )
282
  );
@@ -348,35 +369,49 @@ class Code_Snippets_Admin {
348
  /* Create the snippet tables if they don't exist */
349
  $code_snippets->maybe_create_tables( true, true );
350
 
351
- /* Don't let the user pass if they can't edit (install check is done by WP) */
352
- if ( isset( $_REQUEST['edit'] ) && ! $code_snippets->user_can( 'edit' ) )
353
- wp_die( __("Sorry, you're not allowed to edit snippets", 'code-snippets' ) );
 
 
 
 
 
 
 
354
 
355
  /* Save the snippet if one has been submitted */
356
- if ( isset( $_REQUEST['save_snippet'] ) || isset( $_REQUEST['save_snippet_activate'] ) ) {
357
 
358
- /* Set the snippet to active if we used the 'Save Changed & Activate' button */
359
- if ( isset( $_REQUEST['save_snippet_activate'] ) )
360
  $_POST['snippet_active'] = 1;
 
 
 
361
 
362
  /* Save the snippet to the database */
363
- $result = $code_snippets->save_snippet( $_POST );
364
 
365
  /* Strip old status query vars from URL */
366
- $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'added', 'updated', 'activated', 'invalid' ) );
367
 
368
  /* Build the status message and redirect */
369
 
370
- if ( isset( $_REQUEST['save_snippet_activate'] ) && $result ) {
371
- /* Snippet was activated */
372
  $_SERVER['REQUEST_URI'] = add_query_arg( 'activated', true );
373
  }
 
 
 
 
374
 
375
  if ( ! $result || $result < 1 ) {
376
  /* An error occurred */
377
  wp_redirect( add_query_arg( 'invalid', true ) );
378
  }
379
- elseif ( isset( $_REQUEST['snippet_id'] ) ) {
380
  /* Existing snippet was updated */
381
  wp_redirect( add_query_arg( array( 'edit' => $result, 'updated' => true ) ) );
382
  }
@@ -386,11 +421,16 @@ class Code_Snippets_Admin {
386
  }
387
  }
388
 
389
- /* Load the screen help tabs */
390
- $this->load_help_tabs( 'single' );
 
 
 
391
 
392
- /* Enqueue the code editor and other scripts and styles */
393
- add_filter( 'admin_enqueue_scripts', array( $this, 'single_menu_enqueue_scripts' ) );
 
 
394
  }
395
 
396
  /**
@@ -414,128 +454,28 @@ class Code_Snippets_Admin {
414
  if ( $hook !== $this->single_page )
415
  return;
416
 
417
- /* CodeMirror package version */
418
- $codemirror_version = '3.14';
419
-
420
- /* CodeMirror base framework */
421
-
422
- wp_register_script(
423
- 'codemirror',
424
- plugins_url( 'vendor/codemirror/lib/codemirror.js', $code_snippets->file ),
425
- false,
426
- $codemirror_version
427
- );
428
-
429
- wp_register_style(
430
- 'codemirror',
431
- plugins_url( 'vendor/codemirror/lib/codemirror.css', $code_snippets->file ),
432
- false,
433
- $codemirror_version
434
- );
435
-
436
- /* CodeMirror modes */
437
-
438
- wp_register_script(
439
- "codemirror-mode-clike",
440
- plugins_url( "vendor/codemirror/mode/clike.js", $code_snippets->file ),
441
- array( 'codemirror' ),
442
- $codemirror_version
443
- );
444
-
445
- wp_register_script(
446
- "codemirror-mode-php",
447
- plugins_url( "vendor/codemirror/mode/php.js", $code_snippets->file ),
448
- array( 'codemirror', 'codemirror-mode-clike' ),
449
- $codemirror_version
450
- );
451
-
452
- /* CodeMirror addons */
453
-
454
- wp_register_script(
455
- "codemirror-addon-dialog",
456
- plugins_url( "vendor/codemirror/addon/dialog.js", $code_snippets->file ),
457
- array( 'codemirror' ),
458
- $codemirror_version
459
- );
460
-
461
- wp_register_style(
462
- 'codemirror-addon-dialog',
463
- plugins_url( 'vendor/codemirror/addon/dialog.css', $code_snippets->file ),
464
- array( 'codemirror' ),
465
- $codemirror_version
466
- );
467
-
468
- wp_register_script(
469
- "codemirror-addon-searchcursor",
470
- plugins_url( "vendor/codemirror/addon/searchcursor.js", $code_snippets->file ),
471
- array( 'codemirror' ),
472
- $codemirror_version
473
- );
474
-
475
- wp_register_script(
476
- "codemirror-addon-search",
477
- plugins_url( "vendor/codemirror/addon/search.js", $code_snippets->file ),
478
- array( 'codemirror', 'codemirror-addon-dialog', 'codemirror-addon-searchcursor' ),
479
- $codemirror_version
480
- );
481
-
482
- wp_register_script(
483
- "codemirror-addon-matchbrackets",
484
- plugins_url( "vendor/codemirror/addon/matchbrackets.js", $code_snippets->file ),
485
- array( 'codemirror' ),
486
- $codemirror_version
487
- );
488
-
489
- if ( $debug ) {
490
-
491
- /* Enqueue the registered scripts */
492
- wp_enqueue_script( array(
493
- 'codemirror-mode-php',
494
- 'codemirror-addon-matchbrackets',
495
- 'codemirror-addon-search',
496
- ) );
497
-
498
- } else {
499
-
500
- wp_register_script(
501
- 'code-snippets-codemirror-min-js',
502
- plugins_url( 'vendor/codemirror.min.js', $code_snippets->file ),
503
- false,
504
- $codemirror_version
505
- );
506
-
507
- }
508
-
509
  /* Enqueue stylesheets */
510
 
511
  wp_enqueue_style(
512
  'code-snippets-admin-single',
513
  plugins_url( 'assets/css/admin-single.css', $code_snippets->file ),
514
- array( 'codemirror', 'codemirror-addon-dialog' ),
515
  $code_snippets->version
516
  );
517
 
518
  /* Enqueue scripts */
519
 
520
- /* Load the minified version of CodeMirror if SCRIPT_DEBUG is turned off */
521
- if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || defined( 'CODEMIRROR_SCRIPT_DEBUG' ) && CODEMIRROR_SCRIPT_DEBUG ) {
522
-
523
- $deps = array(
524
- 'codemirror-mode-php',
525
- 'codemirror-addon-matchbrackets',
526
- 'codemirror-addon-search'
527
- );
528
-
529
- } else {
530
- $deps = array( 'code-snippets-codemirror-min-js' );
531
- }
532
-
533
  wp_enqueue_script(
534
  'code-snippets-admin-single',
535
- plugins_url( 'assets/js/admin-single.js', $code_snippets->file ),
536
- $deps,
537
- $code_snippets->version
 
538
  );
 
 
 
 
539
  }
540
 
541
  /**
@@ -625,7 +565,7 @@ class Code_Snippets_Admin {
625
  ?>
626
 
627
  <label for="snippet_description">
628
- <h3><div style="position: absolute;"><?php _e( 'Description', 'code-snippets' ); ?></div></h3>
629
  </label>
630
 
631
  <?php
@@ -700,4 +640,43 @@ class Code_Snippets_Admin {
700
  ) );
701
  }
702
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
703
  } // end of class
89
 
90
  /* Allow super admins to control site admins access to snippet admin menus */
91
  add_filter( 'mu_menu_items', array( $this, 'mu_menu_items') );
92
+
93
+ /* Add the survey notice on the manage snippets page */
94
+ add_action( 'code_snippets/admin/manage', array( $this, 'survey_message' ) );
95
+
96
+ /* Remove incompatible Debug Bar Console CodeMirror version */
97
+ $this->remove_debug_bar_codemirror();
98
+ }
99
+
100
+ /**
101
+ * Remove the old CodeMirror version used by the Debug Bar Console
102
+ * plugin that is messing up the snippet editor
103
+ * @since 1.9
104
+ */
105
+ function remove_debug_bar_codemirror() {
106
+ global $pagenow;
107
+
108
+ /* Try to discern if we are on the single snippet page as best as we can at this early time */
109
+ is_admin() && 'admin.php' === $pagenow && isset( $_GET['page' ] ) && 'snippet' === $_GET['page']
110
+
111
+ /* Remove the action and stop all Debug Bar Console scripts */
112
+ && remove_action( 'debug_bar_enqueue_scripts', 'debug_bar_console_scripts' );
113
  }
114
 
115
  /**
234
  global $code_snippets;
235
 
236
  /* Use a different screen icon for the MP6 interface */
237
+ if ( ! defined( 'MP6' ) ) {
238
  $menu_icon = apply_filters( 'code_snippets/admin/menu_icon_url',
239
  plugins_url( 'assets/images/menu-icon.png', $code_snippets->file )
240
  );
246
  $this->manage_page = add_menu_page(
247
  __( 'Snippets', 'code-snippets' ),
248
  __( 'Snippets', 'code-snippets' ),
249
+ $code_snippets->get_cap(),
250
  $this->manage_slug,
251
  array( $this, 'display_manage_menu' ),
252
  $menu_icon,
257
  $this->manage_slug,
258
  __( 'Snippets', 'code-snippets' ),
259
  __( 'Manage', 'code-snippets' ),
260
+ $code_snippets->get_cap(),
261
  $this->manage_slug,
262
  array( $this, 'display_manage_menu')
263
  );
269
  $this->manage_slug,
270
  $editing ? __( 'Edit Snippet', 'code-snippets' ) : __( 'Add New Snippet', 'code-snippets' ),
271
  $editing ? __( 'Edit', 'code-snippets' ) : __( 'Add New', 'code-snippets' ),
272
+ $code_snippets->get_cap(),
273
  $this->single_slug,
274
  array( $this, 'display_single_menu' )
275
  );
297
  $this->manage_slug,
298
  __( 'Import Snippets', 'code-snippets' ),
299
  __( 'Import', 'code-snippets' ),
300
+ $code_snippets->get_cap(),
301
  'import-code-snippets',
302
  array( $this, 'display_import_menu' )
303
  );
369
  /* Create the snippet tables if they don't exist */
370
  $code_snippets->maybe_create_tables( true, true );
371
 
372
+ /* Load the screen help tabs */
373
+ $this->load_help_tabs( 'single' );
374
+
375
+ /* Enqueue the code editor and other scripts and styles */
376
+ add_filter( 'admin_enqueue_scripts', array( $this, 'single_menu_enqueue_scripts' ) );
377
+
378
+ /* Make sure the nonce validates before we do any snippet ops */
379
+ if ( ! isset( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'save_snippet' ) ) {
380
+ return;
381
+ }
382
 
383
  /* Save the snippet if one has been submitted */
384
+ if ( isset( $_POST['save_snippet'] ) || isset( $_POST['save_snippet_activate'] ) || isset( $_POST['save_snippet_deactivate'] ) ) {
385
 
386
+ /* Activate or deactivate the snippet before saving if we clicked the button */
387
+ if ( isset( $_POST['save_snippet_activate'] ) ) {
388
  $_POST['snippet_active'] = 1;
389
+ } elseif ( isset( $_POST['save_snippet_deactivate'] ) ) {
390
+ $_POST['snippet_active'] = 0;
391
+ }
392
 
393
  /* Save the snippet to the database */
394
+ $result = $code_snippets->save_snippet( stripslashes_deep( $_POST ) );
395
 
396
  /* Strip old status query vars from URL */
397
+ $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'added', 'updated', 'activated', 'deactivated', 'invalid' ) );
398
 
399
  /* Build the status message and redirect */
400
 
401
+ if ( $result && isset( $_POST['save_snippet_activate'] ) ) {
402
+ /* Snippet was activated addition to saving*/
403
  $_SERVER['REQUEST_URI'] = add_query_arg( 'activated', true );
404
  }
405
+ elseif ( $result && isset( $_POST['save_snippet_deactivate'] ) ) {
406
+ /* Snippet was deactivated addition to saving*/
407
+ $_SERVER['REQUEST_URI'] = add_query_arg( 'deactivated', true );
408
+ }
409
 
410
  if ( ! $result || $result < 1 ) {
411
  /* An error occurred */
412
  wp_redirect( add_query_arg( 'invalid', true ) );
413
  }
414
+ elseif ( isset( $_POST['snippet_id'] ) ) {
415
  /* Existing snippet was updated */
416
  wp_redirect( add_query_arg( array( 'edit' => $result, 'updated' => true ) ) );
417
  }
421
  }
422
  }
423
 
424
+ /* Delete the snippet if the button was clicked */
425
+ elseif ( isset( $_POST['snippet_id'], $_POST['delete_snippet'] ) ) {
426
+ $code_snippets->delete_snippet( $_POST['snippet_id'] );
427
+ wp_redirect( add_query_arg( 'delete', true, $this->manage_url ) );
428
+ }
429
 
430
+ /* Export the snippet if the button was clicked */
431
+ elseif ( isset( $_POST['snippet_id'], $_POST['export_snippet'] ) ) {
432
+ $code_snippets->export( $_POST['snippet_id'] );
433
+ }
434
  }
435
 
436
  /**
454
  if ( $hook !== $this->single_page )
455
  return;
456
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
  /* Enqueue stylesheets */
458
 
459
  wp_enqueue_style(
460
  'code-snippets-admin-single',
461
  plugins_url( 'assets/css/admin-single.css', $code_snippets->file ),
462
+ false,
463
  $code_snippets->version
464
  );
465
 
466
  /* Enqueue scripts */
467
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
  wp_enqueue_script(
469
  'code-snippets-admin-single',
470
+ plugins_url( 'assets/js/admin-single.min.js', $code_snippets->file ),
471
+ false,
472
+ $code_snippets->version,
473
+ true // Load in footer
474
  );
475
+
476
+ /* Remove other CodeMirror styles */
477
+ wp_deregister_style( 'codemirror' );
478
+ wp_deregister_style( 'wpeditor' );
479
  }
480
 
481
  /**
565
  ?>
566
 
567
  <label for="snippet_description">
568
+ <h3><div><?php _e( 'Description', 'code-snippets' ); ?></div></h3>
569
  </label>
570
 
571
  <?php
640
  ) );
641
  }
642
 
643
+ /**
644
+ * Print a notice inviting people to participate in the Code Snippets Survey
645
+ *
646
+ * @since 1.9
647
+ * @return void
648
+ */
649
+ function survey_message() {
650
+ global $current_user;
651
+
652
+ $key = 'ignore_code_snippets_survey_message';
653
+
654
+ /* Bail now if the user has dismissed the message */
655
+ if ( get_user_meta( $current_user->ID, $key ) ) {
656
+ return;
657
+ }
658
+ elseif ( isset( $_GET[ $key ], $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], $key ) ) {
659
+ add_user_meta( $current_user->ID, $key, true, true );
660
+ return;
661
+ }
662
+
663
+ ?>
664
+
665
+ <br />
666
+
667
+ <div class="updated"><p>
668
+
669
+ <?php _e( "<strong>Have feedback on Code Snippets?</strong> Please take the time to answer a short survey on how you use this plugin and what you'd like to see changed or added in the future.", 'code-snippets' ); ?>
670
+
671
+ <a href="http://code-snippets.bungeshea.com/survey/" class="button secondary" target="_blank" style="margin: auto .5em;">
672
+ <?php _e( 'Take the survey now', 'code-snippets' ); ?>
673
+ </a>
674
+
675
+ <a href="<?php echo wp_nonce_url( add_query_arg( $key, true ), $key ); ?>">Dismiss</a>
676
+
677
+ </p></div>
678
+
679
+ <?php
680
+ }
681
+
682
  } // end of class
includes/class-export-php.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This file handles exporting snippets in PHP format
5
+ *
6
+ * It's better to call the $code_snippets->export_php()
7
+ * method than directly using this class
8
+ *
9
+ * @since 1.9
10
+ * @package Code_Snippets
11
+ * @subpackage Export
12
+ */
13
+
14
+ if ( ! class_exists( 'Code_Snippets_Export_PHP' ) ) :
15
+
16
+ /**
17
+ * Exports selected snippets to a XML or PHP file.
18
+ *
19
+ * @since 1.3
20
+ * @param array $ids The IDs of the snippets to export
21
+ * @param string $format The format of the export file
22
+ * @return void
23
+ */
24
+ class Code_Snippets_Export_PHP extends Code_Snippets_Export {
25
+
26
+ /**
27
+ * Constructor function
28
+ * @param array $ids The IDs of the snippets to export
29
+ * @param string $table The name of the table to fetch snippets from
30
+ */
31
+ public function __construct( array $ids, $table ) {
32
+ add_filter( 'code_snippets/export/filename', array( $this, 'replace_filename_extension' ) );
33
+ parent::__construct( $ids, $table );
34
+ }
35
+
36
+ /**
37
+ * Replace the .xml file extension with a .php file extension
38
+ * @param string $filename The filename with a .xml extension
39
+ * @return string The filename with a .php extension
40
+ */
41
+ public function replace_filename_extension( $filename ) {
42
+ $filename = str_replace( '.xml', '.php', $filename );
43
+ return $filename;
44
+ }
45
+
46
+ /**
47
+ * Begin the export file
48
+ */
49
+ protected function do_header() {
50
+ echo '<?php';
51
+ }
52
+
53
+ /**
54
+ * Output a single snippet
55
+ * @param array $snippet
56
+ */
57
+ protected function do_item( $snippet ) {
58
+
59
+ echo "\n/**\n * {$snippet['name']}\n";
60
+
61
+ if ( ! empty( $snippet['description'] ) ) {
62
+
63
+ /* Convert description to PhpDoc */
64
+ $desc = strip_tags( str_replace( "\n", "\n * ", $snippet['description'] ) );
65
+
66
+ echo " *\n * $desc\n";
67
+ }
68
+
69
+ echo " */\n{$snippet['code']}\n";
70
+ }
71
+
72
+ /**
73
+ * Finish off the file
74
+ */
75
+ protected function do_footer() {}
76
+ }
77
+
78
+ endif; // function exists check
includes/class-export.php ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This file handles exporting snippets in XML format
5
+ *
6
+ * It's better to call the $code_snippets->export_php()
7
+ * method than directly using this class
8
+ *
9
+ * @since 1.9
10
+ * @package Code_Snippets
11
+ * @subpackage Export
12
+ */
13
+
14
+ if ( ! class_exists( 'Code_Snippets_Export' ) ) :
15
+
16
+ /**
17
+ * Exports selected snippets to a XML or PHP file.
18
+ *
19
+ * @since 1.3
20
+ * @param array $ids The IDs of the snippets to export
21
+ * @param string $format The format of the export file
22
+ * @return void
23
+ */
24
+ class Code_Snippets_Export {
25
+
26
+ /**
27
+ * The IDs
28
+ * @var array
29
+ */
30
+ public $snippet_ids = array();
31
+
32
+ /**
33
+ * The name of the table to fetch snippets from
34
+ * @var string
35
+ */
36
+ protected $table_name = '';
37
+
38
+ /**
39
+ * Constructor function
40
+ * @param array $ids The IDs of the snippets to export
41
+ * @param string $table The name of the table to fetch snippets from
42
+ */
43
+ function __construct( $ids, $table ) {
44
+ $this->snippet_ids = (array) $ids;
45
+ $this->table_name = $table;
46
+ $this->exclude_fields = apply_filters( 'code_snippets/export/exclude_from_export', array( 'id', 'active' ) );
47
+ }
48
+
49
+ /**
50
+ * Build the export file name
51
+ * @return string
52
+ */
53
+ function get_filename() {
54
+ global $code_snippets;
55
+
56
+ if ( 1 == count( $this->snippet_ids ) ) {
57
+ /* If there is only snippet to export, use its name instead of the site name */
58
+ $snippet = $code_snippets->get_snippet( $this->snippet_ids[0] );
59
+ $sitename = strtolower( $snippet->name );
60
+ } else {
61
+ /* Otherwise, use the site name as set in Settings > General */
62
+ $sitename = strtolower( get_bloginfo( 'name' ) );
63
+ }
64
+
65
+ /* Filter and sanitize the filename */
66
+ $filename = sanitize_file_name( apply_filters(
67
+ 'code_snippets/export/filename',
68
+ "{$sitename}.code-snippets.xml",
69
+ $sitename
70
+ ) );
71
+
72
+ return $filename;
73
+ }
74
+
75
+ /**
76
+ * Set HTTP headers and render the file header
77
+ */
78
+ protected function do_header() {
79
+ global $code_snippets;
80
+ header( 'Content-Type: text/xml; charset=' . get_bloginfo('charset') );
81
+
82
+ echo '<?xml version="1.0" encoding="' . get_bloginfo('charset') . "\" ?>\n";
83
+
84
+ ?>
85
+ <!-- This is a code snippets export file generated by the Code Snippets WordPress plugin. -->
86
+ <!-- http://wordpress.org/plugins/code-snippets -->
87
+
88
+ <!-- To import these snippets a WordPress site follow these steps: -->
89
+ <!-- 1. Log in to that site as an administrator. -->
90
+ <!-- 2. Install the Code Snippets plugin using the directions provided at the above link. -->
91
+ <!-- 3. Go to 'Tools: Import' in the WordPress admin panel. -->
92
+ <!-- 4. Click on the "Code Snippets" importer in the list -->
93
+ <!-- 5. Upload this file using the form provided on that page. -->
94
+ <!-- 6. Code Snippets will then import all of the snippets and associated information -->
95
+ <!-- contained in this file into your site. -->
96
+ <!-- 7. You will then have to visit the 'Snippets: Manage' admin menu and activate desired snippets -->
97
+
98
+ <?php
99
+
100
+ /* Run the generator line through the standard WordPress filter */
101
+ $gen = sprintf (
102
+ '<!-- generator="Code Snippets/%s" created="%s" -->',
103
+ $code_snippets->version,
104
+ date('Y-m-d H:i')
105
+ );
106
+ $type = 'code_snippets_export';
107
+ echo apply_filters( "get_the_generator_$type", $gen, $type );
108
+
109
+ /* Begin the file */
110
+ echo '<snippets>';
111
+
112
+ }
113
+
114
+ /**
115
+ * Render the items
116
+ */
117
+ protected function do_items() {
118
+ global $wpdb;
119
+
120
+ /* Loop through the snippets */
121
+
122
+ foreach ( $this->snippet_ids as $id ) {
123
+
124
+ /* Grab the snippet from the database */
125
+ $snippet = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE id = %d", $id ), ARRAY_A );
126
+
127
+ /* Remove slashes */
128
+ $snippet = stripslashes_deep( $snippet );
129
+
130
+ /* Output the item */
131
+ $this->do_item( $snippet );
132
+ do_action( 'code_snippets/export/after_snippet', $id, $this->get_filename() );
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Render a single item
138
+ * @param array $snippet
139
+ */
140
+ protected function do_item( $snippet ) {
141
+ echo "\n\t" . '<snippet>';
142
+
143
+ foreach ( $snippet as $field => $value ) {
144
+
145
+ /* Don't export certain fields */
146
+ if ( in_array( $field, $this->exclude_fields ) )
147
+ continue;
148
+
149
+ /* Output the field and value as indented XML */
150
+ if ( $value = apply_filters( "code_snippets/export/$field", $value ) ) {
151
+ $value = htmlspecialchars( $value );
152
+ echo "\n\t\t<$field>$value</$field>";
153
+ }
154
+ }
155
+ echo "\n\t" . '</snippet>';
156
+ }
157
+
158
+ /**
159
+ * Render the file footer
160
+ */
161
+ protected function do_footer() {
162
+ echo "\n</snippets>";
163
+ }
164
+
165
+ /**
166
+ * Export the snippets
167
+ */
168
+ public function do_export() {
169
+
170
+ /* HTTP header */
171
+ $filename = $this->get_filename();
172
+ header( 'Content-Disposition: attachment; filename=' . $filename );
173
+
174
+ /* File header */
175
+ $this->do_header();
176
+ do_action( 'code_snippets/export/after_header', $this->snippet_ids, $filename );
177
+
178
+ /* Items */
179
+ $this->do_items();
180
+ do_action( 'code_snippets/export/after_snippets', $this->snippet_ids, $filename );
181
+
182
+ /* Footer */
183
+ $this->do_footer();
184
+ do_action( 'code_snippets/export/after_footer', $this->snippet_ids, $filename );
185
+
186
+ exit;
187
+ }
188
+ }
189
+
190
+ endif; // function exists check
includes/class-list-table.php CHANGED
@@ -91,7 +91,7 @@ class Code_Snippets_List_Table extends WP_List_Table {
91
  return;
92
 
93
  /* Load a different stylesheet if MP6 is active */
94
- if ( 'mp6' === get_user_option( 'admin_color' ) ) {
95
 
96
  wp_enqueue_style(
97
  'snippets-table-mp6',
@@ -199,10 +199,16 @@ class Code_Snippets_List_Table extends WP_List_Table {
199
  else
200
  $title = sprintf ( __( 'Untitled #%d', 'code-snippets' ), $snippet->id );
201
 
 
 
 
 
202
  /* Return the name contents */
203
  return apply_filters(
204
  'code_snippets/list_table/column_name',
205
- sprintf ( '<strong>%s</strong>', $title ) . $this->row_actions( $actions, true ),
 
 
206
  $snippet
207
  );
208
  }
91
  return;
92
 
93
  /* Load a different stylesheet if MP6 is active */
94
+ if ( defined( 'MP6' ) ) {
95
 
96
  wp_enqueue_style(
97
  'snippets-table-mp6',
199
  else
200
  $title = sprintf ( __( 'Untitled #%d', 'code-snippets' ), $snippet->id );
201
 
202
+ $row_actions = $this->row_actions( $actions,
203
+ apply_filters( 'code_snippets/list_table/row_actions_always_visiable', false )
204
+ );
205
+
206
  /* Return the name contents */
207
  return apply_filters(
208
  'code_snippets/list_table/column_name',
209
+ sprintf ( '<a href="%2$s"><strong>%1$s</strong></a>', $title,
210
+ add_query_arg( 'edit', $snippet->id, $code_snippets->admin_single_url )
211
+ ) . $row_actions,
212
  $snippet
213
  );
214
  }
includes/export.php DELETED
@@ -1,153 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * This file handles the export functions
5
- *
6
- * It's better to call the $code_snippets->export()
7
- * and $code_snippets->export_php() methods then
8
- * directly use those in this file
9
- *
10
- * @package Code_Snippets
11
- * @subpackage Functions
12
- */
13
-
14
- if ( ! function_exists( 'code_snippets_export' ) ) :
15
-
16
- /**
17
- * Exports selected snippets to a XML or PHP file.
18
- *
19
- * @since 1.3
20
- * @param array $ids The IDs of the snippets to export
21
- * @param string $format The format of the export file
22
- * @return void
23
- */
24
- function code_snippets_export( $ids, $format = 'xml' ) {
25
-
26
- global $wpdb, $code_snippets;
27
- $ids = (array) $ids;
28
-
29
- if ( 1 === count( $ids ) ) {
30
- /* If there is only snippet to export, use its name instead of the site name */
31
- $snippet = $code_snippets->get_snippet( $ids );
32
- $sitename = strtolower( $snippet->name );
33
- } else {
34
- /* Otherwise, use the site name as set in Settings > General */
35
- $sitename = strtolower( get_bloginfo( 'name' ) );
36
- }
37
-
38
- $filename = sanitize_file_name( apply_filters(
39
- 'code_snippets/export/filename',
40
- "{$sitename}.code-snippets.{$format}",
41
- $format, $sitename
42
- ) );
43
-
44
- /* Apply the file headers */
45
-
46
- header( 'Content-Disposition: attachment; filename=' . $filename );
47
-
48
- if ( $format === 'xml' ) {
49
- header( 'Content-Type: text/xml; charset=' . get_bloginfo('charset') );
50
-
51
- echo '<?xml version="1.0" encoding="' . get_bloginfo('charset') . "\" ?>\n";
52
-
53
- ?>
54
- <!-- This is a code snippets export file generated by the Code Snippets WordPress plugin. -->
55
- <!-- http://wordpress.org/plugins/code-snippets -->
56
-
57
- <!-- To import these snippets a WordPress site follow these steps: -->
58
- <!-- 1. Log in to that site as an administrator. -->
59
- <!-- 2. Install the Code Snippets plugin using the directions provided at the above link. -->
60
- <!-- 3. Go to 'Tools: Import' in the WordPress admin panel. -->
61
- <!-- 4. Click on the "Code Snippets" importer in the list -->
62
- <!-- 5. Upload this file using the form provided on that page. -->
63
- <!-- 6. Code Snippets will then import all of the snippets and associated information -->
64
- <!-- contained in this file into your site. -->
65
- <!-- 7. You will then have to visit the 'Snippets: Manage' admin menu and activate desired snippets -->
66
-
67
- <?php
68
-
69
- /* Run the generator line through the standard WordPress filter */
70
- $gen = sprintf (
71
- '<!-- generator="Code Snippets/%s" created="%s" -->',
72
- $code_snippets->version,
73
- date('Y-m-d H:i')
74
- );
75
- $type = 'code_snippets_export';
76
- echo apply_filters( "get_the_generator_$type", $gen, $type );
77
-
78
- /* Start the XML section */
79
- echo "\n<snippets>";
80
-
81
- } elseif ( 'php' === $format ) {
82
-
83
- echo "<?php\n";
84
-
85
- }
86
-
87
- do_action( 'code_snippets/export/after_header', $format, $ids, $filename );
88
-
89
- /* Loop through the snippets */
90
-
91
- $table = $code_snippets->get_table_name();
92
- $exclude = apply_filters( 'code_snippets/export/exclude_from_export', array( 'id', 'active' ) );
93
-
94
- foreach ( $ids as $id ) {
95
-
96
- /* Grab the snippet from the database */
97
- $snippet = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE id = %d", $id ), ARRAY_A );
98
-
99
- /* Remove slashes */
100
- $snippet = stripslashes_deep( $snippet );
101
-
102
- if ( 'xml' === $format ) {
103
-
104
- echo "\n\t" . '<snippet>';
105
-
106
- foreach ( $snippet as $field => $value ) {
107
-
108
- /* Don't export certain fields */
109
- if ( in_array( $field, $exclude ) )
110
- continue;
111
-
112
- /* Output the field and value as indented XML */
113
- if ( $value = apply_filters( "code_snippets/export/$field", $value ) )
114
- echo "\n\t\t<$field>$value</$field>";
115
- }
116
- echo "\n\t" . '</snippet>';
117
- }
118
- elseif ( 'php' === $format ) {
119
-
120
- echo "\n/**\n * {$snippet['name']}\n";
121
-
122
- if ( ! empty( $snippet['description'] ) ) {
123
-
124
- /* Convert description to PhpDoc */
125
- $desc = strip_tags( str_replace( "\n", "\n * ", $snippet['description'] ) );
126
-
127
- echo " *\n * $desc\n";
128
- }
129
-
130
- echo " */\n{$snippet['code']}\n";
131
- }
132
- }
133
-
134
- do_action( 'code_snippets/export/after_snippets', $format, $id, $filename );
135
-
136
- /* Finish off the file */
137
-
138
- if ( 'xml' === $format ) {
139
-
140
- echo "\n</snippets>";
141
-
142
- } elseif ( 'php' === $format ) {
143
-
144
- echo '?>';
145
-
146
- }
147
-
148
- do_action( 'code_snippets/export/after_footer', $format, $ids, $filename );
149
-
150
- exit;
151
- }
152
-
153
- endif; // function exists check
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/code-snippets-fr_FR.mo ADDED
Binary file
languages/code-snippets-fr_FR.po ADDED
@@ -0,0 +1,574 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is distributed under the same license as the Code Snippets package.
2
+ msgid ""
3
+ msgstr ""
4
+ "PO-Revision-Date: 2013-09-12 10:25+0100\n"
5
+ "MIME-Version: 1.0\n"
6
+ "Content-Type: text/plain; charset=UTF-8\n"
7
+ "Content-Transfer-Encoding: 8bit\n"
8
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
9
+ "X-Generator: Poedit 1.5.7\n"
10
+ "Project-Id-Version: Code Snippets\n"
11
+ "POT-Creation-Date: \n"
12
+ "Last-Translator: \n"
13
+ "Language-Team: oWEB <oweb@office-web.net>\n"
14
+ "Language: French\n"
15
+
16
+ #: code-snippets.php:0 code-snippets.php:262
17
+ msgid "Code Snippets"
18
+ msgstr "Code Snippets"
19
+
20
+ #: code-snippets.php:0
21
+ msgid ""
22
+ "An easy, clean and simple way to add code snippets to your site. No need to "
23
+ "edit to your theme's functions.php file again!"
24
+ msgstr ""
25
+ "Une manière simple d'ajouter des snippets, portions de code, dans votre "
26
+ "site. Plus besoin d'éditer le fichier functions.php de votre thème !"
27
+
28
+ #: code-snippets.php:0
29
+ msgid "Shea Bunge"
30
+ msgstr "Shea Bunge"
31
+
32
+ #: code-snippets.php:0
33
+ msgid "http://bungeshea.com"
34
+ msgstr "http://bungeshea.com"
35
+
36
+ #: code-snippets.php:577 code-snippets.php:578 code-snippets.php:588
37
+ #: includes/admin/manage.php:36
38
+ msgid "Snippets"
39
+ msgstr "Snippets"
40
+
41
+ #: code-snippets.php:612 code-snippets.php:1145 includes/admin/single.php:45
42
+ msgid "Add New Snippet"
43
+ msgstr "Ajouter Snippet"
44
+
45
+ #: code-snippets.php:613
46
+ msgid "Add New"
47
+ msgstr "Nouveau"
48
+
49
+ #: code-snippets.php:641 includes/admin/import.php:34
50
+ msgid "Import Snippets"
51
+ msgstr "Import de Snippets"
52
+
53
+ #: code-snippets.php:642
54
+ msgid "Import"
55
+ msgstr "Importer"
56
+
57
+ #: code-snippets.php:601 code-snippets.php:1146 includes/admin/single.php:37
58
+ msgid "Edit Snippet"
59
+ msgstr "Editer"
60
+
61
+ #: code-snippets.php:1465
62
+ msgid "Manage your existing snippets"
63
+ msgstr "Gérer les snippets existants"
64
+
65
+ #: code-snippets.php:589 code-snippets.php:1466
66
+ msgid "Manage"
67
+ msgstr "Gérer"
68
+
69
+ #: code-snippets.php:1486
70
+ msgid "Visit the WordPress.org plugin page"
71
+ msgstr "Page du plugin sur WordPress.org"
72
+
73
+ #: code-snippets.php:1487
74
+ msgid "About"
75
+ msgstr "A propos"
76
+
77
+ #: code-snippets.php:1491
78
+ msgid "Visit the support forums"
79
+ msgstr "Forums de support"
80
+
81
+ #: code-snippets.php:1492
82
+ msgid "Support"
83
+ msgstr "Support"
84
+
85
+ #: code-snippets.php:1496
86
+ msgid "Support this plugin's development"
87
+ msgstr "Aider au développement du plugin"
88
+
89
+ #: code-snippets.php:1497
90
+ msgid "Donate"
91
+ msgstr "Faire un don"
92
+
93
+ #: includes/admin/import.php:38
94
+ msgid ""
95
+ "Howdy! Upload your Code Snippets export file and we&#8217;ll import the "
96
+ "snippets to this site."
97
+ msgstr ""
98
+ "Hey ! Chargez votre fichier contenant les portions de code et nous "
99
+ "importerons les Snippets dans ce site."
100
+
101
+ #: includes/admin/import.php:40
102
+ msgid ""
103
+ "You will need to go to the <a href=\"%s\">Manage Snippets</a> page to "
104
+ "activate the imported snippets."
105
+ msgstr ""
106
+ "Vous devez vous rendre à la page <a href=\"%s\">Gérer les Snippets</a> pour "
107
+ "activer l'import de snippets."
108
+
109
+ #: includes/admin/import.php:42
110
+ msgid ""
111
+ "Choose a Code Snippets (.xml) file to upload, then click Upload file and "
112
+ "import."
113
+ msgstr ""
114
+ "Choisissez un fichier Code Snippets (.xml) à transférer, puis cliquez "
115
+ "Transférer et Importer."
116
+
117
+ #: includes/admin/import.php:46
118
+ msgid "Choose a file from your computer:"
119
+ msgstr "Fichier sur votre ordinateur : "
120
+
121
+ #: includes/admin/import.php:46
122
+ msgid "(Maximum size: 8MB)"
123
+ msgstr "(Taille maxi : 8MB)"
124
+
125
+ #: includes/admin/import.php:55
126
+ msgid "Upload file and import"
127
+ msgstr "Transférer et Importer"
128
+
129
+ #: includes/admin/manage.php:21
130
+ msgid "Snippet <strong>activated</strong>."
131
+ msgstr "Snippet <strong>activaté</strong>."
132
+
133
+ #: includes/admin/manage.php:23
134
+ msgid "Selected snippets <strong>activated</strong>."
135
+ msgstr "Snippets sélectionnés <strong>activés</strong>. "
136
+
137
+ #: includes/admin/manage.php:25
138
+ msgid "Snippet <strong>deactivated</strong>."
139
+ msgstr "Snippet <strong>désactivaté</strong>."
140
+
141
+ #: includes/admin/manage.php:27
142
+ msgid "Selected snippets <strong>deactivated</strong>."
143
+ msgstr "Snippets sélectionnés <strong>désactivés</strong>. "
144
+
145
+ #: includes/admin/manage.php:29
146
+ msgid "Snippet <strong>deleted</strong>."
147
+ msgstr "Snippet <strong>supprimé</strong>."
148
+
149
+ #: includes/admin/manage.php:31
150
+ msgid "Selected snippets <strong>deleted</strong>."
151
+ msgstr "Snippets sélectionnés <strong>supprimés</strong>. "
152
+
153
+ #: includes/admin/manage.php:38 includes/admin/single.php:42
154
+ msgctxt "snippet"
155
+ msgid "Add New"
156
+ msgstr "Ajouter "
157
+
158
+ #: includes/admin/manage.php:47
159
+ msgid "Search Installed Snippets"
160
+ msgstr "Chercher dans les Snippets installés"
161
+
162
+ #: includes/admin/single.php:22
163
+ msgid "Please provide a name for the snippet and its code."
164
+ msgstr "Veuillez indiauer un nom ainsi que le code pour ce Snippet. "
165
+
166
+ #: includes/admin/single.php:28
167
+ msgid "Snippet <strong>updated</strong>."
168
+ msgstr "Snippet <strong>mis à jour</strong>."
169
+
170
+ #: includes/admin/single.php:30
171
+ msgid "Snippet <strong>added</strong>."
172
+ msgstr "Snippet <strong>ajouté</strong>."
173
+
174
+ #: includes/admin/single.php:55 includes/admin/single.php:56
175
+ msgid "Name (short title)"
176
+ msgstr "Nom (titre court) "
177
+
178
+ #: includes/admin/single.php:61
179
+ msgid "Code"
180
+ msgstr "Code"
181
+
182
+ #: code-snippets.php:1433 includes/class-list-table.php:189
183
+ msgid "Description"
184
+ msgstr "Description"
185
+
186
+ #: code-snippets.php:1434
187
+ msgid "(Optional)"
188
+ msgstr "(Option)"
189
+
190
+ #: includes/class-list-table.php:36
191
+ msgid "Snippets per page"
192
+ msgstr "Snippets par page "
193
+
194
+ #: code-snippets.php:1118 includes/class-list-table.php:127
195
+ #: includes/class-list-table.php:213
196
+ msgid "Network Deactivate"
197
+ msgstr "Désactiver réseau "
198
+
199
+ #: code-snippets.php:1118 includes/class-list-table.php:127
200
+ #: includes/class-list-table.php:213
201
+ msgid "Deactivate"
202
+ msgstr "Désactiver "
203
+
204
+ #: code-snippets.php:1127 includes/class-list-table.php:137
205
+ #: includes/class-list-table.php:212
206
+ msgid "Network Activate"
207
+ msgstr "Activer réseau "
208
+
209
+ #: code-snippets.php:1127 includes/class-list-table.php:137
210
+ #: includes/class-list-table.php:212
211
+ msgid "Activate"
212
+ msgstr "Activer"
213
+
214
+ #: includes/class-list-table.php:187
215
+ msgid "Name"
216
+ msgstr "Nom"
217
+
218
+ #: includes/class-list-table.php:188
219
+ msgid "ID"
220
+ msgstr "ID"
221
+
222
+ #: includes/class-list-table.php:147 includes/class-list-table.php:214
223
+ msgid "Export"
224
+ msgstr "Exporter"
225
+
226
+ #: includes/class-list-table.php:155 includes/class-list-table.php:215
227
+ msgid "Delete"
228
+ msgstr "Supprimer"
229
+
230
+ #: includes/class-list-table.php:216
231
+ msgid "Export to PHP"
232
+ msgstr "Export en PHP"
233
+
234
+ #: includes/class-list-table.php:236
235
+ msgid "All <span class=\"count\">(%s)</span>"
236
+ msgid_plural "All <span class=\"count\">(%s)</span>"
237
+ msgstr[0] "Tout <span class=\"count\">(%s)</span>"
238
+ msgstr[1] "Tout <span class=\"count\">(%s)</span>"
239
+
240
+ #: includes/class-list-table.php:239
241
+ msgid "Active <span class=\"count\">(%s)</span>"
242
+ msgid_plural "Active <span class=\"count\">(%s)</span>"
243
+ msgstr[0] "Activer <span class=\"count\">(%s)</span>"
244
+ msgstr[1] "Activer <span class=\"count\">(%s)</span>"
245
+
246
+ #: includes/class-list-table.php:242
247
+ msgid "Recently Active <span class=\"count\">(%s)</span>"
248
+ msgid_plural "Recently Active <span class=\"count\">(%s)</span>"
249
+ msgstr[0] "Récemment activé <span class=\"count\">(%s)</span>"
250
+ msgstr[1] "Récemment activés <span class=\"count\">(%s)</span>"
251
+
252
+ #: includes/class-list-table.php:245
253
+ msgid "Inactive <span class=\"count\">(%s)</span>"
254
+ msgid_plural "Inactive <span class=\"count\">(%s)</span>"
255
+ msgstr[0] "Inactif <span class=\"count\">(%s)</span>"
256
+ msgstr[1] "Inactifs <span class=\"count\">(%s)</span>"
257
+
258
+ #: includes/class-list-table.php:279
259
+ msgid "Clear List"
260
+ msgstr "Vider la liste"
261
+
262
+ #: includes/class-list-table.php:374
263
+ msgid ""
264
+ "You do not appear to have any snippets available at this time. <a href=\"%s"
265
+ "\">Add New&rarr;</a>"
266
+ msgstr "Aucun Snippet pour l'instant. <a href=\"%s\">En ajouter un&rarr;</a>"
267
+
268
+ #: includes/help/import.php:5 includes/help/manage.php:5
269
+ #: includes/help/single.php:5
270
+ msgid "Overview"
271
+ msgstr "Présentation "
272
+
273
+ #: includes/help/import.php:7
274
+ msgid ""
275
+ "Snippets are similar to plugins - they both extend and expand the "
276
+ "functionality of WordPress. Snippets are more light-weight, just a few lines "
277
+ "of code, and do not put as much load on your server. Here you can load "
278
+ "snippets from a Code Snippets (.xml) import file into the database with your "
279
+ "existing snippets."
280
+ msgstr ""
281
+ "Les Snippets sont similaires aux plugins. Ils permettent aussi d'étendre les "
282
+ "fonctionnalités de WordPress. Les Snippets sont plus légers, juste quelques "
283
+ "lignes de code : cela permet à votre site de se charger plus rapidement. "
284
+ "Vous pouvez en charger plusieurs en important un fichier de Snippets (.xml)."
285
+
286
+ #: includes/help/import.php:12
287
+ msgid "Importing"
288
+ msgstr "Importation"
289
+
290
+ #: includes/help/import.php:15
291
+ msgid ""
292
+ "Snippets will be added to the database along with your existing snippets. "
293
+ "Regardless of whether the snippets were active on the previous site, "
294
+ "imported snippets are always inactive until activated using the <a href=\"%s"
295
+ "\">Manage Snippets</a> page.</p>"
296
+ msgstr ""
297
+ "Les Snippets seront ajoutés à votre base de données, en plus de ceux déjà "
298
+ "existants. Tous les Snippets importés seront inactifs, même si lors de "
299
+ "l'export précédent ils étaient actifs. Il vous restera à les <a href=\"%s"
300
+ "\">activer</a> ensuite.</p>"
301
+
302
+ #: includes/help/import.php:20
303
+ msgid "Exporting"
304
+ msgstr "Exportation"
305
+
306
+ #: includes/help/import.php:22
307
+ msgid ""
308
+ "You can save your snippets to a Code Snippets (.xml) export file using the "
309
+ "<a href=\"%s\">Manage Snippets</a> page."
310
+ msgstr ""
311
+ "Vous pouvez sauvegarder vos Snippets dans un fichier de Codes (.xml) en les "
312
+ "<a href=\"%s\">exportant</a> ."
313
+
314
+ #: includes/help/import.php:26 includes/help/manage.php:27
315
+ #: includes/help/single.php:31
316
+ msgid "For more information:"
317
+ msgstr "Pour plus d'informations : "
318
+
319
+ #: includes/help/import.php:27 includes/help/single.php:32
320
+ msgid ""
321
+ "<a href=\"http://wordpress.org/plugins/code-snippets\" target=\"_blank"
322
+ "\">WordPress Extend</a>"
323
+ msgstr ""
324
+ "<a href=\"http://wordpress.org/plugins/code-snippets\" target=\"_blank"
325
+ "\">WordPress Extend</a>"
326
+
327
+ #: includes/help/import.php:28 includes/help/manage.php:29
328
+ #: includes/help/single.php:33
329
+ msgid ""
330
+ "<a href=\"http://wordpress.org/support/plugin/code-snippets\" target=\"_blank"
331
+ "\">Support Forums</a>"
332
+ msgstr ""
333
+ "<a href=\"http://wordpress.org/support/plugin/code-snippets\" target=\"_blank"
334
+ "\">Support Forums</a>"
335
+
336
+ #: includes/help/manage.php:7
337
+ msgid ""
338
+ "Snippets are similar to plugins - they both extend and expand the "
339
+ "functionality of WordPress. Snippets are more light-weight, just a few lines "
340
+ "of code, and do not put as much load on your server. Here you can manage "
341
+ "your existing snippets and preform tasks on them such as activating, "
342
+ "deactivating, deleting and exporting."
343
+ msgstr ""
344
+ "Les Snippets sont similaires au Plugins. Les deux permettent d'étendre les "
345
+ "fonctionnalités de WordPress. Les Snippets sont plus légers et permettent, "
346
+ "avec quelques lignes de code, de rendre votre site plus rapide. Ici vous "
347
+ "avez la possibilité de gérer vos portions de code, automatiser des tâches, "
348
+ "en activant, désactivant, supprimant et exportant. "
349
+
350
+ #: includes/help/manage.php:12
351
+ msgid "Safe Mode"
352
+ msgstr "Mode sécurité "
353
+
354
+ #: includes/help/manage.php:14
355
+ msgid ""
356
+ "Be sure to check your snippets for errors before you activate them, as a "
357
+ "faulty snippet could bring your whole blog down. If your site starts doing "
358
+ "strange things, deactivate all your snippets and activate them one at a time."
359
+ msgstr ""
360
+ "Veuillez bien vérifier vos Snippets avant de les activer. Si la syntaxe "
361
+ "n'est pas correcte, il est possible de rendre votre site inaccessible. Si "
362
+ "vous découvrez des comportements bizarres sur votre site, désactivez tous "
363
+ "vos Snippets, puis activez-les un par un."
364
+
365
+ #: includes/help/manage.php:20
366
+ msgid "Uninstall"
367
+ msgstr "Désinstaller"
368
+
369
+ #: includes/help/manage.php:22
370
+ msgid ""
371
+ "When you delete Code Snippets through the Plugins menu in WordPress it will "
372
+ "clear up the <code>%1$s</code> table and a few other bits of data stored in "
373
+ "the database. If you want to keep this data (ie: you are only temporally "
374
+ "uninstalling Code Snippets) then remove the <code>%2$s</code> folder using "
375
+ "FTP."
376
+ msgstr ""
377
+ "Si vous désinstallez Code Snippets depuis le menu Plugins de votre "
378
+ "installation WordPress, la table <code>%1$s</code> contenant les portions de "
379
+ "code sera supprimée de la base de données. Si vous voulez conserver les "
380
+ "données (par exemple : désinstaller temporairement Code Snippets) supprimez "
381
+ "le dossier <code>%2$s</code> via votre client FTP."
382
+
383
+ #: includes/help/manage.php:23
384
+ msgid ""
385
+ "Even if you're sure that you don't want to use Code Snippets ever again on "
386
+ "this WordPress installation, you may want to use the export feature to back "
387
+ "up your snippets."
388
+ msgstr ""
389
+ "Même si vous êtes certain(e) de ne plus vouloir utiliser Code Snippets avec "
390
+ "cette installation de WordPress, vous pouvez exporter vos Snippets."
391
+
392
+ #: includes/help/manage.php:28
393
+ msgid ""
394
+ "<a href=\"http://wordpress.org/plugins/code-snippets\" target=\"_blank"
395
+ "\">WordPress Extend</a></p>"
396
+ msgstr ""
397
+ "<a href=\"http://wordpress.org/plugins/code-snippets\" target=\"_blank"
398
+ "\">WordPress Extend</a></p>"
399
+
400
+ #: includes/help/single.php:7
401
+ msgid ""
402
+ "Snippets are similar to plugins - they both extend and expand the "
403
+ "functionality of WordPress. Snippets are more light-weight, just a few lines "
404
+ "of code, and do not put as much load on your server. Here you can add a new "
405
+ "snippet, or edit an existing one."
406
+ msgstr ""
407
+ "Les Snippets sont similaires aux plugins. Ils permettent aussi d'étendre les "
408
+ "fonctionnalités de WordPress. Les Snippets sont plus légers, juste quelques "
409
+ "lignes de code : cela permet à votre site de se charger plus rapidement. "
410
+ "Ici, vous pouvez en ajouter ou en éditer."
411
+
412
+ #: includes/help/single.php:11
413
+ msgid "Finding Snippets"
414
+ msgstr "Trouver des Snippets"
415
+
416
+ #: includes/help/single.php:13
417
+ msgid ""
418
+ "Here are some links to websites which host a large number of snippets that "
419
+ "you can add to your site.\n"
420
+ "\t\t<ul>\n"
421
+ "\t\t\t<li><a href=\"http://wp-snippets.com\" title=\"WordPress Snippets\">WP-"
422
+ "Snippets</a></li>\n"
423
+ "\t\t\t<li><a href=\"http://wpsnipp.com\" title=\"WP Snipp\">WP Snipp</a></"
424
+ "li>\n"
425
+ "\t\t\t<li><a href=\"http://www.catswhocode.com/blog/snippets\" title=\"Cats "
426
+ "Who Code Snippet Library\">Cats Who Code</a></li>\n"
427
+ "\t\t\t<li><a href=\"http://www.wpfunction.me\">WP Function Me</a></li>\n"
428
+ "\t\t</ul>"
429
+ msgstr ""
430
+ "Voici quelques liens vers des sites qui proposent une large panoplie de "
431
+ "Snippets que vous pouvez ajouter à votre installation.\n"
432
+ "\t\t<ul>\n"
433
+ "\t\t\t<li><a href=\"http://wp-snippets.com\" title=\"WordPress Snippets\">WP-"
434
+ "Snippets</a></li>\n"
435
+ "\t\t\t<li><a href=\"http://wpsnipp.com\" title=\"WP Snipp\">WP Snipp</a></"
436
+ "li>\n"
437
+ "\t\t\t<li><a href=\"http://www.catswhocode.com/blog/snippets\" title=\"Cats "
438
+ "Who Code Snippet Library\">Cats Who Code</a></li>\n"
439
+ "\t\t\t<li><a href=\"http://www.wpfunction.me\">WP Function Me</a></li>\n"
440
+ "\t\t</ul>"
441
+
442
+ #: includes/help/single.php:24
443
+ msgid "Adding Snippets"
444
+ msgstr "Ajout de Snippets"
445
+
446
+ #: includes/help/single.php:26
447
+ msgid ""
448
+ "You need to fill out the name and code fields for your snippet to be added. "
449
+ "While the description field will add more information about how your snippet "
450
+ "works, what is does and where you found it, it is completely optional."
451
+ msgstr ""
452
+ "Vous devez remplir les champs Nom et Code pour ajouter un Snippet. Le champ "
453
+ "description permet d'ajouter des informations sur la fonction ajoutée : "
454
+ "utilité, où vous l'avez trouvé. C'est une option de confort."
455
+
456
+ #: includes/help/single.php:27
457
+ msgid ""
458
+ "Please be sure to check that your snippet is valid PHP code and will not "
459
+ "produce errors before adding it through this page. While doing so will not "
460
+ "become active straight away, it will help to minimise the chance of a faulty "
461
+ "snippet becoming active on your site."
462
+ msgstr ""
463
+ "Veuillez vérifier le code PHP de votre Snippet. En vérifiant le code avant "
464
+ "d'activer le Snippet, vous vous assurerez que vous ne mettrez en danger "
465
+ "votre installation."
466
+
467
+ #: code-snippets.php:0
468
+ msgid "http://code-snippets.bungeshea.com"
469
+ msgstr "http://code-snippets.bungeshea.com"
470
+
471
+ #: code-snippets.php:263
472
+ msgid "Import snippets from a <strong>Code Snippets</strong> export file"
473
+ msgstr ""
474
+ "Importer des Snippets depuis un fichier <strong>Code Snippets</strong> "
475
+ "exporté préalablement. "
476
+
477
+ #: includes/admin/import.php:20
478
+ msgid "Imported <strong>%d</strong> snippet."
479
+ msgid_plural "Imported <strong>%d</strong> snippets."
480
+ msgstr[0] "Snippet <strong>%d</strong> importé."
481
+ msgstr[1] "Snippets <strong>%d</strong> importés."
482
+
483
+ #: includes/help/import.php:29 includes/help/manage.php:30
484
+ #: includes/help/single.php:34
485
+ msgid ""
486
+ "<a href=\"http://code-snippets.bungeshea.com/\" target=\"_blank\">Project "
487
+ "Website</a>"
488
+ msgstr ""
489
+ "<a href=\"http://code-snippets.bungeshea.com/\" target=\"_blank\">Site du "
490
+ "Projet</a>"
491
+
492
+ #: includes/help/manage.php:15
493
+ msgid ""
494
+ "If something goes wrong with a snippet and you can't use WordPress, you can "
495
+ "cause all snippets to stop executing by adding <code>define"
496
+ "('CODE_SNIPPETS_SAFE_MODE', true);</code> to your <code>wp-config.php</code> "
497
+ "file. After you have deactivated the offending snippet, you can turn off "
498
+ "safe mode by removing this line or replacing <strong>true</strong> with "
499
+ "<strong>false</strong>."
500
+ msgstr ""
501
+ "Si un problème survient suite à l'activation d'un Snippet et que votre "
502
+ "installation WordPress ne fonctionne plus, vous pouvez stopper l'activation "
503
+ "de tous les Snippets en ajoutant <code>define('CODE_SNIPPETS_SAFE_MODE', "
504
+ "true);</code> dans votre fichier <code>wp-config.php</code>. Vous pourrez "
505
+ "alors désactiver le Snippet qui pose problème, puis désactiver le mode "
506
+ "sécurité en retirant la ligne <code>define('CODE_SNIPPETS_SAFE_MODE', true);"
507
+ "</code> dans votre fichier <code>wp-config.php</code> ou alors changer "
508
+ "<strong>true</strong> par <strong>false</strong>."
509
+
510
+ #: includes/help/single.php:20
511
+ msgid ""
512
+ "More places to find snippets, as well as a selection of example snippets, "
513
+ "can be found in the <a href=\"http://code-snippets.bungeshea.com/docs/"
514
+ "finding-snippets/\">plugin documentation</a>"
515
+ msgstr ""
516
+ "Vous trouverez une collection de Snippets, ou des exemples sur la page de <a "
517
+ "href=\"http://code-snippets.bungeshea.com/docs/finding-snippets/"
518
+ "\">documentation</a> du plugin. "
519
+
520
+ #: code-snippets.php:0
521
+ msgid "1.7"
522
+ msgstr "1.7"
523
+
524
+ #: code-snippets.php:602 includes/class-list-table.php:142
525
+ msgid "Edit"
526
+ msgstr "Editer"
527
+
528
+ #: code-snippets.php:1227
529
+ msgid "Sorry, you're not allowed to edit snippets"
530
+ msgstr "Désolé, vous n'êtes pas autorisé à éditer les Snippets "
531
+
532
+ #: includes/admin/single.php:24
533
+ msgid "Snippet <strong>updated</strong> and <strong>activated</strong>."
534
+ msgstr "Snippet <strong>mis à jour</strong> et <strong>activé</strong>."
535
+
536
+ #: includes/admin/single.php:26
537
+ msgid "Snippet <strong>added</strong> and <strong>activated</strong>."
538
+ msgstr "Snippet <strong>ajouté</strong> et <strong>activaté</strong>."
539
+
540
+ #: includes/class-list-table.php:163
541
+ msgid ""
542
+ "You are about to permanently delete the selected item.\n"
543
+ "\t\t\t\t'Cancel' to stop, 'OK' to delete."
544
+ msgstr ""
545
+ "Vous allez supprimer définitivement la sélection.\n"
546
+ "\t\t\t\t'Cancel' pour annuler, 'OK' confirmer et supprimer."
547
+
548
+ #: includes/class-list-table.php:270
549
+ msgid "Filter"
550
+ msgstr "Filtre "
551
+
552
+ #: includes/class-list-table.php:541
553
+ msgid "Search results"
554
+ msgstr "Résultats de la recherche "
555
+
556
+ #: includes/class-list-table.php:544
557
+ msgid " for &#8220;%s&#8221;"
558
+ msgstr " pour &#8220;%s&#8221;"
559
+
560
+ #: includes/class-list-table.php:550
561
+ msgid "Clear Filters"
562
+ msgstr "Annuler les filtres "
563
+
564
+ #: includes/help/import.php:14
565
+ msgid ""
566
+ "You can load your snippets from a code snippets (.xml) export file using "
567
+ "this page."
568
+ msgstr ""
569
+ "Vous pouvez charger vos Snippets depuis un fichier Code Snippets (.xml) "
570
+ "depuis cette page."
571
+
572
+ #: includes/admin/single.php:74
573
+ msgid "Save Changes &amp; Activate"
574
+ msgstr "Enregistrer &amp; Activer"
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: bungeshea
3
  Donate link: http://code-snippets.bungeshea.com/donate/
4
  Tags: code-snippets, snippets, code, php, network, multisite
5
  Requires at least: 3.3
6
- Tested up to: 3.6
7
- Stable tag: 1.8.1
8
  License: MIT
9
  License URI: license.txt
10
 
@@ -63,6 +63,16 @@ Yes. Just add it but do not activate it yet.
63
  = How can I insert my snippet into the post text editor? =
64
  Snippets that you add to this plugin are not meant to be inserted into the text editor. Instead, they are run on your site just as if they were added to your functions.php file.
65
 
 
 
 
 
 
 
 
 
 
 
66
  = What do I use to write my snippets? =
67
  The [CodeMirror](http://codemirror.net) source-code editor will add line numbers, syntax highlighting, bracket matching, search, tabulate and other cool features to the code editor.
68
 
@@ -111,8 +121,29 @@ That's fantastic! Join me on [GitHub](https://github.com/bungeshea/code-snippets
111
 
112
  == Changelog ==
113
 
114
- = 1.8.1.1 =
 
115
  * Updated MP6 icon implementation
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  = 1.8.1 =
118
  * Compiled all CodeMirror scripts into a single file
@@ -231,9 +262,6 @@ Plugin updates will be posted on the [plugin's homepage](http://code-snippets.bu
231
 
232
  == Upgrade Notice ==
233
 
234
- = 1.8.1.1 =
235
- Updated MP6 icon implementation
236
-
237
  = 1.8.1 =
238
  Minimize CSS and JS; updated CodeMirror; fixed export files
239
 
3
  Donate link: http://code-snippets.bungeshea.com/donate/
4
  Tags: code-snippets, snippets, code, php, network, multisite
5
  Requires at least: 3.3
6
+ Tested up to: 3.7.1
7
+ Stable tag: 1.9
8
  License: MIT
9
  License URI: license.txt
10
 
63
  = How can I insert my snippet into the post text editor? =
64
  Snippets that you add to this plugin are not meant to be inserted into the text editor. Instead, they are run on your site just as if they were added to your functions.php file.
65
 
66
+ = Where did the Import menu go after upgrading to version 1.6? =
67
+ As the import menu is not accessed neatly as much as the manage or add new menus, it has been moved under the *Tools > Import* menu. To access the import page, visit the *Tools > Import* menu in your WordPress dashboard and click on the **Code Snippets** link.
68
+
69
+ = Help! I just activated a snippet, and my whole site broke! =
70
+ You can try activating 'safe mode'. All snippets will not execute while safe mode is active, allowing you to access your site and deactivate the snippet that is causing the error. To activate safe mode, add the following line to your wp-config.php file, just before the line that reads `/* That's all, stop editing! Happy blogging. */`:
71
+
72
+ define('CODE_SNIPPETS_SAFE_MODE', true);
73
+
74
+ To turn safe mode off, either [comment out](http://php.net/manual/language.basic-syntax.comments.php) this line or delete it.
75
+
76
  = What do I use to write my snippets? =
77
  The [CodeMirror](http://codemirror.net) source-code editor will add line numbers, syntax highlighting, bracket matching, search, tabulate and other cool features to the code editor.
78
 
121
 
122
  == Changelog ==
123
 
124
+ = 1.9 =
125
+ * Add and remove network capabilities as super admins are added and removed
126
  * Updated MP6 icon implementation
127
+ * Replaced buggy trim `<?php` and `?>` functionality with a much more reliable regex method ([#](http://wordpress.org/support/topic/character-gets-cut))
128
+ * Added French translation thanks to translator [oWEB](http://office-web.net)
129
+ * Fixed snippet failing to save when code contains `%` character, props to [nikan06](http://wordpress.org/support/profile/nikan06) ([#](http://wordpress.org/support/topic/percent-sign-bug))
130
+ * Added 'Save & Deactivate' button to the edit snippet page ([#](http://wordpress.org/support/topic/deactivate-button-in-edit-snippet-page))
131
+ * Removed edit and install capabilities (now only uses the manage capability)
132
+ * Fixed HTML breaking in export files ([#](http://wordpress.org/support/topic/import-problem-7))
133
+ * Make the title of each snippet on the manage page a clickable link to edit the snippet ([#](http://wordpress.org/support/topic/deactivate-button-in-edit-snippet-page?replies=9#post-4682757))
134
+ * Added nonce to edit snippet page
135
+ * Hide row actions on manage snippet page by default
136
+ * Removed screenshots from plugin
137
+ * Improved CodeMirror implementation
138
+ * Added a fallback MP6 icon
139
+ * Use the proper WordPress database APIs all of the time
140
+ * Rewritten export functionality
141
+ * Fixed incorrect export filename
142
+ * Updated CodeMirror to version 3.19
143
+ * Removed CodeMirror bundled with plugin
144
+ * Updated WordPress.org plugin banner
145
+ * Fixed CodeMirror incompatibility with the WP Editor plugin
146
+ * Fixed CodeMirror incompatibility with the Debug Bar Console plugin
147
 
148
  = 1.8.1 =
149
  * Compiled all CodeMirror scripts into a single file
262
 
263
  == Upgrade Notice ==
264
 
 
 
 
265
  = 1.8.1 =
266
  Minimize CSS and JS; updated CodeMirror; fixed export files
267
 
screenshot-1.png DELETED
Binary file
screenshot-2.png DELETED
Binary file
screenshot-3.png DELETED
Binary file
screenshot-4.png DELETED
Binary file
screenshot-5.png DELETED
Binary file
vendor/codemirror.min.js DELETED
@@ -1,5 +0,0 @@
1
- window.CodeMirror=function(){"use strict";function a(c,d){if(!(this instanceof a))return new a(c,d);this.options=d=d||{};for(var e in cf)!d.hasOwnProperty(e)&&cf.hasOwnProperty(e)&&(d[e]=cf[e]);m(d);var f="string"==typeof d.value?0:d.value.first,g=this.display=b(c,f);g.wrapper.CodeMirror=this,j(this),d.autofocus&&!Ke&&nb(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,draggingText:!1,highlight:new Sd},h(this),d.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap");var i=d.value;"string"==typeof i&&(i=new rf(d.value,d.mode)),fb(this,jd)(this,i),xe&&setTimeout(_d(mb,this,!0),20),pb(this);var k;try{k=document.activeElement==g.input}catch(l){}k||d.autofocus&&!Ke?setTimeout(_d(Fb,this),20):Gb(this),fb(this,function(){for(var a in bf)bf.propertyIsEnumerable(a)&&bf[a](this,d[a],df);for(var b=0;b<hf.length;++b)hf[b](this)})()}function b(a,b){var c={},d=c.input=ce("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");return Ae?d.style.width="1000px":d.setAttribute("wrap","off"),Je&&(d.style.border="1px solid black"),d.setAttribute("autocorrect","off"),d.setAttribute("autocapitalize","off"),d.setAttribute("spellcheck","false"),c.inputDiv=ce("div",[d],null,"overflow: hidden; position: relative; width: 3px; height: 0px;"),c.scrollbarH=ce("div",[ce("div",null,null,"height: 1px")],"CodeMirror-hscrollbar"),c.scrollbarV=ce("div",[ce("div",null,null,"width: 1px")],"CodeMirror-vscrollbar"),c.scrollbarFiller=ce("div",null,"CodeMirror-scrollbar-filler"),c.gutterFiller=ce("div",null,"CodeMirror-gutter-filler"),c.lineDiv=ce("div",null,"CodeMirror-code"),c.selectionDiv=ce("div",null,null,"position: relative; z-index: 1"),c.cursor=ce("div"," ","CodeMirror-cursor"),c.otherCursor=ce("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"),c.measure=ce("div",null,"CodeMirror-measure"),c.lineSpace=ce("div",[c.measure,c.selectionDiv,c.lineDiv,c.cursor,c.otherCursor],null,"position: relative; outline: none"),c.mover=ce("div",[ce("div",[c.lineSpace],"CodeMirror-lines")],null,"position: relative"),c.sizer=ce("div",[c.mover],"CodeMirror-sizer"),c.heightForcer=ce("div",null,null,"position: absolute; height: "+wf+"px; width: 1px;"),c.gutters=ce("div",null,"CodeMirror-gutters"),c.lineGutter=null,c.scroller=ce("div",[c.sizer,c.heightForcer,c.gutters],"CodeMirror-scroll"),c.scroller.setAttribute("tabIndex","-1"),c.wrapper=ce("div",[c.inputDiv,c.scrollbarH,c.scrollbarV,c.scrollbarFiller,c.gutterFiller,c.scroller],"CodeMirror"),ye&&(c.gutters.style.zIndex=-1,c.scroller.style.paddingRight=0),a.appendChild?a.appendChild(c.wrapper):a(c.wrapper),Je&&(d.style.width="0px"),Ae||(c.scroller.draggable=!0),Fe?(c.inputDiv.style.height="1px",c.inputDiv.style.position="absolute"):ye&&(c.scrollbarH.style.minWidth=c.scrollbarV.style.minWidth="18px"),c.viewOffset=c.lastSizeC=0,c.showingFrom=c.showingTo=b,c.lineNumWidth=c.lineNumInnerWidth=c.lineNumChars=null,c.prevInput="",c.alignWidgets=!1,c.pollingFast=!1,c.poll=new Sd,c.cachedCharWidth=c.cachedTextHeight=null,c.measureLineCache=[],c.measureLineCachePos=0,c.inaccurateSelection=!1,c.maxLine=null,c.maxLineLength=0,c.maxLineChanged=!1,c.wheelDX=c.wheelDY=c.wheelStartX=c.wheelStartY=null,c}function c(b){b.doc.mode=a.getMode(b.options,b.doc.modeOption),b.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),b.doc.frontier=b.doc.first,G(b,100),b.state.modeGen++,b.curOp&&ib(b)}function d(a){a.options.lineWrapping?(a.display.wrapper.className+=" CodeMirror-wrap",a.display.sizer.style.minWidth=""):(a.display.wrapper.className=a.display.wrapper.className.replace(" CodeMirror-wrap",""),l(a)),f(a),ib(a),T(a),setTimeout(function(){n(a)},100)}function e(a){var b=bb(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/cb(a.display)-3);return function(e){return Nc(a.doc,e)?0:c?(Math.ceil(e.text.length/d)||1)*b:b}}function f(a){var b=a.doc,c=e(a);b.iter(function(a){var b=c(a);b!=a.height&&nd(a,b)})}function g(a){var b=lf[a.options.keyMap],c=b.style;a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-keymap-\S+/g,"")+(c?" cm-keymap-"+c:""),a.state.disableInput=b.disableInput}function h(a){a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+a.options.theme.replace(/(^|\s)\s*/g," cm-s-"),T(a)}function i(a){j(a),ib(a),setTimeout(function(){p(a)},20)}function j(a){var b=a.display.gutters,c=a.options.gutters;de(b);for(var d=0;d<c.length;++d){var e=c[d],f=b.appendChild(ce("div",null,"CodeMirror-gutter "+e));"CodeMirror-linenumbers"==e&&(a.display.lineGutter=f,f.style.width=(a.display.lineNumWidth||1)+"px")}b.style.display=d?"":"none"}function k(a,b){if(0==b.height)return 0;for(var c,d=b.text.length,e=b;c=Kc(e);){var f=c.find();e=kd(a,f.from.line),d+=f.from.ch-f.to.ch}for(e=b;c=Lc(e);){var f=c.find();d-=e.text.length-f.from.ch,e=kd(a,f.to.line),d+=e.text.length-f.to.ch}return d}function l(a){var b=a.display,c=a.doc;b.maxLine=kd(c,c.first),b.maxLineLength=k(c,b.maxLine),b.maxLineChanged=!0,c.iter(function(a){var d=k(c,a);d>b.maxLineLength&&(b.maxLineLength=d,b.maxLine=a)})}function m(a){for(var b=!1,c=0;c<a.gutters.length;++c)"CodeMirror-linenumbers"==a.gutters[c]&&(a.lineNumbers?b=!0:a.gutters.splice(c--,1));!b&&a.lineNumbers&&a.gutters.push("CodeMirror-linenumbers")}function n(a){var b=a.display,c=a.doc.height,d=c+L(b);b.sizer.style.minHeight=b.heightForcer.style.top=d+"px",b.gutters.style.height=Math.max(d,b.scroller.clientHeight-wf)+"px";var e=Math.max(d,b.scroller.scrollHeight),f=b.scroller.scrollWidth>b.scroller.clientWidth+1,g=e>b.scroller.clientHeight+1;g?(b.scrollbarV.style.display="block",b.scrollbarV.style.bottom=f?ie(b.measure)+"px":"0",b.scrollbarV.firstChild.style.height=e-b.scroller.clientHeight+b.scrollbarV.clientHeight+"px"):b.scrollbarV.style.display="",f?(b.scrollbarH.style.display="block",b.scrollbarH.style.right=g?ie(b.measure)+"px":"0",b.scrollbarH.firstChild.style.width=b.scroller.scrollWidth-b.scroller.clientWidth+b.scrollbarH.clientWidth+"px"):b.scrollbarH.style.display="",f&&g?(b.scrollbarFiller.style.display="block",b.scrollbarFiller.style.height=b.scrollbarFiller.style.width=ie(b.measure)+"px"):b.scrollbarFiller.style.display="",f&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(b.gutterFiller.style.display="block",b.gutterFiller.style.height=ie(b.measure)+"px",b.gutterFiller.style.width=b.gutters.offsetWidth+"px"):b.gutterFiller.style.display="",Ge&&0===ie(b.measure)&&(b.scrollbarV.style.minWidth=b.scrollbarH.style.minHeight=He?"18px":"12px")}function o(a,b,c){var d=a.scroller.scrollTop,e=a.wrapper.clientHeight;"number"==typeof c?d=c:c&&(d=c.top,e=c.bottom-c.top),d=Math.floor(d-K(a));var f=Math.ceil(d+e);return{from:pd(b,d),to:pd(b,f)}}function p(a){var b=a.display;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var c=s(b)-b.scroller.scrollLeft+a.doc.scrollLeft,d=b.gutters.offsetWidth,e=c+"px",f=b.lineDiv.firstChild;f;f=f.nextSibling)if(f.alignable)for(var g=0,h=f.alignable;g<h.length;++g)h[g].style.left=e;a.options.fixedGutter&&(b.gutters.style.left=c+d+"px")}}function q(a){if(!a.options.lineNumbers)return!1;var b=a.doc,c=r(a.options,b.first+b.size-1),d=a.display;if(c.length!=d.lineNumChars){var e=d.measure.appendChild(ce("div",[ce("div",c)],"CodeMirror-linenumber CodeMirror-gutter-elt")),f=e.firstChild.offsetWidth,g=e.offsetWidth-f;return d.lineGutter.style.width="",d.lineNumInnerWidth=Math.max(f,d.lineGutter.offsetWidth-g),d.lineNumWidth=d.lineNumInnerWidth+g,d.lineNumChars=d.lineNumInnerWidth?c.length:-1,d.lineGutter.style.width=d.lineNumWidth+"px",!0}return!1}function r(a,b){return String(a.lineNumberFormatter(b+a.firstLineNumber))}function s(a){return ge(a.scroller).left-ge(a.sizer).left}function t(a,b,c,d){for(var e,f=a.display.showingFrom,g=a.display.showingTo,h=o(a.display,a.doc,c);u(a,b,h,d)&&(d=!1,e=!0,C(a),n(a),c&&(c=Math.min(a.display.scroller.scrollHeight-a.display.scroller.clientHeight,"number"==typeof c?c:c.top)),h=o(a.display,a.doc,c),!(h.from>=a.display.showingFrom&&h.to<=a.display.showingTo));)b=[];return e&&(Nd(a,"update",a),(a.display.showingFrom!=f||a.display.showingTo!=g)&&Nd(a,"viewportChange",a,a.display.showingFrom,a.display.showingTo)),e}function u(a,b,c,d){var e=a.display,f=a.doc;if(!e.wrapper.clientWidth)return e.showingFrom=e.showingTo=f.first,e.viewOffset=0,void 0;if(!(!d&&0==b.length&&c.from>e.showingFrom&&c.to<e.showingTo)){q(a)&&(b=[{from:f.first,to:f.first+f.size}]);var g=e.sizer.style.marginLeft=e.gutters.offsetWidth+"px";e.scrollbarH.style.left=a.options.fixedGutter?g:"0";var h=1/0;if(a.options.lineNumbers)for(var i=0;i<b.length;++i)if(b[i].diff){h=b[i].from;break}var j=f.first+f.size,k=Math.max(c.from-a.options.viewportMargin,f.first),l=Math.min(j,c.to+a.options.viewportMargin);if(e.showingFrom<k&&k-e.showingFrom<20&&(k=Math.max(f.first,e.showingFrom)),e.showingTo>l&&e.showingTo-l<20&&(l=Math.min(j,e.showingTo)),Ue)for(k=od(Mc(f,kd(f,k)));j>l&&Nc(f,kd(f,l));)++l;var m=[{from:Math.max(e.showingFrom,f.first),to:Math.min(e.showingTo,j)}];if(m=m[0].from>=m[0].to?[]:x(m,b),Ue)for(var i=0;i<m.length;++i)for(var n,o=m[i];n=Lc(kd(f,o.to-1));){var p=n.find().from.line;if(!(p>o.from)){m.splice(i--,1);break}o.to=p}for(var r=0,i=0;i<m.length;++i){var o=m[i];o.from<k&&(o.from=k),o.to>l&&(o.to=l),o.from>=o.to?m.splice(i--,1):r+=o.to-o.from}if(!d&&r==l-k&&k==e.showingFrom&&l==e.showingTo)return w(a),void 0;m.sort(function(a,b){return a.from-b.from});try{var s=document.activeElement}catch(t){}.7*(l-k)>r&&(e.lineDiv.style.display="none"),z(a,k,l,m,h),e.lineDiv.style.display="",s&&document.activeElement!=s&&s.offsetHeight&&s.focus();var u=k!=e.showingFrom||l!=e.showingTo||e.lastSizeC!=e.wrapper.clientHeight;return u&&(e.lastSizeC=e.wrapper.clientHeight,G(a,400)),e.showingFrom=k,e.showingTo=l,v(a),w(a),!0}}function v(a){for(var b,c=a.display,d=c.lineDiv.offsetTop,e=c.lineDiv.firstChild;e;e=e.nextSibling)if(e.lineObj){if(ye){var f=e.offsetTop+e.offsetHeight;b=f-d,d=f}else{var g=ge(e);b=g.bottom-g.top}var h=e.lineObj.height-b;if(2>b&&(b=bb(c)),h>.001||-.001>h){nd(e.lineObj,b);var i=e.lineObj.widgets;if(i)for(var j=0;j<i.length;++j)i[j].height=i[j].node.offsetHeight}}}function w(a){var b=a.display.viewOffset=qd(a,kd(a.doc,a.display.showingFrom));a.display.mover.style.top=b+"px"}function x(a,b){for(var c=0,d=b.length||0;d>c;++c){for(var e=b[c],f=[],g=e.diff||0,h=0,i=a.length;i>h;++h){var j=a[h];e.to<=j.from&&e.diff?f.push({from:j.from+g,to:j.to+g}):e.to<=j.from||e.from>=j.to?f.push(j):(e.from>j.from&&f.push({from:j.from,to:e.from}),e.to<j.to&&f.push({from:e.to+g,to:j.to+g}))}a=f}return a}function y(a){for(var b=a.display,c={},d={},e=b.gutters.firstChild,f=0;e;e=e.nextSibling,++f)c[a.options.gutters[f]]=e.offsetLeft,d[a.options.gutters[f]]=e.offsetWidth;return{fixedPos:s(b),gutterTotalWidth:b.gutters.offsetWidth,gutterLeft:c,gutterWidth:d,wrapperWidth:b.wrapper.clientWidth}}function z(a,b,c,d,e){function f(b){var c=b.nextSibling;return Ae&&Le&&a.display.currentWheelTarget==b?(b.style.display="none",b.lineObj=null):b.parentNode.removeChild(b),c}var g=y(a),h=a.display,i=a.options.lineNumbers;d.length||Ae&&a.display.currentWheelTarget||de(h.lineDiv);var j=h.lineDiv,k=j.firstChild,l=d.shift(),m=b;for(a.doc.iter(b,c,function(b){if(l&&l.to==m&&(l=d.shift()),Nc(a.doc,b)){if(0!=b.height&&nd(b,0),b.widgets&&k.previousSibling)for(var c=0;c<b.widgets.length;++c){var h=b.widgets[c];if(h.showIfHidden){var n=k.previousSibling;if(/pre/i.test(n.nodeName)){var o=ce("div",null,null,"position: relative");n.parentNode.replaceChild(o,n),o.appendChild(n),n=o}var p=n.appendChild(ce("div",[h.node],"CodeMirror-linewidget"));h.handleMouseEvents||(p.ignoreEvents=!0),B(h,p,n,g)}}}else if(l&&l.from<=m&&l.to>m){for(;k.lineObj!=b;)k=f(k);i&&m>=e&&k.lineNumber&&fe(k.lineNumber,r(a.options,m)),k=k.nextSibling}else{if(b.widgets)for(var q,s=0,t=k;t&&20>s;++s,t=t.nextSibling)if(t.lineObj==b&&/div/i.test(t.nodeName)){q=t;break}var u=A(a,b,m,g,q);if(u!=q)j.insertBefore(u,k);else{for(;k!=q;)k=f(k);k=k.nextSibling}u.lineObj=b}++m});k;)k=f(k)}function A(a,b,c,d,e){var f,g=_c(a,b),h=b.gutterMarkers,i=a.display;if(!(a.options.lineNumbers||h||b.bgClass||b.wrapClass||b.widgets))return g;if(e){e.alignable=null;for(var j,k=!0,l=0,m=null,n=e.firstChild;n;n=j)if(j=n.nextSibling,/\bCodeMirror-linewidget\b/.test(n.className)){for(var o=0;o<b.widgets.length;++o){var p=b.widgets[o];if(p.node==n.firstChild){p.above||m||(m=n),B(p,n,e,d),++l;break}}if(o==b.widgets.length){k=!1;break}}else e.removeChild(n);e.insertBefore(g,m),k&&l==b.widgets.length&&(f=e,e.className=b.wrapClass||"")}if(f||(f=ce("div",null,b.wrapClass,"position: relative"),f.appendChild(g)),b.bgClass&&f.insertBefore(ce("div",null,b.bgClass+" CodeMirror-linebackground"),f.firstChild),a.options.lineNumbers||h){var q=f.insertBefore(ce("div",null,null,"position: absolute; left: "+(a.options.fixedGutter?d.fixedPos:-d.gutterTotalWidth)+"px"),f.firstChild);if(a.options.fixedGutter&&(f.alignable||(f.alignable=[])).push(q),!a.options.lineNumbers||h&&h["CodeMirror-linenumbers"]||(f.lineNumber=q.appendChild(ce("div",r(a.options,c),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+d.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+i.lineNumInnerWidth+"px"))),h)for(var s=0;s<a.options.gutters.length;++s){var t=a.options.gutters[s],u=h.hasOwnProperty(t)&&h[t];u&&q.appendChild(ce("div",[u],"CodeMirror-gutter-elt","left: "+d.gutterLeft[t]+"px; width: "+d.gutterWidth[t]+"px"))}}if(ye&&(f.style.zIndex=2),b.widgets&&f!=e)for(var o=0,v=b.widgets;o<v.length;++o){var p=v[o],w=ce("div",[p.node],"CodeMirror-linewidget");p.handleMouseEvents||(w.ignoreEvents=!0),B(p,w,f,d),p.above?f.insertBefore(w,a.options.lineNumbers&&0!=b.height?q:g):f.appendChild(w),Nd(p,"redraw")}return f}function B(a,b,c,d){if(a.noHScroll){(c.alignable||(c.alignable=[])).push(b);var e=d.wrapperWidth;b.style.left=d.fixedPos+"px",a.coverGutter||(e-=d.gutterTotalWidth,b.style.paddingLeft=d.gutterTotalWidth+"px"),b.style.width=e+"px"}a.coverGutter&&(b.style.zIndex=5,b.style.position="relative",a.noHScroll||(b.style.marginLeft=-d.gutterTotalWidth+"px"))}function C(a){var b=a.display,c=Tb(a.doc.sel.from,a.doc.sel.to);if(c||a.options.showCursorWhenSelecting?D(a):b.cursor.style.display=b.otherCursor.style.display="none",c?b.selectionDiv.style.display="none":E(a),a.options.moveInputWithCursor){var d=Z(a,a.doc.sel.head,"div"),e=ge(b.wrapper),f=ge(b.lineDiv);b.inputDiv.style.top=Math.max(0,Math.min(b.wrapper.clientHeight-10,d.top+f.top-e.top))+"px",b.inputDiv.style.left=Math.max(0,Math.min(b.wrapper.clientWidth-10,d.left+f.left-e.left))+"px"}}function D(a){var b=a.display,c=Z(a,a.doc.sel.head,"div");b.cursor.style.left=c.left+"px",b.cursor.style.top=c.top+"px",b.cursor.style.height=Math.max(0,c.bottom-c.top)*a.options.cursorHeight+"px",b.cursor.style.display="",c.other?(b.otherCursor.style.display="",b.otherCursor.style.left=c.other.left+"px",b.otherCursor.style.top=c.other.top+"px",b.otherCursor.style.height=.85*(c.other.bottom-c.other.top)+"px"):b.otherCursor.style.display="none"}function E(a){function b(a,b,c,d){0>b&&(b=0),g.appendChild(ce("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px; top: "+b+"px; width: "+(null==c?h-a:c)+"px; height: "+(d-b)+"px"))}function c(c,d,f){function g(b,d){return Y(a,Sb(c,b),"div",l,d)}var j,k,l=kd(e,c),m=l.text.length;return ke(rd(l),d||0,null==f?m:f,function(a,c,e){var l,n,o,p=g(a,"left");if(a==c)l=p,n=o=p.left;else{if(l=g(c-1,"right"),"rtl"==e){var q=p;p=l,l=q}n=p.left,o=l.right}null==d&&0==a&&(n=i),l.top-p.top>3&&(b(n,p.top,null,p.bottom),n=i,p.bottom<l.top&&b(n,p.bottom,null,l.top)),null==f&&c==m&&(o=h),(!j||p.top<j.top||p.top==j.top&&p.left<j.left)&&(j=p),(!k||l.bottom>k.bottom||l.bottom==k.bottom&&l.right>k.right)&&(k=l),i+1>n&&(n=i),b(n,l.top,o-n,l.bottom)}),{start:j,end:k}}var d=a.display,e=a.doc,f=a.doc.sel,g=document.createDocumentFragment(),h=d.lineSpace.offsetWidth,i=M(a.display);if(f.from.line==f.to.line)c(f.from.line,f.from.ch,f.to.ch);else{var j=kd(e,f.from.line),k=kd(e,f.to.line),l=Mc(e,j)==Mc(e,k),m=c(f.from.line,f.from.ch,l?j.text.length:null).end,n=c(f.to.line,l?0:null,f.to.ch).start;l&&(m.top<n.top-2?(b(m.right,m.top,null,m.bottom),b(i,n.top,n.left,n.bottom)):b(m.right,m.top,n.left-m.right,m.bottom)),m.bottom<n.top&&b(i,m.bottom,null,n.top)}ee(d.selectionDiv,g),d.selectionDiv.style.display=""}function F(a){if(a.state.focused){var b=a.display;clearInterval(b.blinker);var c=!0;b.cursor.style.visibility=b.otherCursor.style.visibility="",b.blinker=setInterval(function(){b.cursor.style.visibility=b.otherCursor.style.visibility=(c=!c)?"":"hidden"},a.options.cursorBlinkRate)}}function G(a,b){a.doc.mode.startState&&a.doc.frontier<a.display.showingTo&&a.state.highlight.set(b,_d(H,a))}function H(a){var b=a.doc;if(b.frontier<b.first&&(b.frontier=b.first),!(b.frontier>=a.display.showingTo)){var c,d=+new Date+a.options.workTime,e=qc(b.mode,J(a,b.frontier)),f=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.showingTo+500),function(g){if(b.frontier>=a.display.showingFrom){var h=g.styles;g.styles=Xc(a,g,e);for(var i=!h||h.length!=g.styles.length,j=0;!i&&j<h.length;++j)i=h[j]!=g.styles[j];i&&(c&&c.end==b.frontier?c.end++:f.push(c={start:b.frontier,end:b.frontier+1})),g.stateAfter=qc(b.mode,e)}else Zc(a,g,e),g.stateAfter=0==b.frontier%5?qc(b.mode,e):null;return++b.frontier,+new Date>d?(G(a,a.options.workDelay),!0):void 0}),f.length&&fb(a,function(){for(var a=0;a<f.length;++a)ib(this,f[a].start,f[a].end)})()}}function I(a,b,c){for(var d,e,f=a.doc,g=b,h=b-100;g>h;--g){if(g<=f.first)return f.first;var i=kd(f,g-1);if(i.stateAfter&&(!c||g<=f.frontier))return g;var j=Td(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=g-1,d=j)}return e}function J(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=I(a,b,c),g=f>d.first&&kd(d,f-1).stateAfter;return g=g?qc(d.mode,g):rc(d.mode),d.iter(f,b,function(c){Zc(a,c,g);var h=f==b-1||0==f%5||f>=e.showingFrom&&f<e.showingTo;c.stateAfter=h?qc(d.mode,g):null,++f}),g}function K(a){return a.lineSpace.offsetTop}function L(a){return a.mover.offsetHeight-a.lineSpace.offsetHeight}function M(a){var b=ee(a.measure,ce("pre",null,null,"text-align: left")).appendChild(ce("span","x"));return b.offsetLeft}function N(a,b,c,d,e){var f=-1;d=d||Q(a,b);for(var g=c;;g+=f){var h=d[g];if(h)break;0>f&&0==g&&(f=1)}return e=g>c?"left":c>g?"right":e,"left"==e&&h.leftSide?h=h.leftSide:"right"==e&&h.rightSide&&(h=h.rightSide),{left:c>g?h.right:h.left,right:g>c?h.left:h.right,top:h.top,bottom:h.bottom}}function O(a,b){for(var c=a.display.measureLineCache,d=0;d<c.length;++d){var e=c[d];if(e.text==b.text&&e.markedSpans==b.markedSpans&&a.display.scroller.clientWidth==e.width&&e.classes==b.textClass+"|"+b.bgClass+"|"+b.wrapClass)return e}}function P(a,b){var c=O(a,b);c&&(c.text=c.measure=c.markedSpans=null)}function Q(a,b){var c=O(a,b);if(c)return c.measure;var d=R(a,b),e=a.display.measureLineCache,f={text:b.text,width:a.display.scroller.clientWidth,markedSpans:b.markedSpans,measure:d,classes:b.textClass+"|"+b.bgClass+"|"+b.wrapClass};return 16==e.length?e[++a.display.measureLineCachePos%16]=f:e.push(f),d}function R(a,b){function c(a){var b=a.top-o.top,c=a.bottom-o.top;c>r&&(c=r),0>b&&(b=0);for(var d=p.length-2;d>=0;d-=2){var e=p[d],f=p[d+1];if(!(e>c||b>f)&&(b>=e&&f>=c||e>=b&&c>=f||Math.min(c,f)-Math.max(b,e)>=c-b>>1)){p[d]=Math.min(b,e),p[d+1]=Math.max(c,f);break}}return 0>d&&(d=p.length,p.push(b,c)),{left:a.left-o.left,right:a.right-o.left,top:d,bottom:null}}function d(a){a.bottom=p[a.top+1],a.top=p[a.top]}var e=a.display,f=$d(b.text.length),g=_c(a,b,f,!0);if(xe&&!ye&&!a.options.lineWrapping&&g.childNodes.length>100){for(var h=document.createDocumentFragment(),i=10,j=g.childNodes.length,k=0,l=Math.ceil(j/i);l>k;++k){for(var m=ce("div",null,null,"display: inline-block"),n=0;i>n&&j;++n)m.appendChild(g.firstChild),--j;h.appendChild(m)}g.appendChild(h)}ee(e.measure,g);var o=ge(e.lineDiv),p=[],q=$d(b.text.length),r=g.offsetHeight;ze&&e.measure.first!=g&&ee(e.measure,g);for(var s,k=0;k<f.length;++k)if(s=f[k]){var t=s,u=null;if(/\bCodeMirror-widget\b/.test(s.className)&&s.getClientRects){1==s.firstChild.nodeType&&(t=s.firstChild);var v=t.getClientRects();v.length>1&&(u=q[k]=c(v[0]),u.rightSide=c(v[v.length-1]))}u||(u=q[k]=c(ge(t))),s.measureRight&&(u.right=ge(s.measureRight).left),s.leftSide&&(u.leftSide=c(ge(s.leftSide)))}for(var s,k=0;k<q.length;++k)(s=q[k])&&(d(s),s.leftSide&&d(s.leftSide),s.rightSide&&d(s.rightSide));return q}function S(a,b){var c=!1;if(b.markedSpans)for(var d=0;d<b.markedSpans;++d){var e=b.markedSpans[d];!e.collapsed||null!=e.to&&e.to!=b.text.length||(c=!0)}var f=!c&&O(a,b);if(f)return N(a,b,b.text.length,f.measure,"right").right;var g=_c(a,b,null,!0),h=g.appendChild(je(a.display.measure));return ee(a.display.measure,g),ge(h).right-ge(a.display.lineDiv).left}function T(a){a.display.measureLineCache.length=a.display.measureLineCachePos=0,a.display.cachedCharWidth=a.display.cachedTextHeight=null,a.options.lineWrapping||(a.display.maxLineChanged=!0),a.display.lineNumChars=null}function U(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function V(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function W(a,b,c,d){if(b.widgets)for(var e=0;e<b.widgets.length;++e)if(b.widgets[e].above){var f=Sc(b.widgets[e]);c.top+=f,c.bottom+=f}if("line"==d)return c;d||(d="local");var g=qd(a,b);if("local"==d?g+=K(a.display):g-=a.display.viewOffset,"page"==d||"window"==d){var h=ge(a.display.lineSpace);g+=h.top+("window"==d?0:V());var i=h.left+("window"==d?0:U());c.left+=i,c.right+=i}return c.top+=g,c.bottom+=g,c}function X(a,b,c){if("div"==c)return b;var d=b.left,e=b.top;if("page"==c)d-=U(),e-=V();else if("local"==c||!c){var f=ge(a.display.sizer);d+=f.left,e+=f.top}var g=ge(a.display.lineSpace);return{left:d-g.left,top:e-g.top}}function Y(a,b,c,d,e){return d||(d=kd(a.doc,b.line)),W(a,d,N(a,d,b.ch,null,e),c)}function Z(a,b,c,d,e){function f(b,f){var g=N(a,d,b,e,f?"right":"left");return f?g.left=g.right:g.right=g.left,W(a,d,g,c)}function g(a,b){var c=h[b],d=c.level%2;return a==le(c)&&b&&c.level<h[b-1].level?(c=h[--b],a=me(c)-(c.level%2?0:1),d=!0):a==me(c)&&b<h.length-1&&c.level<h[b+1].level&&(c=h[++b],a=le(c)-c.level%2,d=!1),d&&a==c.to&&a>c.from?f(a-1):f(a,d)}d=d||kd(a.doc,b.line),e||(e=Q(a,d));var h=rd(d),i=b.ch;if(!h)return f(i);var j=se(h,i),k=g(i,j);return null!=If&&(k.other=g(i,If)),k}function $(a,b,c,d){var e=new Sb(a,b);return e.xRel=d,c&&(e.outside=!0),e}function _(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return $(d.first,0,!0,-1);var e=pd(d,c),f=d.first+d.size-1;if(e>f)return $(d.first+d.size-1,kd(d,f).text.length,!0,1);for(0>b&&(b=0);;){var g=kd(d,e),h=ab(a,g,e,b,c),i=Lc(g),j=i&&i.find();if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=j.to.line}}function ab(a,b,c,d,e){function f(d){var e=Z(a,Sb(c,d),"line",b,j);return h=!0,g>e.bottom?e.left-i:g<e.top?e.left+i:(h=!1,e.left)}var g=e-qd(a,b),h=!1,i=2*a.display.wrapper.clientWidth,j=Q(a,b),k=rd(b),l=b.text.length,m=ne(b),n=oe(b),o=f(m),p=h,q=f(n),r=h;if(d>q)return $(c,n,r,1);for(;;){if(k?n==m||n==ue(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);Af.test(b.text.charAt(s));)++s;var u=$(c,s,s==m?p:r,0>t?-1:t?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=ue(b,w,1)}var y=f(w);y>d?(n=w,q=y,(r=h)&&(q+=1e3),l=v):(m=w,o=y,p=h,l-=v)}}function bb(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==Oe){Oe=ce("pre");for(var b=0;49>b;++b)Oe.appendChild(document.createTextNode("x")),Oe.appendChild(ce("br"));Oe.appendChild(document.createTextNode("x"))}ee(a.measure,Oe);var c=Oe.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),de(a.measure),c||1}function cb(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=ce("span","x"),c=ce("pre",[b]);ee(a.measure,c);var d=b.offsetWidth;return d>2&&(a.cachedCharWidth=d),d||10}function db(a){a.curOp={changes:[],forceUpdate:!1,updateInput:null,userSelChange:null,textChanged:null,selectionChanged:!1,cursorActivity:!1,updateMaxLine:!1,updateScrollPos:!1,id:++Ve},vf++||(uf=[])}function eb(a){var b=a.curOp,c=a.doc,d=a.display;if(a.curOp=null,b.updateMaxLine&&l(a),d.maxLineChanged&&!a.options.lineWrapping&&d.maxLine){var e=S(a,d.maxLine);d.sizer.style.minWidth=Math.max(0,e+3+wf)+"px",d.maxLineChanged=!1;var f=Math.max(0,d.sizer.offsetLeft+d.sizer.offsetWidth-d.scroller.clientWidth);f<c.scrollLeft&&!b.updateScrollPos&&xb(a,Math.min(d.scroller.scrollLeft,f),!0)}var g,h;if(b.updateScrollPos)g=b.updateScrollPos;else if(b.selectionChanged&&d.scroller.clientHeight){var i=Z(a,c.sel.head);g=gc(a,i.left,i.top,i.left,i.bottom)}(b.changes.length||b.forceUpdate||g&&null!=g.scrollTop)&&(h=t(a,b.changes,g&&g.scrollTop,b.forceUpdate),a.display.scroller.offsetHeight&&(a.doc.scrollTop=a.display.scroller.scrollTop)),!h&&b.selectionChanged&&C(a),b.updateScrollPos?(d.scroller.scrollTop=d.scrollbarV.scrollTop=c.scrollTop=g.scrollTop,d.scroller.scrollLeft=d.scrollbarH.scrollLeft=c.scrollLeft=g.scrollLeft,p(a),b.scrollToPos&&ec(a,Xb(a.doc,b.scrollToPos),b.scrollToPosMargin)):g&&dc(a),b.selectionChanged&&F(a),a.state.focused&&b.updateInput&&mb(a,b.userSelChange);var j=b.maybeHiddenMarkers,k=b.maybeUnhiddenMarkers;if(j)for(var m=0;m<j.length;++m)j[m].lines.length||Md(j[m],"hide");if(k)for(var m=0;m<k.length;++m)k[m].lines.length&&Md(k[m],"unhide");var n;if(--vf||(n=uf,uf=null),b.textChanged&&Md(a,"change",a,b.textChanged),b.cursorActivity&&Md(a,"cursorActivity",a),n)for(var m=0;m<n.length;++m)n[m]()}function fb(a,b){return function(){var c=a||this,d=!c.curOp;d&&db(c);try{var e=b.apply(c,arguments)}finally{d&&eb(c)}return e}}function gb(a){return function(){var b,c=this.cm&&!this.cm.curOp;c&&db(this.cm);try{b=a.apply(this,arguments)}finally{c&&eb(this.cm)}return b}}function hb(a,b){var c,d=!a.curOp;d&&db(a);try{c=b()}finally{d&&eb(a)}return c}function ib(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),a.curOp.changes.push({from:b,to:c,diff:d})}function jb(a){a.display.pollingFast||a.display.poll.set(a.options.pollInterval,function(){lb(a),a.state.focused&&jb(a)})}function kb(a){function b(){var d=lb(a);d||c?(a.display.pollingFast=!1,jb(a)):(c=!0,a.display.poll.set(60,b))}var c=!1;a.display.pollingFast=!0,a.display.poll.set(20,b)}function lb(a){var b=a.display.input,c=a.display.prevInput,d=a.doc,e=d.sel;if(!a.state.focused||Ff(b)||ob(a)||a.state.disableInput)return!1;var f=b.value;if(f==c&&Tb(e.from,e.to))return!1;if(xe&&!ze&&a.display.inputHasSelection===f)return mb(a,!0),!1;var g=!a.curOp;g&&db(a),e.shift=!1;for(var h=0,i=Math.min(c.length,f.length);i>h&&c.charCodeAt(h)==f.charCodeAt(h);)++h;var j=e.from,k=e.to;h<c.length?j=Sb(j.line,j.ch-(c.length-h)):a.state.overwrite&&Tb(j,k)&&!a.state.pasteIncoming&&(k=Sb(k.line,Math.min(kd(d,k.line).text.length,k.ch+(f.length-h))));var l=a.curOp.updateInput,m={from:j,to:k,text:Ef(f.slice(h)),origin:a.state.pasteIncoming?"paste":"+input"};return Lb(a.doc,m,"end"),a.curOp.updateInput=l,Nd(a,"inputRead",a,m),f.length>1e3||f.indexOf("\n")>-1?b.value=a.display.prevInput="":a.display.prevInput=f,g&&eb(a),a.state.pasteIncoming=!1,!0}function mb(a,b){var c,d,e=a.doc;if(Tb(e.sel.from,e.sel.to))b&&(a.display.prevInput=a.display.input.value="",xe&&!ze&&(a.display.inputHasSelection=null));else{a.display.prevInput="",c=Gf&&(e.sel.to.line-e.sel.from.line>100||(d=a.getSelection()).length>1e3);var f=c?"-":d||a.getSelection();a.display.input.value=f,a.state.focused&&Wd(a.display.input),xe&&!ze&&(a.display.inputHasSelection=f)}a.display.inaccurateSelection=c}function nb(a){"nocursor"==a.options.readOnly||Ke&&document.activeElement==a.display.input||a.display.input.focus()}function ob(a){return a.options.readOnly||a.doc.cantEdit}function pb(a){function b(){a.state.focused&&setTimeout(_d(nb,a),0)}function c(){null==h&&(h=setTimeout(function(){h=null,g.cachedCharWidth=g.cachedTextHeight=Cf=null,T(a),hb(a,_d(ib,a))},100))}function d(){for(var a=g.wrapper.parentNode;a&&a!=document.body;a=a.parentNode);a?setTimeout(d,5e3):Ld(window,"resize",c)}function e(b){Od(a,b)||a.options.onDragEvent&&a.options.onDragEvent(a,Dd(b))||Hd(b)}function f(){g.inaccurateSelection&&(g.prevInput="",g.inaccurateSelection=!1,g.input.value=a.getSelection(),Wd(g.input))}var g=a.display;Kd(g.scroller,"mousedown",fb(a,sb)),xe?Kd(g.scroller,"dblclick",fb(a,function(b){if(!Od(a,b)){var c=rb(a,b);if(c&&!tb(a,b)&&!qb(a.display,b)){Ed(b);var d=nc(kd(a.doc,c.line).text,c);$b(a.doc,d.from,d.to)}}})):Kd(g.scroller,"dblclick",function(b){Od(a,b)||Ed(b)}),Kd(g.lineSpace,"selectstart",function(a){qb(g,a)||Ed(a)}),Se||Kd(g.scroller,"contextmenu",function(b){Hb(a,b)}),Kd(g.scroller,"scroll",function(){g.scroller.clientHeight&&(wb(a,g.scroller.scrollTop),xb(a,g.scroller.scrollLeft,!0),Md(a,"scroll",a))}),Kd(g.scrollbarV,"scroll",function(){g.scroller.clientHeight&&wb(a,g.scrollbarV.scrollTop)}),Kd(g.scrollbarH,"scroll",function(){g.scroller.clientHeight&&xb(a,g.scrollbarH.scrollLeft)}),Kd(g.scroller,"mousewheel",function(b){yb(a,b)}),Kd(g.scroller,"DOMMouseScroll",function(b){yb(a,b)}),Kd(g.scrollbarH,"mousedown",b),Kd(g.scrollbarV,"mousedown",b),Kd(g.wrapper,"scroll",function(){g.wrapper.scrollTop=g.wrapper.scrollLeft=0});var h;Kd(window,"resize",c),setTimeout(d,5e3),Kd(g.input,"keyup",fb(a,function(b){Od(a,b)||a.options.onKeyEvent&&a.options.onKeyEvent(a,Dd(b))||16==b.keyCode&&(a.doc.sel.shift=!1)})),Kd(g.input,"input",_d(kb,a)),Kd(g.input,"keydown",fb(a,Db)),Kd(g.input,"keypress",fb(a,Eb)),Kd(g.input,"focus",_d(Fb,a)),Kd(g.input,"blur",_d(Gb,a)),a.options.dragDrop&&(Kd(g.scroller,"dragstart",function(b){vb(a,b)}),Kd(g.scroller,"dragenter",e),Kd(g.scroller,"dragover",e),Kd(g.scroller,"drop",fb(a,ub))),Kd(g.scroller,"paste",function(b){qb(g,b)||(nb(a),kb(a))}),Kd(g.input,"paste",function(){a.state.pasteIncoming=!0,kb(a)}),Kd(g.input,"cut",f),Kd(g.input,"copy",f),Fe&&Kd(g.sizer,"mouseup",function(){document.activeElement==g.input&&g.input.blur(),nb(a)})}function qb(a,b){for(var c=Id(b);c!=a.wrapper;c=c.parentNode)if(!c||c.ignoreEvents||c.parentNode==a.sizer&&c!=a.mover)return!0}function rb(a,b,c){var d=a.display;if(!c){var e=Id(b);if(e==d.scrollbarH||e==d.scrollbarH.firstChild||e==d.scrollbarV||e==d.scrollbarV.firstChild||e==d.scrollbarFiller||e==d.gutterFiller)return null}var f,g,h=ge(d.lineSpace);try{f=b.clientX,g=b.clientY}catch(b){return null}return _(a,f-h.left,g-h.top)}function sb(a){function b(a){if(!Tb(r,a)){if(r=a,"single"==k)return $b(e.doc,Xb(g,i),a),void 0;if(p=Xb(g,p),q=Xb(g,q),"double"==k){var b=nc(kd(g,a.line).text,a);Ub(a,p)?$b(e.doc,b.from,q):$b(e.doc,p,b.to)}else"triple"==k&&(Ub(a,p)?$b(e.doc,q,Xb(g,Sb(a.line,0))):$b(e.doc,p,Xb(g,Sb(a.line+1,0))))}}function c(a){var d=++t,h=rb(e,a,!0);if(h)if(Tb(h,m)){var i=a.clientY<s.top?-20:a.clientY>s.bottom?20:0;i&&setTimeout(fb(e,function(){t==d&&(f.scroller.scrollTop+=i,c(a))}),50)}else{e.state.focused||Fb(e),m=h,b(h);var j=o(f,g);(h.line>=j.to||h.line<j.from)&&setTimeout(fb(e,function(){t==d&&c(a)}),150)}}function d(a){t=1/0,Ed(a),nb(e),Ld(document,"mousemove",u),Ld(document,"mouseup",v)}if(!Od(this,a)){var e=this,f=e.display,g=e.doc,h=g.sel;if(h.shift=a.shiftKey,qb(f,a))return Ae||(f.scroller.draggable=!1,setTimeout(function(){f.scroller.draggable=!0},100)),void 0;if(!tb(e,a)){var i=rb(e,a);switch(Jd(a)){case 3:return Se&&Hb.call(e,e,a),void 0;case 2:return i&&$b(e.doc,i),setTimeout(_d(nb,e),20),Ed(a),void 0}if(!i)return Id(a)==f.scroller&&Ed(a),void 0;e.state.focused||Fb(e);var j=+new Date,k="single";if(Qe&&Qe.time>j-400&&Tb(Qe.pos,i))k="triple",Ed(a),setTimeout(_d(nb,e),20),oc(e,i.line);else if(Pe&&Pe.time>j-400&&Tb(Pe.pos,i)){k="double",Qe={time:j,pos:i},Ed(a);var l=nc(kd(g,i.line).text,i);$b(e.doc,l.from,l.to)}else Pe={time:j,pos:i};var m=i;if(e.options.dragDrop&&Bf&&!ob(e)&&!Tb(h.from,h.to)&&!Ub(i,h.from)&&!Ub(h.to,i)&&"single"==k){var n=fb(e,function(b){Ae&&(f.scroller.draggable=!1),e.state.draggingText=!1,Ld(document,"mouseup",n),Ld(f.scroller,"drop",n),Math.abs(a.clientX-b.clientX)+Math.abs(a.clientY-b.clientY)<10&&(Ed(b),$b(e.doc,i),nb(e))
2
- });return Ae&&(f.scroller.draggable=!0),e.state.draggingText=n,f.scroller.dragDrop&&f.scroller.dragDrop(),Kd(document,"mouseup",n),Kd(f.scroller,"drop",n),void 0}Ed(a),"single"==k&&$b(e.doc,Xb(g,i));var p=h.from,q=h.to,r=i,s=ge(f.wrapper),t=0,u=fb(e,function(a){xe||Jd(a)?c(a):d(a)}),v=fb(e,d);Kd(document,"mousemove",u),Kd(document,"mouseup",v)}}}function tb(a,b){var c=a.display;try{var d=b.clientX,e=b.clientY}catch(b){return!1}if(d>=Math.floor(ge(c.gutters).right))return!1;if(Ed(b),!Qd(a,"gutterClick"))return!0;var f=ge(c.lineDiv);if(e>f.bottom)return!0;e-=f.top-c.viewOffset;for(var g=0;g<a.options.gutters.length;++g){var h=c.gutters.childNodes[g];if(h&&ge(h).right>=d){var i=pd(a.doc,e),j=a.options.gutters[g];Nd(a,"gutterClick",a,i,j,b);break}}return!0}function ub(a){var b=this;if(!(Od(b,a)||qb(b.display,a)||b.options.onDragEvent&&b.options.onDragEvent(b,Dd(a)))){Ed(a),xe&&(We=+new Date);var c=rb(b,a,!0),d=a.dataTransfer.files;if(c&&!ob(b))if(d&&d.length&&window.FileReader&&window.File)for(var e=d.length,f=Array(e),g=0,h=function(a,d){var h=new FileReader;h.onload=function(){f[d]=h.result,++g==e&&(c=Xb(b.doc,c),Lb(b.doc,{from:c,to:c,text:Ef(f.join("\n")),origin:"paste"},"around"))},h.readAsText(a)},i=0;e>i;++i)h(d[i],i);else{if(b.state.draggingText&&!Ub(c,b.doc.sel.from)&&!Ub(b.doc.sel.to,c))return b.state.draggingText(a),setTimeout(_d(nb,b),20),void 0;try{var f=a.dataTransfer.getData("Text");if(f){var j=b.doc.sel.from,k=b.doc.sel.to;ac(b.doc,c,c),b.state.draggingText&&Rb(b.doc,"",j,k,"paste"),b.replaceSelection(f,null,"paste"),nb(b),Fb(b)}}catch(a){}}}}function vb(a,b){if(xe&&(!a.state.draggingText||+new Date-We<100))return Hd(b),void 0;if(!Od(a,b)&&!qb(a.display,b)){var c=a.getSelection();if(b.dataTransfer.setData("Text",c),b.dataTransfer.setDragImage&&!Ee){var d=ce("img",null,null,"position: fixed; left: 0; top: 0;");De&&(d.width=d.height=1,a.display.wrapper.appendChild(d),d._top=d.offsetTop),b.dataTransfer.setDragImage(d,0,0),De&&d.parentNode.removeChild(d)}}}function wb(a,b){Math.abs(a.doc.scrollTop-b)<2||(a.doc.scrollTop=b,we||t(a,[],b),a.display.scroller.scrollTop!=b&&(a.display.scroller.scrollTop=b),a.display.scrollbarV.scrollTop!=b&&(a.display.scrollbarV.scrollTop=b),we&&t(a,[]),G(a,100))}function xb(a,b,c){(c?b==a.doc.scrollLeft:Math.abs(a.doc.scrollLeft-b)<2)||(b=Math.min(b,a.display.scroller.scrollWidth-a.display.scroller.clientWidth),a.doc.scrollLeft=b,p(a),a.display.scroller.scrollLeft!=b&&(a.display.scroller.scrollLeft=b),a.display.scrollbarH.scrollLeft!=b&&(a.display.scrollbarH.scrollLeft=b))}function yb(a,b){var c=b.wheelDeltaX,d=b.wheelDeltaY;null==c&&b.detail&&b.axis==b.HORIZONTAL_AXIS&&(c=b.detail),null==d&&b.detail&&b.axis==b.VERTICAL_AXIS?d=b.detail:null==d&&(d=b.wheelDelta);var e=a.display,f=e.scroller;if(c&&f.scrollWidth>f.clientWidth||d&&f.scrollHeight>f.clientHeight){if(d&&Le&&Ae)for(var g=b.target;g!=f;g=g.parentNode)if(g.lineObj){a.display.currentWheelTarget=g;break}if(c&&!we&&!De&&null!=Ye)return d&&wb(a,Math.max(0,Math.min(f.scrollTop+d*Ye,f.scrollHeight-f.clientHeight))),xb(a,Math.max(0,Math.min(f.scrollLeft+c*Ye,f.scrollWidth-f.clientWidth))),Ed(b),e.wheelStartX=null,void 0;if(d&&null!=Ye){var h=d*Ye,i=a.doc.scrollTop,j=i+e.wrapper.clientHeight;0>h?i=Math.max(0,i+h-50):j=Math.min(a.doc.height,j+h+50),t(a,[],{top:i,bottom:j})}20>Xe&&(null==e.wheelStartX?(e.wheelStartX=f.scrollLeft,e.wheelStartY=f.scrollTop,e.wheelDX=c,e.wheelDY=d,setTimeout(function(){if(null!=e.wheelStartX){var a=f.scrollLeft-e.wheelStartX,b=f.scrollTop-e.wheelStartY,c=b&&e.wheelDY&&b/e.wheelDY||a&&e.wheelDX&&a/e.wheelDX;e.wheelStartX=e.wheelStartY=null,c&&(Ye=(Ye*Xe+c)/(Xe+1),++Xe)}},200)):(e.wheelDX+=c,e.wheelDY+=d))}}function zb(a,b,c){if("string"==typeof b&&(b=kf[b],!b))return!1;a.display.pollingFast&&lb(a)&&(a.display.pollingFast=!1);var d=a.doc,e=d.sel.shift,f=!1;try{ob(a)&&(a.state.suppressEdits=!0),c&&(d.sel.shift=!1),f=b(a)!=xf}finally{d.sel.shift=e,a.state.suppressEdits=!1}return f}function Ab(a){var b=a.state.keyMaps.slice(0);return a.options.extraKeys&&b.push(a.options.extraKeys),b.push(a.options.keyMap),b}function Bb(a,b){var c=sc(a.options.keyMap),d=c.auto;clearTimeout(Ze),d&&!uc(b)&&(Ze=setTimeout(function(){sc(a.options.keyMap)==c&&(a.options.keyMap=d.call?d.call(null,a):d,g(a))},50));var e=vc(b,!0),f=!1;if(!e)return!1;var h=Ab(a);return f=b.shiftKey?tc("Shift-"+e,h,function(b){return zb(a,b,!0)})||tc(e,h,function(b){return("string"==typeof b?/^go[A-Z]/.test(b):b.motion)?zb(a,b):void 0}):tc(e,h,function(b){return zb(a,b)}),f&&(Ed(b),F(a),ze&&(b.oldKeyCode=b.keyCode,b.keyCode=0),Nd(a,"keyHandled",a,e,b)),f}function Cb(a,b,c){var d=tc("'"+c+"'",Ab(a),function(b){return zb(a,b,!0)});return d&&(Ed(b),F(a),Nd(a,"keyHandled",a,"'"+c+"'",b)),d}function Db(a){var b=this;if(b.state.focused||Fb(b),xe&&27==a.keyCode&&(a.returnValue=!1),!(Od(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Dd(a)))){var c=a.keyCode;b.doc.sel.shift=16==c||a.shiftKey;var d=Bb(b,a);De&&(_e=d?c:null,!d&&88==c&&!Gf&&(Le?a.metaKey:a.ctrlKey)&&b.replaceSelection(""))}}function Eb(a){var b=this;if(!(Od(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Dd(a)))){var c=a.keyCode,d=a.charCode;if(De&&c==_e)return _e=null,Ed(a),void 0;if(!(De&&(!a.which||a.which<10)||Fe)||!Bb(b,a)){var e=String.fromCharCode(null==d?c:d);this.options.electricChars&&this.doc.mode.electricChars&&this.options.smartIndent&&!ob(this)&&this.doc.mode.electricChars.indexOf(e)>-1&&setTimeout(fb(b,function(){jc(b,b.doc.sel.to.line,"smart")}),75),Cb(b,a,e)||(xe&&!ze&&(b.display.inputHasSelection=null),kb(b))}}}function Fb(a){"nocursor"!=a.options.readOnly&&(a.state.focused||(Md(a,"focus",a),a.state.focused=!0,-1==a.display.wrapper.className.search(/\bCodeMirror-focused\b/)&&(a.display.wrapper.className+=" CodeMirror-focused"),mb(a,!0)),jb(a),F(a))}function Gb(a){a.state.focused&&(Md(a,"blur",a),a.state.focused=!1,a.display.wrapper.className=a.display.wrapper.className.replace(" CodeMirror-focused","")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.doc.sel.shift=!1)},150)}function Hb(a,b){function c(){if(null!=e.input.selectionStart){var a=e.input.value=" "+(Tb(f.from,f.to)?"":e.input.value);e.prevInput=" ",e.input.selectionStart=1,e.input.selectionEnd=a.length}}function d(){if(e.inputDiv.style.position="relative",e.input.style.cssText=i,ze&&(e.scrollbarV.scrollTop=e.scroller.scrollTop=h),jb(a),null!=e.input.selectionStart){(!xe||ze)&&c(),clearTimeout($e);var b=0,d=function(){" "==e.prevInput&&0==e.input.selectionStart?fb(a,kf.selectAll)(a):b++<10?$e=setTimeout(d,500):mb(a)};$e=setTimeout(d,200)}}if(!Od(a,b,"contextmenu")){var e=a.display,f=a.doc.sel;if(!qb(e,b)){var g=rb(a,b),h=e.scroller.scrollTop;if(g&&!De){(Tb(f.from,f.to)||Ub(g,f.from)||!Ub(g,f.to))&&fb(a,ac)(a.doc,g,g);var i=e.input.style.cssText;if(e.inputDiv.style.position="absolute",e.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(b.clientY-5)+"px; left: "+(b.clientX-5)+"px; z-index: 1000; background: white; outline: none;"+"border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);",nb(a),mb(a,!0),Tb(f.from,f.to)&&(e.input.value=e.prevInput=" "),xe&&!ze&&c(),Se){Hd(b);var j=function(){Ld(window,"mouseup",j),setTimeout(d,20)};Kd(window,"mouseup",j)}else setTimeout(d,50)}}}}function Ib(a,b,c){if(!Ub(b.from,c))return Xb(a,c);var d=b.text.length-1-(b.to.line-b.from.line);if(c.line>b.to.line+d){var e=c.line-d,f=a.first+a.size-1;return e>f?Sb(f,kd(a,f).text.length):Yb(c,kd(a,e).text.length)}if(c.line==b.to.line+d)return Yb(c,Vd(b.text).length+(1==b.text.length?b.from.ch:0)+kd(a,b.to.line).text.length-b.to.ch);var g=c.line-b.from.line;return Yb(c,b.text[g].length+(g?0:b.from.ch))}function Jb(a,b,c){if(c&&"object"==typeof c)return{anchor:Ib(a,b,c.anchor),head:Ib(a,b,c.head)};if("start"==c)return{anchor:b.from,head:b.from};var d=af(b);if("around"==c)return{anchor:b.from,head:d};if("end"==c)return{anchor:d,head:d};var e=function(a){if(Ub(a,b.from))return a;if(!Ub(b.to,a))return d;var c=a.line+b.text.length-(b.to.line-b.from.line)-1,e=a.ch;return a.line==b.to.line&&(e+=d.ch-b.to.ch),Sb(c,e)};return{anchor:e(a.sel.anchor),head:e(a.sel.head)}}function Kb(a,b,c){var d={canceled:!1,from:b.from,to:b.to,text:b.text,origin:b.origin,cancel:function(){this.canceled=!0}};return c&&(d.update=function(b,c,d,e){b&&(this.from=Xb(a,b)),c&&(this.to=Xb(a,c)),d&&(this.text=d),void 0!==e&&(this.origin=e)}),Md(a,"beforeChange",a,d),a.cm&&Md(a.cm,"beforeChange",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function Lb(a,b,c,d){if(a.cm){if(!a.cm.curOp)return fb(a.cm,Lb)(a,b,c,d);if(a.cm.state.suppressEdits)return}if(!(Qd(a,"beforeChange")||a.cm&&Qd(a.cm,"beforeChange"))||(b=Kb(a,b,!0))){var e=Te&&!d&&Ic(a,b.from,b.to);if(e){for(var f=e.length-1;f>=1;--f)Mb(a,{from:e[f].from,to:e[f].to,text:[""]});e.length&&Mb(a,{from:e[0].from,to:e[0].to,text:b.text},c)}else Mb(a,b,c)}}function Mb(a,b,c){var d=Jb(a,b,c);vd(a,b,d,a.cm?a.cm.curOp.id:0/0),Pb(a,b,d,Gc(a,b));var e=[];id(a,function(a,c){c||-1!=Xd(e,a.history)||(Bd(a.history,b),e.push(a.history)),Pb(a,b,null,Gc(a,b))})}function Nb(a,b){if(!a.cm||!a.cm.state.suppressEdits){var c=a.history,d=("undo"==b?c.done:c.undone).pop();if(d){var e={changes:[],anchorBefore:d.anchorAfter,headBefore:d.headAfter,anchorAfter:d.anchorBefore,headAfter:d.headBefore,generation:c.generation};("undo"==b?c.undone:c.done).push(e),c.generation=d.generation||++c.maxGeneration;for(var f=Qd(a,"beforeChange")||a.cm&&Qd(a.cm,"beforeChange"),g=d.changes.length-1;g>=0;--g){var h=d.changes[g];if(h.origin=b,f&&!Kb(a,h,!1))return("undo"==b?c.done:c.undone).length=0,void 0;e.changes.push(ud(a,h));var i=g?Jb(a,h,null):{anchor:d.anchorBefore,head:d.headBefore};Pb(a,h,i,Hc(a,h));var j=[];id(a,function(a,b){b||-1!=Xd(j,a.history)||(Bd(a.history,h),j.push(a.history)),Pb(a,h,null,Hc(a,h))})}}}}function Ob(a,b){function c(a){return Sb(a.line+b,a.ch)}a.first+=b,a.cm&&ib(a.cm,a.first,a.first,b),a.sel.head=c(a.sel.head),a.sel.anchor=c(a.sel.anchor),a.sel.from=c(a.sel.from),a.sel.to=c(a.sel.to)}function Pb(a,b,c,d){if(a.cm&&!a.cm.curOp)return fb(a.cm,Pb)(a,b,c,d);if(b.to.line<a.first)return Ob(a,b.text.length-1-(b.to.line-b.from.line)),void 0;if(!(b.from.line>a.lastLine())){if(b.from.line<a.first){var e=b.text.length-1-(a.first-b.from.line);Ob(a,e),b={from:Sb(a.first,0),to:Sb(b.to.line+e,b.to.ch),text:[Vd(b.text)],origin:b.origin}}var f=a.lastLine();b.to.line>f&&(b={from:b.from,to:Sb(f,kd(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=ld(a,b.from,b.to),c||(c=Jb(a,b,null)),a.cm?Qb(a.cm,b,d,c):fd(a,b,d,c)}}function Qb(a,b,c,d){var f=a.doc,g=a.display,h=b.from,i=b.to,j=!1,l=h.line;a.options.lineWrapping||(l=od(Mc(f,kd(f,h.line))),f.iter(l,i.line+1,function(a){return a==g.maxLine?(j=!0,!0):void 0})),Ub(f.sel.head,b.from)||Ub(b.to,f.sel.head)||(a.curOp.cursorActivity=!0),fd(f,b,c,d,e(a)),a.options.lineWrapping||(f.iter(l,h.line+b.text.length,function(a){var b=k(f,a);b>g.maxLineLength&&(g.maxLine=a,g.maxLineLength=b,g.maxLineChanged=!0,j=!1)}),j&&(a.curOp.updateMaxLine=!0)),f.frontier=Math.min(f.frontier,h.line),G(a,400);var m=b.text.length-(i.line-h.line)-1;if(ib(a,h.line,i.line+1,m),Qd(a,"change")){var n={from:h,to:i,text:b.text,removed:b.removed,origin:b.origin};if(a.curOp.textChanged){for(var o=a.curOp.textChanged;o.next;o=o.next);o.next=n}else a.curOp.textChanged=n}}function Rb(a,b,c,d,e){if(d||(d=c),Ub(d,c)){var f=d;d=c,c=f}"string"==typeof b&&(b=Ef(b)),Lb(a,{from:c,to:d,text:b,origin:e},null)}function Sb(a,b){return this instanceof Sb?(this.line=a,this.ch=b,void 0):new Sb(a,b)}function Tb(a,b){return a.line==b.line&&a.ch==b.ch}function Ub(a,b){return a.line<b.line||a.line==b.line&&a.ch<b.ch}function Vb(a){return Sb(a.line,a.ch)}function Wb(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function Xb(a,b){if(b.line<a.first)return Sb(a.first,0);var c=a.first+a.size-1;return b.line>c?Sb(c,kd(a,c).text.length):Yb(b,kd(a,b.line).text.length)}function Yb(a,b){var c=a.ch;return null==c||c>b?Sb(a.line,b):0>c?Sb(a.line,0):a}function Zb(a,b){return b>=a.first&&b<a.first+a.size}function $b(a,b,c,d){if(a.sel.shift||a.sel.extend){var e=a.sel.anchor;if(c){var f=Ub(b,e);f!=Ub(c,e)?(e=b,b=c):f!=Ub(b,c)&&(b=c)}ac(a,e,b,d)}else ac(a,b,c||b,d);a.cm&&(a.cm.curOp.userSelChange=!0)}function _b(a,b,c){var d={anchor:b,head:c};return Md(a,"beforeSelectionChange",a,d),a.cm&&Md(a.cm,"beforeSelectionChange",a.cm,d),d.anchor=Xb(a,d.anchor),d.head=Xb(a,d.head),d}function ac(a,b,c,d,e){if(!e&&Qd(a,"beforeSelectionChange")||a.cm&&Qd(a.cm,"beforeSelectionChange")){var f=_b(a,b,c);c=f.head,b=f.anchor}var g=a.sel;if(g.goalColumn=null,(e||!Tb(b,g.anchor))&&(b=cc(a,b,d,"push"!=e)),(e||!Tb(c,g.head))&&(c=cc(a,c,d,"push"!=e)),!Tb(g.anchor,b)||!Tb(g.head,c)){g.anchor=b,g.head=c;var h=Ub(c,b);g.from=h?c:b,g.to=h?b:c,a.cm&&(a.cm.curOp.updateInput=a.cm.curOp.selectionChanged=a.cm.curOp.cursorActivity=!0),Nd(a,"cursorActivity",a)}}function bc(a){ac(a.doc,a.doc.sel.from,a.doc.sel.to,null,"push")}function cc(a,b,c,d){var e=!1,f=b,g=c||1;a.cantEdit=!1;a:for(;;){var h=kd(a,f.line);if(h.markedSpans)for(var i=0;i<h.markedSpans.length;++i){var j=h.markedSpans[i],k=j.marker;if((null==j.from||(k.inclusiveLeft?j.from<=f.ch:j.from<f.ch))&&(null==j.to||(k.inclusiveRight?j.to>=f.ch:j.to>f.ch))){if(d&&(Md(k,"beforeCursorEnter"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find()[0>g?"from":"to"];if(Tb(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?Xb(a,Sb(l.line-1)):null:l.ch>h.text.length&&(l=l.line<a.first+a.size-1?Sb(l.line+1,0):null),!l)){if(e)return d?(a.cantEdit=!0,Sb(a.first,0)):cc(a,b,c,!0);e=!0,l=b,g=-g}f=l;continue a}}return f}}function dc(a){var b=ec(a,a.doc.sel.head,a.options.cursorScrollMargin);if(a.state.focused){var c=a.display,d=ge(c.sizer),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!Ie){var f="none"==c.cursor.style.display;f&&(c.cursor.style.display="",c.cursor.style.left=b.left+"px",c.cursor.style.top=b.top-c.viewOffset+"px"),c.cursor.scrollIntoView(e),f&&(c.cursor.style.display="none")}}}function ec(a,b,c){for(null==c&&(c=0);;){var d=!1,e=Z(a,b),f=gc(a,e.left,e.top-c,e.left,e.bottom+c),g=a.doc.scrollTop,h=a.doc.scrollLeft;if(null!=f.scrollTop&&(wb(a,f.scrollTop),Math.abs(a.doc.scrollTop-g)>1&&(d=!0)),null!=f.scrollLeft&&(xb(a,f.scrollLeft),Math.abs(a.doc.scrollLeft-h)>1&&(d=!0)),!d)return e}}function fc(a,b,c,d,e){var f=gc(a,b,c,d,e);null!=f.scrollTop&&wb(a,f.scrollTop),null!=f.scrollLeft&&xb(a,f.scrollLeft)}function gc(a,b,c,d,e){var f=a.display,g=bb(a.display);0>c&&(c=0);var h=f.scroller.clientHeight-wf,i=f.scroller.scrollTop,j={},k=a.doc.height+L(f),l=g>c,m=e>k-g;if(i>c)j.scrollTop=l?0:c;else if(e>i+h){var n=Math.min(c,(m?k:e)-h);n!=i&&(j.scrollTop=n)}var o=f.scroller.clientWidth-wf,p=f.scroller.scrollLeft;b+=f.gutters.offsetWidth,d+=f.gutters.offsetWidth;var q=f.gutters.offsetWidth,r=q+10>b;return p+q>b||r?(r&&(b=0),j.scrollLeft=Math.max(0,b-10-q)):d>o+p-3&&(j.scrollLeft=d+10-o),j}function hc(a,b,c){a.curOp.updateScrollPos={scrollLeft:null==b?a.doc.scrollLeft:b,scrollTop:null==c?a.doc.scrollTop:c}}function ic(a,b,c){var d=a.curOp.updateScrollPos||(a.curOp.updateScrollPos={scrollLeft:a.doc.scrollLeft,scrollTop:a.doc.scrollTop}),e=a.display.scroller;d.scrollTop=Math.max(0,Math.min(e.scrollHeight-e.clientHeight,d.scrollTop+c)),d.scrollLeft=Math.max(0,Math.min(e.scrollWidth-e.clientWidth,d.scrollLeft+b))}function jc(a,b,c,d){var e=a.doc;if(null==c&&(c="add"),"smart"==c)if(a.doc.mode.indent)var f=J(a,b);else c="prev";var g,h=a.options.tabSize,i=kd(e,b),j=Td(i.text,null,h),k=i.text.match(/^\s*/)[0];if("smart"==c&&(g=a.doc.mode.indent(f,i.text.slice(k.length),i.text),g==xf)){if(!d)return;c="prev"}"prev"==c?g=b>e.first?Td(kd(e,b-1).text,null,h):0:"add"==c?g=j+a.options.indentUnit:"subtract"==c?g=j-a.options.indentUnit:"number"==typeof c&&(g=j+c),g=Math.max(0,g);var l="",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(g/h);n;--n)m+=h,l+=" ";g>m&&(l+=Ud(g-m)),l!=k&&Rb(a.doc,l,Sb(b,0),Sb(b,k.length),"+input"),i.stateAfter=null}function kc(a,b,c){var d=b,e=b,f=a.doc;return"number"==typeof b?e=kd(f,Wb(f,b)):d=od(b),null==d?null:c(e,d)?(ib(a,d,d+1),e):null}function lc(a,b,c,d,e){function f(){var b=h+c;return b<a.first||b>=a.first+a.size?l=!1:(h=b,k=kd(a,b))}function g(a){var b=(e?ue:ve)(k,i,c,!0);if(null==b){if(a||!f())return l=!1;i=e?(0>c?oe:ne)(k):0>c?k.text.length:0}else i=b;return!0}var h=b.line,i=b.ch,j=c,k=kd(a,h),l=!0;if("char"==d)g();else if("column"==d)g(!0);else if("word"==d||"group"==d)for(var m=null,n="group"==d,o=!0;!(0>c)||g(!o);o=!1){var p=k.text.charAt(i)||"\n",q=ae(p)?"w":n?/\s/.test(p)?null:"p":null;if(m&&m!=q){0>c&&(c=1,g());break}if(q&&(m=q),c>0&&!g(!o))break}var r=cc(a,Sb(h,i),j,!0);return l||(r.hitSide=!0),r}function mc(a,b,c,d){var e,f=a.doc,g=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);e=b.top+c*(h-(0>c?1.5:.5)*bb(a.display))}else"line"==d&&(e=c>0?b.bottom+3:b.top-3);for(;;){var i=_(a,g,e);if(!i.outside)break;if(0>c?0>=e:e>=f.height){i.hitSide=!0;break}e+=5*c}return i}function nc(a,b){var c=b.ch,d=b.ch;if(a){(b.xRel<0||d==a.length)&&c?--c:++d;for(var e=a.charAt(c),f=ae(e)?ae:/\s/.test(e)?function(a){return/\s/.test(a)}:function(a){return!/\s/.test(a)&&!ae(a)};c>0&&f(a.charAt(c-1));)--c;for(;d<a.length&&f(a.charAt(d));)++d}return{from:Sb(b.line,c),to:Sb(b.line,d)}}function oc(a,b){$b(a.doc,Sb(b,0),Xb(a.doc,Sb(b+1,0)))}function pc(b,c,d,e){a.defaults[b]=c,d&&(bf[b]=e?function(a,b,c){c!=df&&d(a,b,c)}:d)}function qc(a,b){if(b===!0)return b;if(a.copyState)return a.copyState(b);var c={};for(var d in b){var e=b[d];e instanceof Array&&(e=e.concat([])),c[d]=e}return c}function rc(a,b,c){return a.startState?a.startState(b,c):!0}function sc(a){return"string"==typeof a?lf[a]:a}function tc(a,b,c){function d(b){b=sc(b);var e=b[a];if(e===!1)return"stop";if(null!=e&&c(e))return!0;if(b.nofallthrough)return"stop";var f=b.fallthrough;if(null==f)return!1;if("[object Array]"!=Object.prototype.toString.call(f))return d(f);for(var g=0,h=f.length;h>g;++g){var i=d(f[g]);if(i)return i}return!1}for(var e=0;e<b.length;++e){var f=d(b[e]);if(f)return"stop"!=f}}function uc(a){var b=Hf[a.keyCode];return"Ctrl"==b||"Alt"==b||"Shift"==b||"Mod"==b}function vc(a,b){if(De&&34==a.keyCode&&a["char"])return!1;var c=Hf[a.keyCode];return null==c||a.altGraphKey?!1:(a.altKey&&(c="Alt-"+c),(Re?a.metaKey:a.ctrlKey)&&(c="Ctrl-"+c),(Re?a.ctrlKey:a.metaKey)&&(c="Cmd-"+c),!b&&a.shiftKey&&(c="Shift-"+c),c)}function wc(a,b){this.pos=this.start=0,this.string=a,this.tabSize=b||8,this.lastColumnPos=this.lastColumnValue=0}function xc(a,b){this.lines=[],this.type=b,this.doc=a}function yc(a,b,c,d,e){if(d&&d.shared)return Ac(a,b,c,d,e);if(a.cm&&!a.cm.curOp)return fb(a.cm,yc)(a,b,c,d,e);var f=new xc(a,e);if("range"==e&&!Ub(b,c))return f;d&&Zd(d,f),f.replacedWith&&(f.collapsed=!0,f.replacedWith=ce("span",[f.replacedWith],"CodeMirror-widget"),d.handleMouseEvents||(f.replacedWith.ignoreEvents=!0)),f.collapsed&&(Ue=!0),f.addToHistory&&vd(a,{from:b,to:c,origin:"markText"},{head:a.sel.head,anchor:a.sel.anchor},0/0);var g,h,i,j=b.line,k=0,l=a.cm;if(a.iter(j,c.line+1,function(d){l&&f.collapsed&&!l.options.lineWrapping&&Mc(a,d)==l.display.maxLine&&(i=!0);var e={from:null,to:null,marker:f};k+=d.text.length,j==b.line&&(e.from=b.ch,k-=b.ch),j==c.line&&(e.to=c.ch,k-=d.text.length-c.ch),f.collapsed&&(j==c.line&&(h=Jc(d,c.ch)),j==b.line?g=Jc(d,b.ch):nd(d,0)),Dc(d,e),++j}),f.collapsed&&a.iter(b.line,c.line+1,function(b){Nc(a,b)&&nd(b,0)}),f.clearOnEnter&&Kd(f,"beforeCursorEnter",function(){f.clear()}),f.readOnly&&(Te=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed){if(g!=h)throw new Error("Inserting collapsed marker overlapping an existing one");f.size=k,f.atomic=!0}return l&&(i&&(l.curOp.updateMaxLine=!0),(f.className||f.title||f.startStyle||f.endStyle||f.collapsed)&&ib(l,b.line,c.line+1),f.atomic&&bc(l)),f}function zc(a,b){this.markers=a,this.primary=b;for(var c=0,d=this;c<a.length;++c)a[c].parent=this,Kd(a[c],"clear",function(){d.clear()})}function Ac(a,b,c,d,e){d=Zd(d),d.shared=!1;var f=[yc(a,b,c,d,e)],g=f[0],h=d.replacedWith;return id(a,function(a){h&&(d.replacedWith=h.cloneNode(!0)),f.push(yc(a,Xb(a,b),Xb(a,c),d,e));for(var i=0;i<a.linked.length;++i)if(a.linked[i].isParent)return;g=Vd(f)}),new zc(f,g)}function Bc(a,b){if(a)for(var c=0;c<a.length;++c){var d=a[c];if(d.marker==b)return d}}function Cc(a,b){for(var c,d=0;d<a.length;++d)a[d]!=b&&(c||(c=[])).push(a[d]);return c}function Dc(a,b){a.markedSpans=a.markedSpans?a.markedSpans.concat([b]):[b],b.marker.attachLine(a)}function Ec(a,b,c){if(a)for(var d,e=0;e<a.length;++e){var f=a[e],g=f.marker,h=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);if(h||"bookmark"==g.type&&f.from==b&&(!c||!f.marker.insertLeft)){var i=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);(d||(d=[])).push({from:f.from,to:i?null:f.to,marker:g})}}return d}function Fc(a,b,c){if(a)for(var d,e=0;e<a.length;++e){var f=a[e],g=f.marker,h=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);if(h||"bookmark"==g.type&&f.from==b&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);(d||(d=[])).push({from:i?null:f.from-b,to:null==f.to?null:f.to-b,marker:g})}}return d}function Gc(a,b){var c=Zb(a,b.from.line)&&kd(a,b.from.line).markedSpans,d=Zb(a,b.to.line)&&kd(a,b.to.line).markedSpans;if(!c&&!d)return null;var e=b.from.ch,f=b.to.ch,g=Tb(b.from,b.to),h=Ec(c,e,g),i=Fc(d,f,g),j=1==b.text.length,k=Vd(b.text).length+(j?e:0);if(h)for(var l=0;l<h.length;++l){var m=h[l];if(null==m.to){var n=Bc(i,m.marker);n?j&&(m.to=null==n.to?null:n.to+k):m.to=e}}if(i)for(var l=0;l<i.length;++l){var m=i[l];if(null!=m.to&&(m.to+=k),null==m.from){var n=Bc(h,m.marker);n||(m.from=k,j&&(h||(h=[])).push(m))}else m.from+=k,j&&(h||(h=[])).push(m)}if(j&&h){for(var l=0;l<h.length;++l)null!=h[l].from&&h[l].from==h[l].to&&"bookmark"!=h[l].marker.type&&h.splice(l--,1);h.length||(h=null)}var o=[h];if(!j){var p,q=b.text.length-2;if(q>0&&h)for(var l=0;l<h.length;++l)null==h[l].to&&(p||(p=[])).push({from:null,to:null,marker:h[l].marker});for(var l=0;q>l;++l)o.push(p);o.push(i)}return o}function Hc(a,b){var c=xd(a,b),d=Gc(a,b);if(!c)return d;if(!d)return c;for(var e=0;e<c.length;++e){var f=c[e],g=d[e];if(f&&g)a:for(var h=0;h<g.length;++h){for(var i=g[h],j=0;j<f.length;++j)if(f[j].marker==i.marker)continue a;f.push(i)}else g&&(c[e]=g)}return c}function Ic(a,b,c){var d=null;if(a.iter(b.line,c.line+1,function(a){if(a.markedSpans)for(var b=0;b<a.markedSpans.length;++b){var c=a.markedSpans[b].marker;!c.readOnly||d&&-1!=Xd(d,c)||(d||(d=[])).push(c)}}),!d)return null;for(var e=[{from:b,to:c}],f=0;f<d.length;++f)for(var g=d[f],h=g.find(),i=0;i<e.length;++i){var j=e[i];if(!Ub(j.to,h.from)&&!Ub(h.to,j.from)){var k=[i,1];(Ub(j.from,h.from)||!g.inclusiveLeft&&Tb(j.from,h.from))&&k.push({from:j.from,to:h.from}),(Ub(h.to,j.to)||!g.inclusiveRight&&Tb(j.to,h.to))&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function Jc(a,b){var c,d=Ue&&a.markedSpans;if(d)for(var e,f=0;f<d.length;++f)e=d[f],e.marker.collapsed&&(null==e.from||e.from<b)&&(null==e.to||e.to>b)&&(!c||c.width<e.marker.width)&&(c=e.marker);return c}function Kc(a){return Jc(a,-1)}function Lc(a){return Jc(a,a.text.length+1)}function Mc(a,b){for(var c;c=Kc(b);)b=kd(a,c.find().from.line);return b}function Nc(a,b){var c=Ue&&b.markedSpans;if(c)for(var d,e=0;e<c.length;++e)if(d=c[e],d.marker.collapsed){if(null==d.from)return!0;if(!d.marker.replacedWith&&0==d.from&&d.marker.inclusiveLeft&&Oc(a,b,d))return!0}}function Oc(a,b,c){if(null==c.to){var d=c.marker.find().to,e=kd(a,d.line);return Oc(a,e,Bc(e.markedSpans,c.marker))}if(c.marker.inclusiveRight&&c.to==b.text.length)return!0;for(var f,g=0;g<b.markedSpans.length;++g)if(f=b.markedSpans[g],f.marker.collapsed&&!f.marker.replacedWith&&f.from==c.to&&(f.marker.inclusiveLeft||c.marker.inclusiveRight)&&Oc(a,b,f))return!0}function Pc(a){var b=a.markedSpans;if(b){for(var c=0;c<b.length;++c)b[c].marker.detachLine(a);a.markedSpans=null}}function Qc(a,b){if(b){for(var c=0;c<b.length;++c)b[c].marker.attachLine(a);a.markedSpans=b}}function Rc(a){return function(){var b=!this.cm.curOp;b&&db(this.cm);try{var c=a.apply(this,arguments)}finally{b&&eb(this.cm)}return c}}function Sc(a){return null!=a.height?a.height:(a.node.parentNode&&1==a.node.parentNode.nodeType||ee(a.cm.display.measure,ce("div",[a.node],null,"position: relative")),a.height=a.node.offsetHeight)}function Tc(a,b,c,d){var e=new mf(a,c,d);return e.noHScroll&&(a.display.alignWidgets=!0),kc(a,b,function(b){var c=b.widgets||(b.widgets=[]);if(null==e.insertAt?c.push(e):c.splice(Math.min(c.length-1,Math.max(0,e.insertAt)),0,e),e.line=b,!Nc(a.doc,b)||e.showIfHidden){var d=qd(a,b)<a.doc.scrollTop;nd(b,b.height+Sc(e)),d&&ic(a,0,e.height)}return!0}),e}function Uc(a,b,c,d){a.text=b,a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null),null!=a.order&&(a.order=null),Pc(a),Qc(a,c);var e=d?d(a):1;e!=a.height&&nd(a,e)}function Vc(a){a.parent=null,Pc(a)}function Wc(a,b,c,d,e){var f=c.flattenSpans;null==f&&(f=a.options.flattenSpans);var g,h=0,i=null,j=new wc(b,a.options.tabSize);for(""==b&&c.blankLine&&c.blankLine(d);!j.eol();)j.pos>a.options.maxHighlightLength?(f=!1,j.pos=Math.min(b.length,j.start+5e4),g=null):g=c.token(j,d),f&&i==g||(h<j.start&&e(j.start,i),h=j.start,i=g),j.start=j.pos;h<j.pos&&e(j.pos,i)}function Xc(a,b,c){var d=[a.state.modeGen];Wc(a,b.text,a.doc.mode,c,function(a,b){d.push(a,b)});for(var e=0;e<a.state.overlays.length;++e){var f=a.state.overlays[e],g=1,h=0;Wc(a,b.text,f.mode,!0,function(a,b){for(var c=g;a>h;){var e=d[g];e>a&&d.splice(g,1,a,d[g+1],e),g+=2,h=Math.min(a,e)}if(b)if(f.opaque)d.splice(c,g-c,a,b),g=c+2;else for(;g>c;c+=2){var i=d[c+1];d[c+1]=i?i+" "+b:b}})}return d}function Yc(a,b){return b.styles&&b.styles[0]==a.state.modeGen||(b.styles=Xc(a,b,b.stateAfter=J(a,od(b)))),b.styles}function Zc(a,b,c){var d=a.doc.mode,e=new wc(b.text,a.options.tabSize);for(""==b.text&&d.blankLine&&d.blankLine(c);!e.eol()&&e.pos<=a.options.maxHighlightLength;)d.token(e,c),e.start=e.pos}function $c(a){return a?of[a]||(of[a]="cm-"+a.replace(/ +/g," cm-")):null}function _c(a,b,c,d){for(var e,f=b,g=!0;e=Kc(f);)f=kd(a.doc,e.find().from.line);var h={pre:ce("pre"),col:0,pos:0,measure:null,measuredSomething:!1,cm:a,copyWidgets:d};f.textClass&&(h.pre.className=f.textClass);do{f.text&&(g=!1),h.measure=f==b&&c,h.pos=0,h.addToken=h.measure?bd:ad,(xe||Ae)&&a.getOption("lineWrapping")&&(h.addToken=cd(h.addToken));var i=ed(f,h,Yc(a,f));c&&f==b&&!h.measuredSomething&&(c[0]=h.pre.appendChild(je(a.display.measure)),h.measuredSomething=!0),i&&(f=kd(a.doc,i.to.line))}while(i);!c||h.measuredSomething||c[0]||(c[0]=h.pre.appendChild(g?ce("span"," "):je(a.display.measure))),h.pre.firstChild||Nc(a.doc,b)||h.pre.appendChild(document.createTextNode(" "));var j;if(c&&xe&&(j=rd(f))){var k=j.length-1;j[k].from==j[k].to&&--k;var l=j[k],m=j[k-1];if(l.from+1==l.to&&m&&l.level<m.level){var n=c[h.pos-1];n&&n.parentNode.insertBefore(n.measureRight=je(a.display.measure),n.nextSibling)}}return Md(a,"renderLine",a,b,h.pre),h.pre}function ad(a,b,c,d,e,f){if(b){if(pf.test(b))for(var g=document.createDocumentFragment(),h=0;;){pf.lastIndex=h;var i=pf.exec(b),j=i?i.index-h:b.length-h;if(j&&(g.appendChild(document.createTextNode(b.slice(h,h+j))),a.col+=j),!i)break;if(h+=j+1," "==i[0]){var k=a.cm.options.tabSize,l=k-a.col%k;g.appendChild(ce("span",Ud(l),"cm-tab")),a.col+=l}else{var m=ce("span","•","cm-invalidchar");m.title="\\u"+i[0].charCodeAt(0).toString(16),g.appendChild(m),a.col+=1}}else{a.col+=b.length;var g=document.createTextNode(b)}if(c||d||e||a.measure){var n=c||"";d&&(n+=d),e&&(n+=e);var m=ce("span",[g],n);return f&&(m.title=f),a.pre.appendChild(m)}a.pre.appendChild(g)}}function bd(a,b,c,d,e){for(var f=a.cm.options.lineWrapping,g=0;g<b.length;++g){var h=b.charAt(g),i=0==g;h>="���"&&"���">h&&g<b.length-1?(h=b.slice(g,g+2),++g):g&&f&&he(b,g)&&a.pre.appendChild(ce("wbr"));var j=a.measure[a.pos],k=a.measure[a.pos]=ad(a,h,c,i&&d,g==b.length-1&&e);j&&(k.leftSide=j.leftSide||j),xe&&f&&" "==h&&g&&!/\s/.test(b.charAt(g-1))&&g<b.length-1&&!/\s/.test(b.charAt(g+1))&&(k.style.whiteSpace="normal"),a.pos+=h.length}b.length&&(a.measuredSomething=!0)}function cd(a){function b(a){for(var b=" ",c=0;c<a.length-2;++c)b+=c%2?" ":" ";return b+=" "}return function(c,d,e,f,g,h){return a(c,d.replace(/ {3,}/,b),e,f,g,h)}}function dd(a,b,c,d){var e=!d&&c.replacedWith;if(e&&(a.copyWidgets&&(e=e.cloneNode(!0)),a.pre.appendChild(e),a.measure)){if(b)a.measure[a.pos]=e;else{var f=a.measure[a.pos]=je(a.cm.display.measure);"bookmark"!=c.type||c.insertLeft?a.pre.insertBefore(f,e):a.pre.appendChild(f)}a.measuredSomething=!0}a.pos+=b}function ed(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var g,h,i,j,k,l,m=e.length,n=0,o=1,p="",q=0;;){if(q==n){h=i=j=k="",l=null,q=1/0;for(var r=null,s=0;s<d.length;++s){var t=d[s],u=t.marker;t.from<=n&&(null==t.to||t.to>n)?(null!=t.to&&q>t.to&&(q=t.to,i=""),u.className&&(h+=" "+u.className),u.startStyle&&t.from==n&&(j+=" "+u.startStyle),u.endStyle&&t.to==q&&(i+=" "+u.endStyle),u.title&&!k&&(k=u.title),u.collapsed&&(!l||l.marker.size<u.size)&&(l=t)):t.from>n&&q>t.from&&(q=t.from),"bookmark"==u.type&&t.from==n&&u.replacedWith&&(r=u)}if(l&&(l.from||0)==n&&(dd(b,(null==l.to?m:l.to)-n,l.marker,null==l.from),null==l.to))return l.marker.find();r&&!l&&dd(b,0,r)}if(n>=m)break;for(var v=Math.min(m,q);;){if(p){var w=n+p.length;if(!l){var x=w>v?p.slice(0,v-n):p;b.addToken(b,x,g?g+h:h,j,n+x.length==q?i:"",k)}if(w>=v){p=p.slice(v-n),n=v;break}n=w,j=""}p=e.slice(f,f=c[o++]),g=$c(c[o++])}}else for(var o=1;o<c.length;o+=2)b.addToken(b,e.slice(f,f=c[o]),$c(c[o+1]))}function fd(a,b,c,d,e){function f(a){return c?c[a]:null}function g(a,c,d){Uc(a,c,d,e),Nd(a,"change",a,b)}var h=b.from,i=b.to,j=b.text,k=kd(a,h.line),l=kd(a,i.line),m=Vd(j),n=f(j.length-1),o=i.line-h.line;if(0==h.ch&&0==i.ch&&""==m){for(var p=0,q=j.length-1,r=[];q>p;++p)r.push(new nf(j[p],f(p),e));g(l,l.text,n),o&&a.remove(h.line,o),r.length&&a.insert(h.line,r)}else if(k==l)if(1==j.length)g(k,k.text.slice(0,h.ch)+m+k.text.slice(i.ch),n);else{for(var r=[],p=1,q=j.length-1;q>p;++p)r.push(new nf(j[p],f(p),e));r.push(new nf(m+k.text.slice(i.ch),n,e)),g(k,k.text.slice(0,h.ch)+j[0],f(0)),a.insert(h.line+1,r)}else if(1==j.length)g(k,k.text.slice(0,h.ch)+j[0]+l.text.slice(i.ch),f(0)),a.remove(h.line+1,o);else{g(k,k.text.slice(0,h.ch)+j[0],f(0)),g(l,m+l.text.slice(i.ch),n);for(var p=1,q=j.length-1,r=[];q>p;++p)r.push(new nf(j[p],f(p),e));o>1&&a.remove(h.line+1,o-1),a.insert(h.line+1,r)}Nd(a,"change",a,b),ac(a,d.anchor,d.head,null,!0)}function gd(a){this.lines=a,this.parent=null;for(var b=0,c=a.length,d=0;c>b;++b)a[b].parent=this,d+=a[b].height;this.height=d}function hd(a){this.children=a;for(var b=0,c=0,d=0,e=a.length;e>d;++d){var f=a[d];b+=f.chunkSize(),c+=f.height,f.parent=this}this.size=b,this.height=c,this.parent=null}function id(a,b,c){function d(a,e,f){if(a.linked)for(var g=0;g<a.linked.length;++g){var h=a.linked[g];if(h.doc!=e){var i=f&&h.sharedHist;(!c||i)&&(b(h.doc,i),d(h.doc,a,i))}}}d(a,null,!0)}function jd(a,b){if(b.cm)throw new Error("This document is already in use.");a.doc=b,b.cm=a,f(a),c(a),a.options.lineWrapping||l(a),a.options.mode=b.modeOption,ib(a)}function kd(a,b){for(b-=a.first;!a.lines;)for(var c=0;;++c){var d=a.children[c],e=d.chunkSize();if(e>b){a=d;break}b-=e}return a.lines[b]}function ld(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function md(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function nd(a,b){for(var c=b-a.height,d=a;d;d=d.parent)d.height+=c}function od(a){if(null==a.parent)return null;for(var b=a.parent,c=Xd(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first
3
- }function pd(a,b){var c=a.first;a:do{for(var d=0,e=a.children.length;e>d;++d){var f=a.children[d],g=f.height;if(g>b){a=f;continue a}b-=g,c+=f.chunkSize()}return c}while(!a.lines);for(var d=0,e=a.lines.length;e>d;++d){var h=a.lines[d],i=h.height;if(i>b)break;b-=i}return c+d}function qd(a,b){b=Mc(a.doc,b);for(var c=0,d=b.parent,e=0;e<d.lines.length;++e){var f=d.lines[e];if(f==b)break;c+=f.height}for(var g=d.parent;g;d=g,g=d.parent)for(var e=0;e<g.children.length;++e){var h=g.children[e];if(h==d)break;c+=h.height}return c}function rd(a){var b=a.order;return null==b&&(b=a.order=Jf(a.text)),b}function sd(a){return{done:[],undone:[],undoDepth:1/0,lastTime:0,lastOp:null,lastOrigin:null,generation:a||1,maxGeneration:a||1}}function td(a,b,c,d){var e=b["spans_"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b["spans_"+a.id]={}))[f]=c.markedSpans),++f})}function ud(a,b){var c={line:b.from.line,ch:b.from.ch},d={from:c,to:af(b),text:ld(a,b.from,b.to)};return td(a,d,b.from.line,b.to.line+1),id(a,function(a){td(a,d,b.from.line,b.to.line+1)},!0),d}function vd(a,b,c,d){var e=a.history;e.undone.length=0;var f=+new Date,g=Vd(e.done);if(g&&(e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&("+"==b.origin.charAt(0)&&a.cm&&e.lastTime>f-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))){var h=Vd(g.changes);Tb(b.from,b.to)&&Tb(b.from,h.to)?h.to=af(b):g.changes.push(ud(a,b)),g.anchorAfter=c.anchor,g.headAfter=c.head}else for(g={changes:[ud(a,b)],generation:e.generation,anchorBefore:a.sel.anchor,headBefore:a.sel.head,anchorAfter:c.anchor,headAfter:c.head},e.done.push(g),e.generation=++e.maxGeneration;e.done.length>e.undoDepth;)e.done.shift();e.lastTime=f,e.lastOp=d,e.lastOrigin=b.origin}function wd(a){if(!a)return null;for(var b,c=0;c<a.length;++c)a[c].marker.explicitlyCleared?b||(b=a.slice(0,c)):b&&b.push(a[c]);return b?b.length?b:null:a}function xd(a,b){var c=b["spans_"+a.id];if(!c)return null;for(var d=0,e=[];d<b.text.length;++d)e.push(wd(c[d]));return e}function yd(a,b){for(var c=0,d=[];c<a.length;++c){var e=a[c],f=e.changes,g=[];d.push({changes:g,anchorBefore:e.anchorBefore,headBefore:e.headBefore,anchorAfter:e.anchorAfter,headAfter:e.headAfter});for(var h=0;h<f.length;++h){var i,j=f[h];if(g.push({from:j.from,to:j.to,text:j.text}),b)for(var k in j)(i=k.match(/^spans_(\d+)$/))&&Xd(b,Number(i[1]))>-1&&(Vd(g)[k]=j[k],delete j[k])}}return d}function zd(a,b,c,d){c<a.line?a.line+=d:b<a.line&&(a.line=b,a.ch=0)}function Ad(a,b,c,d){for(var e=0;e<a.length;++e){for(var f=a[e],g=!0,h=0;h<f.changes.length;++h){var i=f.changes[h];if(f.copied||(i.from=Vb(i.from),i.to=Vb(i.to)),c<i.from.line)i.from.line+=d,i.to.line+=d;else if(b<=i.to.line){g=!1;break}}f.copied||(f.anchorBefore=Vb(f.anchorBefore),f.headBefore=Vb(f.headBefore),f.anchorAfter=Vb(f.anchorAfter),f.readAfter=Vb(f.headAfter),f.copied=!0),g?(zd(f.anchorBefore),zd(f.headBefore),zd(f.anchorAfter),zd(f.headAfter)):(a.splice(0,e+1),e=0)}}function Bd(a,b){var c=b.from.line,d=b.to.line,e=b.text.length-(d-c)-1;Ad(a.done,c,d,e),Ad(a.undone,c,d,e)}function Cd(){Hd(this)}function Dd(a){return a.stop||(a.stop=Cd),a}function Ed(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function Fd(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0}function Gd(a){return null!=a.defaultPrevented?a.defaultPrevented:0==a.returnValue}function Hd(a){Ed(a),Fd(a)}function Id(a){return a.target||a.srcElement}function Jd(a){var b=a.which;return null==b&&(1&a.button?b=1:2&a.button?b=3:4&a.button&&(b=2)),Le&&a.ctrlKey&&1==b&&(b=3),b}function Kd(a,b,c){if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var d=a._handlers||(a._handlers={}),e=d[b]||(d[b]=[]);e.push(c)}}function Ld(a,b,c){if(a.removeEventListener)a.removeEventListener(b,c,!1);else if(a.detachEvent)a.detachEvent("on"+b,c);else{var d=a._handlers&&a._handlers[b];if(!d)return;for(var e=0;e<d.length;++e)if(d[e]==c){d.splice(e,1);break}}}function Md(a,b){var c=a._handlers&&a._handlers[b];if(c)for(var d=Array.prototype.slice.call(arguments,2),e=0;e<c.length;++e)c[e].apply(null,d)}function Nd(a,b){function c(a){return function(){a.apply(null,e)}}var d=a._handlers&&a._handlers[b];if(d){var e=Array.prototype.slice.call(arguments,2);uf||(++vf,uf=[],setTimeout(Pd,0));for(var f=0;f<d.length;++f)uf.push(c(d[f]))}}function Od(a,b,c){return Md(a,c||b.type,a,b),Gd(b)||b.codemirrorIgnore}function Pd(){--vf;var a=uf;uf=null;for(var b=0;b<a.length;++b)a[b]()}function Qd(a,b){var c=a._handlers&&a._handlers[b];return c&&c.length>0}function Rd(a){a.prototype.on=function(a,b){Kd(this,a,b)},a.prototype.off=function(a,b){Ld(this,a,b)}}function Sd(){this.id=null}function Td(a,b,c,d,e){null==b&&(b=a.search(/[^\s\u00a0]/),-1==b&&(b=a.length));for(var f=d||0,g=e||0;b>f;++f)" "==a.charAt(f)?g+=c-g%c:++g;return g}function Ud(a){for(;yf.length<=a;)yf.push(Vd(yf)+" ");return yf[a]}function Vd(a){return a[a.length-1]}function Wd(a){if(Je)a.selectionStart=0,a.selectionEnd=a.value.length;else try{a.select()}catch(b){}}function Xd(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0,d=a.length;d>c;++c)if(a[c]==b)return c;return-1}function Yd(a,b){function c(){}c.prototype=a;var d=new c;return b&&Zd(b,d),d}function Zd(a,b){b||(b={});for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function $d(a){for(var b=[],c=0;a>c;++c)b.push(void 0);return b}function _d(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function ae(a){return/\w/.test(a)||a>"€"&&(a.toUpperCase()!=a.toLowerCase()||zf.test(a))}function be(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function ce(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)fe(e,b);else if(b)for(var f=0;f<b.length;++f)e.appendChild(b[f]);return e}function de(a){for(var b=a.childNodes.length;b>0;--b)a.removeChild(a.firstChild);return a}function ee(a,b){return de(a).appendChild(b)}function fe(a,b){ze?(a.innerHTML="",a.appendChild(document.createTextNode(b))):a.textContent=b}function ge(a){return a.getBoundingClientRect()}function he(){return!1}function ie(a){if(null!=Cf)return Cf;var b=ce("div",null,null,"width: 50px; height: 50px; overflow-x: scroll");return ee(a,b),b.offsetWidth&&(Cf=b.offsetHeight-b.clientHeight),Cf||0}function je(a){if(null==Df){var b=ce("span","​");ee(a,ce("span",[b,document.createTextNode("x")])),0!=a.firstChild.offsetHeight&&(Df=b.offsetWidth<=1&&b.offsetHeight>2&&!ye)}return Df?ce("span","​"):ce("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px")}function ke(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;f<a.length;++f){var g=a[f];(g.from<c&&g.to>b||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function le(a){return a.level%2?a.to:a.from}function me(a){return a.level%2?a.from:a.to}function ne(a){var b=rd(a);return b?le(b[0]):0}function oe(a){var b=rd(a);return b?me(Vd(b)):a.text.length}function pe(a,b){var c=kd(a.doc,b),d=Mc(a.doc,c);d!=c&&(b=od(d));var e=rd(d),f=e?e[0].level%2?oe(d):ne(d):0;return Sb(b,f)}function qe(a,b){for(var c,d;c=Lc(d=kd(a.doc,b));)b=c.find().to.line;var e=rd(d),f=e?e[0].level%2?ne(d):oe(d):d.text.length;return Sb(b,f)}function re(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function se(a,b){for(var c,d=0;d<a.length;++d){var e=a[d];if(e.from<b&&e.to>b)return If=null,d;if(e.from==b||e.to==b){if(null!=c)return re(a,e.level,a[c].level)?(If=c,d):(If=d,c);c=d}}return If=null,c}function te(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&Af.test(a.text.charAt(b)));return b}function ue(a,b,c,d){var e=rd(a);if(!e)return ve(a,b,c,d);for(var f=se(e,b),g=e[f],h=te(a,b,g.level%2?-c:c,d);;){if(h>g.from&&h<g.to)return h;if(h==g.from||h==g.to)return se(e,h)==f?h:(g=e[f+=c],c>0==g.level%2?g.to:g.from);if(g=e[f+=c],!g)return null;h=c>0==g.level%2?te(a,g.to,-1,d):te(a,g.from,1,d)}}function ve(a,b,c,d){var e=b+c;if(d)for(;e>0&&Af.test(a.text.charAt(e));)e+=c;return 0>e||e>a.text.length?null:e}var we=/gecko\/\d/i.test(navigator.userAgent),xe=/MSIE \d/.test(navigator.userAgent),ye=xe&&(null==document.documentMode||document.documentMode<8),ze=xe&&(null==document.documentMode||document.documentMode<9),Ae=/WebKit\//.test(navigator.userAgent),Be=Ae&&/Qt\/\d+\.\d+/.test(navigator.userAgent),Ce=/Chrome\//.test(navigator.userAgent),De=/Opera\//.test(navigator.userAgent),Ee=/Apple Computer/.test(navigator.vendor),Fe=/KHTML\//.test(navigator.userAgent),Ge=/Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent),He=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent),Ie=/PhantomJS/.test(navigator.userAgent),Je=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent),Ke=Je||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),Le=Je||/Mac/.test(navigator.platform),Me=/windows/i.test(navigator.platform),Ne=De&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);Ne&&(Ne=Number(Ne[1])),Ne&&Ne>=15&&(De=!1,Ae=!0);var Oe,Pe,Qe,Re=Le&&(Be||De&&(null==Ne||12.11>Ne)),Se=we||xe&&!ze,Te=!1,Ue=!1,Ve=0,We=0,Xe=0,Ye=null;xe?Ye=-.53:we?Ye=15:Ce?Ye=-.7:Ee&&(Ye=-1/3);var Ze,$e,_e=null,af=a.changeEnd=function(a){return a.text?Sb(a.from.line+a.text.length-1,Vd(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};a.Pos=Sb,a.prototype={constructor:a,focus:function(){window.focus(),nb(this),Fb(this),kb(this)},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||"mode"==a)&&(c[a]=b,bf.hasOwnProperty(a)&&fb(this,bf[a])(this,b,d))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?"push":"unshift"](a)},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;c<b.length;++c)if(b[c]==a||"string"!=typeof b[c]&&b[c].name==a)return b.splice(c,1),!0},addOverlay:fb(null,function(b,c){var d=b.token?b:a.getMode(this.options,b);if(d.startState)throw new Error("Overlays may not be stateful.");this.state.overlays.push({mode:d,modeSpec:b,opaque:c&&c.opaque}),this.state.modeGen++,ib(this)}),removeOverlay:fb(null,function(a){for(var b=this.state.overlays,c=0;c<b.length;++c){var d=b[c].modeSpec;if(d==a||"string"==typeof a&&d.name==a)return b.splice(c,1),this.state.modeGen++,ib(this),void 0}}),indentLine:fb(null,function(a,b,c){"string"!=typeof b&&"number"!=typeof b&&(b=null==b?this.options.smartIndent?"smart":"prev":b?"add":"subtract"),Zb(this.doc,a)&&jc(this,a,b,c)}),indentSelection:fb(null,function(a){var b=this.doc.sel;if(Tb(b.from,b.to))return jc(this,b.from.line,a);for(var c=b.to.line-(b.to.ch?0:1),d=b.from.line;c>=d;++d)jc(this,d,a)}),getTokenAt:function(a,b){var c=this.doc;a=Xb(c,a);for(var d=J(this,a.line,b),e=this.doc.mode,f=kd(c,a.line),g=new wc(f.text,this.options.tabSize);g.pos<a.ch&&!g.eol();){g.start=g.pos;var h=e.token(g,d)}return{start:g.start,end:g.pos,string:g.current(),className:h||null,type:h||null,state:d}},getTokenTypeAt:function(a){a=Xb(this.doc,a);var b=Yc(this,kd(this.doc,a.line)),c=0,d=(b.length-1)/2,e=a.ch;if(0==e)return b[2];for(;;){var f=c+d>>1;if((f?b[2*f-1]:0)>=e)d=f;else{if(!(b[2*f+1]<e))return b[2*f+2];c=f+1}}},getModeAt:function(b){var c=this.doc.mode;return c.innerMode?a.innerMode(c,this.getTokenAt(b).state).mode:c},getHelper:function(a,b){if(jf.hasOwnProperty(b)){var c=jf[b],d=this.getModeAt(a);return d[b]&&c[d[b]]||d.helperType&&c[d.helperType]||c[d.name]}},getStateAfter:function(a,b){var c=this.doc;return a=Wb(c,null==a?c.first+c.size-1:a),J(this,a+1,b)},cursorCoords:function(a,b){var c,d=this.doc.sel;return c=null==a?d.head:"object"==typeof a?Xb(this.doc,a):a?d.from:d.to,Z(this,c,b||"page")},charCoords:function(a,b){return Y(this,Xb(this.doc,a),b||"page")},coordsChar:function(a,b){return a=X(this,a,b||"page"),_(this,a.left,a.top)},lineAtHeight:function(a,b){return a=X(this,{top:a,left:0},b||"page").top,pd(this.doc,a+this.display.viewOffset)},heightAtLine:function(a,b){var c=!1,d=this.doc.first+this.doc.size-1;a<this.doc.first?a=this.doc.first:a>d&&(a=d,c=!0);var e=kd(this.doc,a);return W(this,kd(this.doc,a),{top:0,left:0},b||"page").top+(c?e.height:0)},defaultTextHeight:function(){return bb(this.display)},defaultCharWidth:function(){return cb(this.display)},setGutterMarker:fb(null,function(a,b,c){return kc(this,a,function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&be(d)&&(a.gutterMarkers=null),!0})}),clearGutter:fb(null,function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,ib(b,d,d+1),be(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),addLineClass:fb(null,function(a,b,c){return kc(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass";if(a[d]){if(new RegExp("(?:^|\\s)"+c+"(?:$|\\s)").test(a[d]))return!1;a[d]+=" "+c}else a[d]=c;return!0})}),removeLineClass:fb(null,function(a,b,c){return kc(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass",e=a[d];if(!e)return!1;if(null==c)a[d]=null;else{var f=e.match(new RegExp("(?:^|\\s+)"+c+"(?:$|\\s+)"));if(!f)return!1;var g=f.index+f[0].length;a[d]=e.slice(0,f.index)+(f.index&&g!=e.length?" ":"")+e.slice(g)||null}return!0})}),addLineWidget:fb(null,function(a,b,c){return Tc(this,a,b,c)}),removeLineWidget:function(a){a.clear()},lineInfo:function(a){if("number"==typeof a){if(!Zb(this.doc,a))return null;var b=a;if(a=kd(this.doc,a),!a)return null}else{var b=od(a);if(null==b)return null}return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},getViewport:function(){return{from:this.display.showingFrom,to:this.display.showingTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=Z(this,Xb(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position="absolute",f.sizer.appendChild(b),"over"==d)g=a.top;else if("above"==d||"near"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);("above"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+"px",b.style.left=b.style.right="","right"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.style.right="0px"):("left"==e?h=0:"middle"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+"px"),c&&fc(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:fb(null,Db),execCommand:function(a){return kf[a](this)},findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=Xb(this.doc,a);b>f&&(g=lc(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:fb(null,function(a,b){var c,d=this.doc.sel;c=d.shift||d.extend||Tb(d.from,d.to)?lc(this.doc,d.head,a,b,this.options.rtlMoveVisually):0>a?d.from:d.to,$b(this.doc,c,c,a)}),deleteH:fb(null,function(a,b){var c=this.doc.sel;Tb(c.from,c.to)?Rb(this.doc,"",c.from,lc(this.doc,c.head,a,b,!1),"+delete"):Rb(this.doc,"",c.from,c.to,"+delete"),this.curOp.userSelChange=!0}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=Xb(this.doc,a);b>g;++g){var i=Z(this,h,"div");if(null==f?f=i.left:i.left=f,h=mc(this,i,e,c),h.hitSide)break}return h},moveV:fb(null,function(a,b){var c=this.doc.sel,d=Z(this,c.head,"div");null!=c.goalColumn&&(d.left=c.goalColumn);var e=mc(this,d,a,b);"page"==b&&ic(this,0,Y(this,e,"div").top-d.top),$b(this.doc,e,e,a),c.goalColumn=d.left}),toggleOverwrite:function(a){(null==a||a!=this.state.overwrite)&&((this.state.overwrite=!this.state.overwrite)?this.display.cursor.className+=" CodeMirror-overwrite":this.display.cursor.className=this.display.cursor.className.replace(" CodeMirror-overwrite",""))},hasFocus:function(){return this.state.focused},scrollTo:fb(null,function(a,b){hc(this,a,b)}),getScrollInfo:function(){var a=this.display.scroller,b=wf;return{left:a.scrollLeft,top:a.scrollTop,height:a.scrollHeight-b,width:a.scrollWidth-b,clientHeight:a.clientHeight-b,clientWidth:a.clientWidth-b}},scrollIntoView:fb(null,function(a,b){"number"==typeof a&&(a=Sb(a,0)),b||(b=0);var c=a;a&&null==a.line||(this.curOp.scrollToPos=a?Xb(this.doc,a):this.doc.sel.head,this.curOp.scrollToPosMargin=b,c=Z(this,this.curOp.scrollToPos));var d=gc(this,c.left,c.top-b,c.right,c.bottom+b);hc(this,d.scrollLeft,d.scrollTop)}),setSize:fb(null,function(a,b){function c(a){return"number"==typeof a||/^\d+$/.test(String(a))?a+"px":a}null!=a&&(this.display.wrapper.style.width=c(a)),null!=b&&(this.display.wrapper.style.height=c(b)),this.options.lineWrapping&&(this.display.measureLineCache.length=this.display.measureLineCachePos=0),this.curOp.forceUpdate=!0}),operation:function(a){return hb(this,a)},refresh:fb(null,function(){T(this),hc(this,this.doc.scrollLeft,this.doc.scrollTop),ib(this)}),swapDoc:fb(null,function(a){var b=this.doc;return b.cm=null,jd(this,a),T(this),mb(this,!0),hc(this,a.scrollLeft,a.scrollTop),b}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Rd(a);var bf=a.optionHandlers={},cf=a.defaults={},df=a.Init={toString:function(){return"CodeMirror.Init"}};pc("value","",function(a,b){a.setValue(b)},!0),pc("mode",null,function(a,b){a.doc.modeOption=b,c(a)},!0),pc("indentUnit",2,c,!0),pc("indentWithTabs",!1),pc("smartIndent",!0),pc("tabSize",4,function(a){c(a),T(a),ib(a)},!0),pc("electricChars",!0),pc("rtlMoveVisually",!Me),pc("theme","default",function(a){h(a),i(a)},!0),pc("keyMap","default",g),pc("extraKeys",null),pc("onKeyEvent",null),pc("onDragEvent",null),pc("lineWrapping",!1,d,!0),pc("gutters",[],function(a){m(a.options),i(a)},!0),pc("fixedGutter",!0,function(a,b){a.display.gutters.style.left=b?s(a.display)+"px":"0",a.refresh()},!0),pc("coverGutterNextToScrollbar",!1,n,!0),pc("lineNumbers",!1,function(a){m(a.options),i(a)},!0),pc("firstLineNumber",1,i,!0),pc("lineNumberFormatter",function(a){return a},i,!0),pc("showCursorWhenSelecting",!1,C,!0),pc("readOnly",!1,function(a,b){"nocursor"==b?(Gb(a),a.display.input.blur()):b||mb(a,!0)}),pc("dragDrop",!0),pc("cursorBlinkRate",530),pc("cursorScrollMargin",0),pc("cursorHeight",1),pc("workTime",100),pc("workDelay",100),pc("flattenSpans",!0),pc("pollInterval",100),pc("undoDepth",40,function(a,b){a.doc.history.undoDepth=b}),pc("historyEventDelay",500),pc("viewportMargin",10,function(a){a.refresh()},!0),pc("maxHighlightLength",1e4,function(a){c(a),a.refresh()},!0),pc("moveInputWithCursor",!0,function(a,b){b||(a.display.inputDiv.style.top=a.display.inputDiv.style.left=0)}),pc("tabindex",null,function(a,b){a.display.input.tabIndex=b||""}),pc("autofocus",null);var ef=a.modes={},ff=a.mimeModes={};a.defineMode=function(b,c){if(a.defaults.mode||"null"==b||(a.defaults.mode=b),arguments.length>2){c.dependencies=[];for(var d=2;d<arguments.length;++d)c.dependencies.push(arguments[d])}ef[b]=c},a.defineMIME=function(a,b){ff[a]=b},a.resolveMode=function(b){if("string"==typeof b&&ff.hasOwnProperty(b))b=ff[b];else if(b&&"string"==typeof b.name&&ff.hasOwnProperty(b.name)){var c=ff[b.name];b=Yd(c,b),b.name=c.name}else if("string"==typeof b&&/^[\w\-]+\/[\w\-]+\+xml$/.test(b))return a.resolveMode("application/xml");return"string"==typeof b?{name:b}:b||{name:"null"}},a.getMode=function(b,c){var c=a.resolveMode(c),d=ef[c.name];if(!d)return a.getMode(b,"text/plain");var e=d(b,c);if(gf.hasOwnProperty(c.name)){var f=gf[c.name];for(var g in f)f.hasOwnProperty(g)&&(e.hasOwnProperty(g)&&(e["_"+g]=e[g]),e[g]=f[g])}return e.name=c.name,e},a.defineMode("null",function(){return{token:function(a){a.skipToEnd()}}}),a.defineMIME("text/plain","null");var gf=a.modeExtensions={};a.extendMode=function(a,b){var c=gf.hasOwnProperty(a)?gf[a]:gf[a]={};Zd(b,c)},a.defineExtension=function(b,c){a.prototype[b]=c},a.defineDocExtension=function(a,b){rf.prototype[a]=b},a.defineOption=pc;var hf=[];a.defineInitHook=function(a){hf.push(a)};var jf=a.helpers={};a.registerHelper=function(b,c,d){jf.hasOwnProperty(b)||(jf[b]=a[b]={}),jf[b][c]=d},a.isWordChar=ae,a.copyState=qc,a.startState=rc,a.innerMode=function(a,b){for(;a.innerMode;){var c=a.innerMode(b);if(!c||c.mode==a)break;b=c.state,a=c.mode}return c||{mode:a,state:b}};var kf=a.commands={selectAll:function(a){a.setSelection(Sb(a.firstLine(),0),Sb(a.lastLine()))},killLine:function(a){var b=a.getCursor(!0),c=a.getCursor(!1),d=!Tb(b,c);d||a.getLine(b.line).length!=b.ch?a.replaceRange("",b,d?c:Sb(b.line),"+delete"):a.replaceRange("",b,Sb(b.line+1,0),"+delete")},deleteLine:function(a){var b=a.getCursor().line;a.replaceRange("",Sb(b,0),Sb(b),"+delete")},delLineLeft:function(a){var b=a.getCursor();a.replaceRange("",Sb(b.line,0),b,"+delete")},undo:function(a){a.undo()},redo:function(a){a.redo()},goDocStart:function(a){a.extendSelection(Sb(a.firstLine(),0))},goDocEnd:function(a){a.extendSelection(Sb(a.lastLine()))},goLineStart:function(a){a.extendSelection(pe(a,a.getCursor().line))},goLineStartSmart:function(a){var b=a.getCursor(),c=pe(a,b.line),d=a.getLineHandle(c.line),e=rd(d);if(e&&0!=e[0].level)a.extendSelection(c);else{var f=Math.max(0,d.text.search(/\S/)),g=b.line==c.line&&b.ch<=f&&b.ch;a.extendSelection(Sb(c.line,g?0:f))}},goLineEnd:function(a){a.extendSelection(qe(a,a.getCursor().line))},goLineRight:function(a){var b=a.charCoords(a.getCursor(),"div").top+5;a.extendSelection(a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:b},"div"))},goLineLeft:function(a){var b=a.charCoords(a.getCursor(),"div").top+5;a.extendSelection(a.coordsChar({left:0,top:b},"div"))},goLineUp:function(a){a.moveV(-1,"line")},goLineDown:function(a){a.moveV(1,"line")},goPageUp:function(a){a.moveV(-1,"page")},goPageDown:function(a){a.moveV(1,"page")},goCharLeft:function(a){a.moveH(-1,"char")},goCharRight:function(a){a.moveH(1,"char")},goColumnLeft:function(a){a.moveH(-1,"column")},goColumnRight:function(a){a.moveH(1,"column")},goWordLeft:function(a){a.moveH(-1,"word")},goGroupRight:function(a){a.moveH(1,"group")},goGroupLeft:function(a){a.moveH(-1,"group")},goWordRight:function(a){a.moveH(1,"word")},delCharBefore:function(a){a.deleteH(-1,"char")},delCharAfter:function(a){a.deleteH(1,"char")},delWordBefore:function(a){a.deleteH(-1,"word")},delWordAfter:function(a){a.deleteH(1,"word")},delGroupBefore:function(a){a.deleteH(-1,"group")},delGroupAfter:function(a){a.deleteH(1,"group")},indentAuto:function(a){a.indentSelection("smart")},indentMore:function(a){a.indentSelection("add")},indentLess:function(a){a.indentSelection("subtract")},insertTab:function(a){a.replaceSelection(" ","end","+input")},defaultTab:function(a){a.somethingSelected()?a.indentSelection("add"):a.replaceSelection(" ","end","+input")},transposeChars:function(a){var b=a.getCursor(),c=a.getLine(b.line);b.ch>0&&b.ch<c.length-1&&a.replaceRange(c.charAt(b.ch)+c.charAt(b.ch-1),Sb(b.line,b.ch-1),Sb(b.line,b.ch+1))},newlineAndIndent:function(a){fb(a,function(){a.replaceSelection("\n","end","+input"),a.indentLine(a.getCursor().line,null,!0)})()},toggleOverwrite:function(a){a.toggleOverwrite()}},lf=a.keyMap={};lf.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite"},lf.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Alt-Up":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Down":"goDocEnd","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore",fallthrough:"basic"},lf.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineStart","Cmd-Right":"goLineEnd","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":"delLineLeft",fallthrough:["basic","emacsy"]},lf["default"]=Le?lf.macDefault:lf.pcDefault,lf.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"},a.lookupKey=tc,a.isModifierKey=uc,a.keyName=vc,a.fromTextArea=function(b,c){function d(){b.value=j.getValue()}if(c||(c={}),c.value=b.value,!c.tabindex&&b.tabindex&&(c.tabindex=b.tabindex),!c.placeholder&&b.placeholder&&(c.placeholder=b.placeholder),null==c.autofocus){var e=document.body;try{e=document.activeElement}catch(f){}c.autofocus=e==b||null!=b.getAttribute("autofocus")&&e==document.body}if(b.form&&(Kd(b.form,"submit",d),!c.leaveSubmitMethodAlone)){var g=b.form,h=g.submit;try{var i=g.submit=function(){d(),g.submit=h,g.submit(),g.submit=i}}catch(f){}}b.style.display="none";var j=a(function(a){b.parentNode.insertBefore(a,b.nextSibling)},c);return j.save=d,j.getTextArea=function(){return b},j.toTextArea=function(){d(),b.parentNode.removeChild(j.getWrapperElement()),b.style.display="",b.form&&(Ld(b.form,"submit",d),"function"==typeof b.form.submit&&(b.form.submit=h))},j},wc.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return 0==this.pos},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.pos<this.string.length?this.string.charAt(this.pos++):void 0},eat:function(a){var b=this.string.charAt(this.pos);if("string"==typeof a)var c=b==a;else var c=b&&(a.test?a.test(b):a(b));return c?(++this.pos,b):void 0},eatWhile:function(a){for(var b=this.pos;this.eat(a););return this.pos>b},eatSpace:function(){for(var a=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);return b>-1?(this.pos=b,!0):void 0},backUp:function(a){this.pos-=a},column:function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=Td(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue},indentation:function(){return Td(this.string,null,this.tabSize)},match:function(a,b,c){if("string"!=typeof a){var d=this.string.slice(this.pos).match(a);return d&&d.index>0?null:(d&&b!==!1&&(this.pos+=d[0].length),d)}var e=function(a){return c?a.toLowerCase():a},f=this.string.substr(this.pos,a.length);return e(f)==e(a)?(b!==!1&&(this.pos+=a.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)}},a.StringStream=wc,a.TextMarker=xc,Rd(xc),xc.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&db(a),Qd(this,"clear")){var c=this.find();c&&Nd(this,"clear",c.from,c.to)}for(var d=null,e=null,f=0;f<this.lines.length;++f){var g=this.lines[f],h=Bc(g.markedSpans,this);null!=h.to&&(e=od(g)),g.markedSpans=Cc(g.markedSpans,h),null!=h.from?d=od(g):this.collapsed&&!Nc(this.doc,g)&&a&&nd(g,bb(a.display))}if(a&&this.collapsed&&!a.options.lineWrapping)for(var f=0;f<this.lines.length;++f){var i=Mc(a.doc,this.lines[f]),j=k(a.doc,i);j>a.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&ib(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&bc(a)),b&&eb(a)}},xc.prototype.find=function(){for(var a,b,c=0;c<this.lines.length;++c){var d=this.lines[c],e=Bc(d.markedSpans,this);if(null!=e.from||null!=e.to){var f=od(d);null!=e.from&&(a=Sb(f,e.from)),null!=e.to&&(b=Sb(f,e.to))}}return"bookmark"==this.type?a:a&&{from:a,to:b}},xc.prototype.changed=function(){var a=this.find(),b=this.doc.cm;if(a&&b){var c=kd(this.doc,a.from.line);if(P(b,c),a.from.line>=b.display.showingFrom&&a.from.line<b.display.showingTo){for(var d=b.display.lineDiv.firstChild;d;d=d.nextSibling)if(d.lineObj==c){d.offsetHeight!=c.height&&nd(c,d.offsetHeight);break}hb(b,function(){b.curOp.selectionChanged=b.curOp.forceUpdate=b.curOp.updateMaxLine=!0})}}},xc.prototype.attachLine=function(a){if(!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;b.maybeHiddenMarkers&&-1!=Xd(b.maybeHiddenMarkers,this)||(b.maybeUnhiddenMarkers||(b.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(a)},xc.prototype.detachLine=function(a){if(this.lines.splice(Xd(this.lines,a),1),!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;(b.maybeHiddenMarkers||(b.maybeHiddenMarkers=[])).push(this)}},a.SharedTextMarker=zc,Rd(zc),zc.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var a=0;a<this.markers.length;++a)this.markers[a].clear();Nd(this,"clear")}},zc.prototype.find=function(){return this.primary.find()};var mf=a.LineWidget=function(a,b,c){if(c)for(var d in c)c.hasOwnProperty(d)&&(this[d]=c[d]);this.cm=a,this.node=b};Rd(mf),mf.prototype.clear=Rc(function(){var a=this.line.widgets,b=od(this.line);if(null!=b&&a){for(var c=0;c<a.length;++c)a[c]==this&&a.splice(c--,1);a.length||(this.line.widgets=null);var d=qd(this.cm,this.line)<this.cm.doc.scrollTop;nd(this.line,Math.max(0,this.line.height-Sc(this))),d&&ic(this.cm,0,-this.height),ib(this.cm,b,b+1)}}),mf.prototype.changed=Rc(function(){var a=this.height;this.height=null;var b=Sc(this)-a;if(b){nd(this.line,this.line.height+b);var c=od(this.line);ib(this.cm,c,c+1)}});var nf=a.Line=function(a,b,c){this.text=a,Qc(this,b),this.height=c?c(this):1};Rd(nf);var of={},pf=/[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;gd.prototype={chunkSize:function(){return this.lines.length},removeInner:function(a,b){for(var c=a,d=a+b;d>c;++c){var e=this.lines[c];this.height-=e.height,Vc(e),Nd(e,"delete")}this.lines.splice(a,b)},collapse:function(a){a.splice.apply(a,[a.length,0].concat(this.lines))},insertInner:function(a,b,c){this.height+=c,this.lines=this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var d=0,e=b.length;e>d;++d)b[d].parent=this},iterN:function(a,b,c){for(var d=a+b;d>a;++a)if(c(this.lines[a]))return!0}},hd.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){this.size-=b;for(var c=0;c<this.children.length;++c){var d=this.children[c],e=d.chunkSize();if(e>a){var f=Math.min(b,e-a),g=d.height;if(d.removeInner(a,f),this.height-=g-d.height,e==f&&(this.children.splice(c--,1),d.parent=null),0==(b-=f))break;a=0}else a-=e}if(this.size-b<25){var h=[];this.collapse(h),this.children=[new gd(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0,c=this.children.length;c>b;++b)this.children[b].collapse(a)},insertInner:function(a,b,c){this.size+=b.length,this.height+=c;for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>=a){if(f.insertInner(a,b,c),f.lines&&f.lines.length>50){for(;f.lines.length>50;){var h=f.lines.splice(f.lines.length-25,25),i=new gd(h);f.height-=i.height,this.children.splice(d+1,0,i),i.parent=this}this.maybeSpill()}break}a-=g}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new hd(b);if(a.parent){a.size-=c.size,a.height-=c.height;var d=Xd(a.parent.children,a);a.parent.children.splice(d+1,0,c)}else{var e=new hd(a.children);e.parent=a,a.children=[e,c],a=e}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();
4
- if(g>a){var h=Math.min(b,g-a);if(f.iterN(a,h,c))return!0;if(0==(b-=h))break;a=0}else a-=g}}};var qf=0,rf=a.Doc=function(a,b,c){if(!(this instanceof rf))return new rf(a,b,c);null==c&&(c=0),hd.call(this,[new gd([new nf("",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.history=sd(),this.cleanGeneration=1,this.frontier=c;var d=Sb(c,0);this.sel={from:d,to:d,head:d,anchor:d,shift:!1,extend:!1,goalColumn:null},this.id=++qf,this.modeOption=b,"string"==typeof a&&(a=Ef(a)),fd(this,{from:d,to:d,text:a},null,{head:d,anchor:d})};rf.prototype=Yd(hd.prototype,{constructor:rf,iter:function(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0,e=b.length;e>d;++d)c+=b[d].height;this.insertInner(a-this.first,b,c)},remove:function(a,b){this.removeInner(a-this.first,b)},getValue:function(a){var b=md(this,this.first,this.first+this.size);return a===!1?b:b.join(a||"\n")},setValue:function(a){var b=Sb(this.first,0),c=this.first+this.size-1;Lb(this,{from:b,to:Sb(c,kd(this,c).text.length),text:Ef(a),origin:"setValue"},{head:b,anchor:b},!0)},replaceRange:function(a,b,c,d){b=Xb(this,b),c=c?Xb(this,c):b,Rb(this,a,b,c,d)},getRange:function(a,b,c){var d=ld(this,Xb(this,a),Xb(this,b));return c===!1?d:d.join(c||"\n")},getLine:function(a){var b=this.getLineHandle(a);return b&&b.text},setLine:function(a,b){Zb(this,a)&&Rb(this,b,Sb(a,0),Xb(this,Sb(a)))},removeLine:function(a){a?Rb(this,"",Xb(this,Sb(a-1)),Xb(this,Sb(a))):Rb(this,"",Sb(0,0),Xb(this,Sb(1,0)))},getLineHandle:function(a){return Zb(this,a)?kd(this,a):void 0},getLineNumber:function(a){return od(a)},getLineHandleVisualStart:function(a){return"number"==typeof a&&(a=kd(this,a)),Mc(this,a)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(a){return Xb(this,a)},getCursor:function(a){var b,c=this.sel;return b=null==a||"head"==a?c.head:"anchor"==a?c.anchor:"end"==a||a===!1?c.to:c.from,Vb(b)},somethingSelected:function(){return!Tb(this.sel.head,this.sel.anchor)},setCursor:gb(function(a,b,c){var d=Xb(this,"number"==typeof a?Sb(a,b||0):a);c?$b(this,d):ac(this,d,d)}),setSelection:gb(function(a,b){ac(this,Xb(this,a),Xb(this,b||a))}),extendSelection:gb(function(a,b){$b(this,Xb(this,a),b&&Xb(this,b))}),getSelection:function(a){return this.getRange(this.sel.from,this.sel.to,a)},replaceSelection:function(a,b,c){Lb(this,{from:this.sel.from,to:this.sel.to,text:Ef(a),origin:c},b||"around")},undo:gb(function(){Nb(this,"undo")}),redo:gb(function(){Nb(this,"redo")}),setExtending:function(a){this.sel.extend=a},historySize:function(){var a=this.history;return{undo:a.done.length,redo:a.undone.length}},clearHistory:function(){this.history=sd(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration()},changeGeneration:function(){return this.history.lastOp=this.history.lastOrigin=null,this.history.generation},isClean:function(a){return this.history.generation==(a||this.cleanGeneration)},getHistory:function(){return{done:yd(this.history.done),undone:yd(this.history.undone)}},setHistory:function(a){var b=this.history=sd(this.history.maxGeneration);b.done=a.done.slice(0),b.undone=a.undone.slice(0)},markText:function(a,b,c){return yc(this,Xb(this,a),Xb(this,b),c,"range")},setBookmark:function(a,b){var c={replacedWith:b&&(null==b.nodeType?b.widget:b),insertLeft:b&&b.insertLeft};return a=Xb(this,a),yc(this,a,a,c,"bookmark")},findMarksAt:function(a){a=Xb(this,a);var b=[],c=kd(this,a.line).markedSpans;if(c)for(var d=0;d<c.length;++d){var e=c[d];(null==e.from||e.from<=a.ch)&&(null==e.to||e.to>=a.ch)&&b.push(e.marker.parent||e.marker)}return b},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.markedSpans;if(c)for(var d=0;d<c.length;++d)null!=c[d].from&&a.push(c[d].marker)}),a},posFromIndex:function(a){var b,c=this.first;return this.iter(function(d){var e=d.text.length+1;return e>a?(b=a,!0):(a-=e,++c,void 0)}),Xb(this,Sb(c,b))},indexFromPos:function(a){a=Xb(this,a);var b=a.ch;return a.line<this.first||a.ch<0?0:(this.iter(this.first,a.line,function(a){b+=a.text.length+1}),b)},copy:function(a){var b=new rf(md(this,this.first,this.first+this.size),this.modeOption,this.first);return b.scrollTop=this.scrollTop,b.scrollLeft=this.scrollLeft,b.sel={from:this.sel.from,to:this.sel.to,head:this.sel.head,anchor:this.sel.anchor,shift:this.sel.shift,extend:!1,goalColumn:this.sel.goalColumn},a&&(b.history.undoDepth=this.history.undoDepth,b.setHistory(this.getHistory())),b},linkedDoc:function(a){a||(a={});var b=this.first,c=this.first+this.size;null!=a.from&&a.from>b&&(b=a.from),null!=a.to&&a.to<c&&(c=a.to);var d=new rf(md(this,b,c),a.mode||this.modeOption,b);return a.sharedHist&&(d.history=this.history),(this.linked||(this.linked=[])).push({doc:d,sharedHist:a.sharedHist}),d.linked=[{doc:this,isParent:!0,sharedHist:a.sharedHist}],d},unlinkDoc:function(b){if(b instanceof a&&(b=b.doc),this.linked)for(var c=0;c<this.linked.length;++c){var d=this.linked[c];if(d.doc==b){this.linked.splice(c,1),b.unlinkDoc(this);break}}if(b.history==this.history){var e=[b.id];id(b,function(a){e.push(a.id)},!0),b.history=sd(),b.history.done=yd(this.history.done,e),b.history.undone=yd(this.history.undone,e)}},iterLinkedDocs:function(a){id(this,a)},getMode:function(){return this.mode},getEditor:function(){return this.cm}}),rf.prototype.eachLine=rf.prototype.iter;var sf="iter insert remove copy getEditor".split(" ");for(var tf in rf.prototype)rf.prototype.hasOwnProperty(tf)&&Xd(sf,tf)<0&&(a.prototype[tf]=function(a){return function(){return a.apply(this.doc,arguments)}}(rf.prototype[tf]));Rd(rf),a.e_stop=Hd,a.e_preventDefault=Ed,a.e_stopPropagation=Fd;var uf,vf=0;a.on=Kd,a.off=Ld,a.signal=Md;var wf=30,xf=a.Pass={toString:function(){return"CodeMirror.Pass"}};Sd.prototype={set:function(a,b){clearTimeout(this.id),this.id=setTimeout(b,a)}},a.countColumn=Td;var yf=[""],zf=/[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,Af=/[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;a.replaceGetRect=function(a){ge=a};var Bf=function(){if(ze)return!1;var a=ce("div");return"draggable"in a||"dragDrop"in a}();we?he=function(a,b){return 36==a.charCodeAt(b-1)&&39==a.charCodeAt(b)}:Ee&&!/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)?he=function(a,b){return/\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(a.slice(b-1,b+1))}:Ae&&!/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent)&&(he=function(a,b){if(b>1&&45==a.charCodeAt(b-1)){if(/\w/.test(a.charAt(b-2))&&/[^\-?\.]/.test(a.charAt(b)))return!0;if(b>2&&/[\d\.,]/.test(a.charAt(b-2))&&/[\d\.,]/.test(a.charAt(b)))return!1}return/[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(a.slice(b-1,b+1))});var Cf,Df,Ef=3!="\n\nb".split(/\n/).length?function(a){for(var b=0,c=[],d=a.length;d>=b;){var e=a.indexOf("\n",b);-1==e&&(e=a.length);var f=a.slice(b,"\r"==a.charAt(e-1)?e-1:e),g=f.indexOf("\r");-1!=g?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\r\n?|\n/)};a.splitLines=Ef;var Ff=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){try{var b=a.ownerDocument.selection.createRange()}catch(c){}return b&&b.parentElement()==a?0!=b.compareEndPoints("StartToEnd",b):!1},Gf=function(){var a=ce("div");return"oncopy"in a?!0:(a.setAttribute("oncopy","return;"),"function"==typeof a.oncopy)}(),Hf={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:";",91:"Mod",92:"Mod",93:"Mod",109:"-",107:"=",127:"Delete",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63276:"PageUp",63277:"PageDown",63275:"End",63273:"Home",63234:"Left",63232:"Up",63235:"Right",63233:"Down",63302:"Insert",63272:"Delete"};a.keyNames=Hf,function(){for(var a=0;10>a;a++)Hf[a+48]=String(a);for(var a=65;90>=a;a++)Hf[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)Hf[a+111]=Hf[a+63235]="F"+a}();var If,Jf=function(){function a(a){return 255>=a?b.charAt(a):a>=1424&&1524>=a?"R":a>=1536&&1791>=a?c.charAt(a-1536):a>=1792&&2220>=a?"r":"L"}var b="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL",c="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr",d=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,e=/[stwN]/,f=/[LRr]/,g=/[Lb1n]/,h=/[1n]/,i="L";return function(b){if(!d.test(b))return!1;for(var c,j=b.length,k=[],l=0;j>l;++l)k.push(c=a(b.charCodeAt(l)));for(var l=0,m=i;j>l;++l){var c=k[l];"m"==c?k[l]=m:m=c}for(var l=0,n=i;j>l;++l){var c=k[l];"1"==c&&"r"==n?k[l]="n":f.test(c)&&(n=c,"r"==c&&(k[l]="R"))}for(var l=1,m=k[0];j-1>l;++l){var c=k[l];"+"==c&&"1"==m&&"1"==k[l+1]?k[l]="1":","!=c||m!=k[l+1]||"1"!=m&&"n"!=m||(k[l]=m),m=c}for(var l=0;j>l;++l){var c=k[l];if(","==c)k[l]="N";else if("%"==c){for(var o=l+1;j>o&&"%"==k[o];++o);for(var p=l&&"!"==k[l-1]||j-1>o&&"1"==k[o]?"1":"N",q=l;o>q;++q)k[q]=p;l=o-1}}for(var l=0,n=i;j>l;++l){var c=k[l];"L"==n&&"1"==c?k[l]="L":f.test(c)&&(n=c)}for(var l=0;j>l;++l)if(e.test(k[l])){for(var o=l+1;j>o&&e.test(k[o]);++o);for(var r="L"==(l?k[l-1]:i),s="L"==(j-1>o?k[o]:i),p=r||s?"L":"R",q=l;o>q;++q)k[q]=p;l=o-1}for(var t,u=[],l=0;j>l;)if(g.test(k[l])){var v=l;for(++l;j>l&&g.test(k[l]);++l);u.push({from:v,to:l,level:0})}else{var w=l,x=u.length;for(++l;j>l&&"L"!=k[l];++l);for(var q=w;l>q;)if(h.test(k[q])){q>w&&u.splice(x,0,{from:w,to:q,level:1});var y=q;for(++q;l>q&&h.test(k[q]);++q);u.splice(x,0,{from:y,to:q,level:2}),w=q}else++q;l>w&&u.splice(x,0,{from:w,to:l,level:1})}return 1==u[0].level&&(t=b.match(/^\s+/))&&(u[0].from=t[0].length,u.unshift({from:0,to:t[0].length,level:0})),1==Vd(u).level&&(t=b.match(/\s+$/))&&(Vd(u).to-=t[0].length,u.push({from:j-t[0].length,to:j,level:0})),u[0].level!=Vd(u).level&&u.push({from:j,to:j,level:u[0].level}),u}}();return a.version="3.15.0",a}(),CodeMirror.defineMode("clike",function(a,b){function c(a,b){var c=a.next();if(q[c]){var f=q[c](a,b);if(f!==!1)return f}if('"'==c||"'"==c)return b.tokenize=d(c),b.tokenize(a,b);if(/[\[\]{}\(\),;\:\.]/.test(c))return i=c,null;if(/\d/.test(c))return a.eatWhile(/[\w\.]/),"number";if("/"==c){if(a.eat("*"))return b.tokenize=e,e(a,b);if(a.eat("/"))return a.skipToEnd(),"comment"}if(s.test(c))return a.eatWhile(s),"operator";a.eatWhile(/[\w\$_]/);var g=a.current();return m.propertyIsEnumerable(g)?(o.propertyIsEnumerable(g)&&(i="newstatement"),"keyword"):n.propertyIsEnumerable(g)?(o.propertyIsEnumerable(g)&&(i="newstatement"),"builtin"):p.propertyIsEnumerable(g)?"atom":"variable"}function d(a){return function(b,c){for(var d,e=!1,f=!1;null!=(d=b.next());){if(d==a&&!e){f=!0;break}e=!e&&"\\"==d}return(f||!e&&!r)&&(c.tokenize=null),"string"}}function e(a,b){for(var c,d=!1;c=a.next();){if("/"==c&&d){b.tokenize=null;break}d="*"==c}return"comment"}function f(a,b,c,d,e){this.indented=a,this.column=b,this.type=c,this.align=d,this.prev=e}function g(a,b,c){var d=a.indented;return a.context&&"statement"==a.context.type&&(d=a.context.indented),a.context=new f(d,b,c,null,a.context)}function h(a){var b=a.context.type;return(")"==b||"]"==b||"}"==b)&&(a.indented=a.context.indented),a.context=a.context.prev}var i,j=a.indentUnit,k=b.statementIndentUnit||j,l=b.dontAlignCalls,m=b.keywords||{},n=b.builtin||{},o=b.blockKeywords||{},p=b.atoms||{},q=b.hooks||{},r=b.multiLineStrings,s=/[+\-*&%=<>!?|\/]/;return{startState:function(a){return{tokenize:null,context:new f((a||0)-j,0,"top",!1),indented:0,startOfLine:!0}},token:function(a,b){var d=b.context;if(a.sol()&&(null==d.align&&(d.align=!1),b.indented=a.indentation(),b.startOfLine=!0),a.eatSpace())return null;i=null;var e=(b.tokenize||c)(a,b);if("comment"==e||"meta"==e)return e;if(null==d.align&&(d.align=!0),";"!=i&&":"!=i&&","!=i||"statement"!=d.type)if("{"==i)g(b,a.column(),"}");else if("["==i)g(b,a.column(),"]");else if("("==i)g(b,a.column(),")");else if("}"==i){for(;"statement"==d.type;)d=h(b);for("}"==d.type&&(d=h(b));"statement"==d.type;)d=h(b)}else i==d.type?h(b):(("}"==d.type||"top"==d.type)&&";"!=i||"statement"==d.type&&"newstatement"==i)&&g(b,a.column(),"statement");else h(b);return b.startOfLine=!1,e},indent:function(a,b){if(a.tokenize!=c&&null!=a.tokenize)return CodeMirror.Pass;var d=a.context,e=b&&b.charAt(0);"statement"==d.type&&"}"==e&&(d=d.prev);var f=e==d.type;return"statement"==d.type?d.indented+("{"==e?0:k):!d.align||l&&")"==d.type?")"!=d.type||f?d.indented+(f?0:j):d.indented+k:d.column+(f?0:1)},electricChars:"{}",blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",fold:"brace"}}),function(){function a(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}function b(a,c){if(!c.startOfLine)return!1;for(;;){if(!a.skipTo("\\")){a.skipToEnd(),c.tokenize=null;break}if(a.next(),a.eol()){c.tokenize=b;break}}return"meta"}function c(a,b){for(var c;null!=(c=a.next());)if('"'==c&&!a.eat('"')){b.tokenize=null;break}return"string"}function d(a,b){for(var c=0;c<a.length;++c)CodeMirror.defineMIME(a[c],b)}var e="auto if break int case long char register continue return default short do sizeof double static else struct entry switch extern typedef float union for unsigned goto while enum void const signed volatile";d(["text/x-csrc","text/x-c","text/x-chdr"],{name:"clike",keywords:a(e),blockKeywords:a("case do else for if switch while struct"),atoms:a("null"),hooks:{"#":b}}),d(["text/x-c++src","text/x-c++hdr"],{name:"clike",keywords:a(e+" asm dynamic_cast namespace reinterpret_cast try bool explicit new "+"static_cast typeid catch operator template typename class friend private "+"this using const_cast inline public throw virtual delete mutable protected "+"wchar_t"),blockKeywords:a("catch class do else finally for if struct switch try while"),atoms:a("true false null"),hooks:{"#":b}}),CodeMirror.defineMIME("text/x-java",{name:"clike",keywords:a("abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while"),blockKeywords:a("catch class do else finally for if switch try while"),atoms:a("true false null"),hooks:{"@":function(a){return a.eatWhile(/[\w\$_]/),"meta"}}}),CodeMirror.defineMIME("text/x-csharp",{name:"clike",keywords:a("abstract as base break case catch checked class const continue default delegate do else enum event explicit extern finally fixed for foreach goto if implicit in interface internal is lock namespace new operator out override params private protected public readonly ref return sealed sizeof stackalloc static struct switch this throw try typeof unchecked unsafe using virtual void volatile while add alias ascending descending dynamic from get global group into join let orderby partial remove select set value var yield"),blockKeywords:a("catch class do else finally for foreach if struct switch try while"),builtin:a("Boolean Byte Char DateTime DateTimeOffset Decimal Double Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32 UInt64 bool byte char decimal double short int long object sbyte float string ushort uint ulong"),atoms:a("true false null"),hooks:{"@":function(a,b){return a.eat('"')?(b.tokenize=c,c(a,b)):(a.eatWhile(/[\w\$_]/),"meta")}}}),CodeMirror.defineMIME("text/x-scala",{name:"clike",keywords:a("abstract case catch class def do else extends false final finally for forSome if implicit import lazy match new null object override package private protected return sealed super this throw trait try trye type val var while with yield _ : = => <- <: <% >: # @ assert assume require print println printf readLine readBoolean readByte readShort readChar readInt readLong readFloat readDouble AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"),blockKeywords:a("catch class do else finally for forSome if match switch try while"),atoms:a("true false null"),hooks:{"@":function(a){return a.eatWhile(/[\w\$_]/),"meta"}}}),d(["x-shader/x-vertex","x-shader/x-fragment"],{name:"clike",keywords:a("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4 sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadowconst attribute uniform varying break continue discard return for while do if else struct in out inout"),blockKeywords:a("for while do if else struct"),builtin:a("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smootstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shadow1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:a("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragColor gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),hooks:{"#":b}})}(),function(){function a(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}function b(a){return function(b,c){return b.match(a)?c.tokenize=null:b.skipToEnd(),"string"}}var c={name:"clike",keywords:a("abstract and array as break case catch class clone const continue declare default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final for foreach function global goto if implements interface instanceof namespace new or private protected public static switch throw trait try use var while xor die echo empty exit eval include include_once isset list require require_once return print unset __halt_compiler self static parent"),blockKeywords:a("catch do else elseif for foreach if switch try while"),atoms:a("true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__"),builtin:a("func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport echo print global static exit array empty eval isset unset die include require include_once require_once"),multiLineStrings:!0,hooks:{$:function(a){return a.eatWhile(/[\w\$_]/),"variable-2"},"<":function(a,c){return a.match(/<</)?(a.eatWhile(/[\w\.]/),c.tokenize=b(a.current().slice(3)),c.tokenize(a,c)):!1},"#":function(a){for(;!a.eol()&&!a.match("?>",!1);)a.next();return"comment"},"/":function(a){if(a.eat("/")){for(;!a.eol()&&!a.match("?>",!1);)a.next();return"comment"}return!1}}};CodeMirror.defineMode("php",function(a,b){function d(a,b){var c=b.curMode==f;if(a.sol()&&'"'!=b.pending&&(b.pending=null),c)return c&&null==b.php.tokenize&&a.match("?>")?(b.curMode=e,b.curState=b.html,"meta"):f.token(a,b.curState);if(a.match(/^<\?\w*/))return b.curMode=f,b.curState=b.php,"meta";if('"'==b.pending){for(;!a.eol()&&'"'!=a.next(););var d="string"}else if(b.pending&&a.pos<b.pending.end){a.pos=b.pending.end;var d=b.pending.style}else var d=e.token(a,b.curState);b.pending=null;var g=a.current(),h=g.search(/<\?/);return-1!=h&&(b.pending="string"==d&&/\"$/.test(g)&&!/\?>/.test(g)?'"':{end:a.pos,style:d},a.backUp(g.length-h)),d}var e=CodeMirror.getMode(a,"text/html"),f=CodeMirror.getMode(a,c);return{startState:function(){var a=CodeMirror.startState(e),c=CodeMirror.startState(f);return{html:a,php:c,curMode:b.startOpen?f:e,curState:b.startOpen?c:a,pending:null}},copyState:function(a){var b,c=a.html,d=CodeMirror.copyState(e,c),g=a.php,h=CodeMirror.copyState(f,g);return b=a.curMode==e?d:h,{html:d,php:h,curMode:a.curMode,curState:b,pending:a.pending}},token:d,indent:function(a,b){return a.curMode!=f&&/^\s*<\//.test(b)||a.curMode==f&&/^\?>/.test(b)?e.indent(a.html,b):a.curMode.indent(a.curState,b)},electricChars:"/{}:",blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",innerMode:function(a){return{state:a.curState,mode:a.curMode}}}},"htmlmixed","clike"),CodeMirror.defineMIME("application/x-httpd-php","php"),CodeMirror.defineMIME("application/x-httpd-php-open",{name:"php",startOpen:!0}),CodeMirror.defineMIME("text/x-php",c)}(),function(){function a(a,c,d,e){if(this.atOccurrence=!1,this.doc=a,null==e&&"string"==typeof c&&(e=!1),d=d?a.clipPos(d):b(0,0),this.pos={from:d,to:d},"string"!=typeof c)c.global||(c=new RegExp(c.source,c.ignoreCase?"ig":"g")),this.matches=function(d,e){if(d){c.lastIndex=0;for(var f,g,h=a.getLine(e.line).slice(0,e.ch),i=0;;){c.lastIndex=i;var j=c.exec(h);if(!j)break;if(f=j,g=f.index,i=f.index+(f[0].length||1),i==h.length)break}var k=f&&f[0].length||0;k||(0==g&&0==h.length?f=void 0:g!=a.getLine(e.line).length&&k++)}else{c.lastIndex=e.ch;var h=a.getLine(e.line),f=c.exec(h),k=f&&f[0].length||0,g=f&&f.index;g+k==h.length||k||(k=1)}return f&&k?{from:b(e.line,g),to:b(e.line,g+k),match:f}:void 0};else{e&&(c=c.toLowerCase());var f=e?function(a){return a.toLowerCase()}:function(a){return a},g=c.split("\n");this.matches=1==g.length?c.length?function(d,e){var g,h=f(a.getLine(e.line)),i=c.length;return(d?e.ch>=i&&-1!=(g=h.lastIndexOf(c,e.ch-i)):-1!=(g=h.indexOf(c,e.ch)))?{from:b(e.line,g),to:b(e.line,g+i)}:void 0}:function(){}:function(c,d){var e=d.line,h=c?g.length-1:0,i=g[h],j=f(a.getLine(e)),k=c?j.indexOf(i)+i.length:j.lastIndexOf(i);if(!(c?k>=d.ch||k!=i.length:k<=d.ch||k!=j.length-i.length))for(;;){if(c?!e:e==a.lineCount()-1)return;if(j=f(a.getLine(e+=c?-1:1)),i=g[c?--h:++h],!(h>0&&h<g.length-1)){var l=c?j.lastIndexOf(i):j.indexOf(i)+i.length;if(c?l!=j.length-i.length:l!=i.length)return;var m=b(d.line,k),n=b(e,l);return{from:c?n:m,to:c?m:n}}if(j!=i)return}}}}var b=CodeMirror.Pos;a.prototype={findNext:function(){return this.find(!1)},findPrevious:function(){return this.find(!0)},find:function(a){function c(a){var c=b(a,0);return d.pos={from:c,to:c},d.atOccurrence=!1,!1}for(var d=this,e=this.doc.clipPos(a?this.pos.from:this.pos.to);;){if(this.pos=this.matches(a,e))return this.pos.from&&this.pos.to||console.log(this.matches,this.pos),this.atOccurrence=!0,this.pos.match||!0;if(a){if(!e.line)return c(0);e=b(e.line-1,this.doc.getLine(e.line-1).length)}else{var f=this.doc.lineCount();if(e.line==f-1)return c(f);e=b(e.line+1,0)}}},from:function(){return this.atOccurrence?this.pos.from:void 0
5
- },to:function(){return this.atOccurrence?this.pos.to:void 0},replace:function(a){if(this.atOccurrence){var c=CodeMirror.splitLines(a);this.doc.replaceRange(c,this.pos.from,this.pos.to),this.pos.to=b(this.pos.from.line+c.length-1,c[c.length-1].length+(1==c.length?this.pos.from.ch:0))}}},CodeMirror.defineExtension("getSearchCursor",function(b,c,d){return new a(this.doc,b,c,d)}),CodeMirror.defineDocExtension("getSearchCursor",function(b,c,d){return new a(this,b,c,d)})}(),function(){function a(a){return"string"==typeof a?{token:function(b){return b.match(a)?"searching":(b.next(),b.skipTo(a.charAt(0))||b.skipToEnd(),void 0)}}:{token:function(b){if(b.match(a))return"searching";for(;!b.eol()&&(b.next(),!b.match(a,!1)););}}}function b(){this.posFrom=this.posTo=this.query=null,this.overlay=null}function c(a){return a.state.search||(a.state.search=new b)}function d(a,b,c){return a.getSearchCursor(b,c,"string"==typeof b&&b==b.toLowerCase())}function e(a,b,c,d){a.openDialog?a.openDialog(b,d):d(prompt(c,""))}function f(a,b,c,d){a.openConfirm?a.openConfirm(b,d):confirm(c)&&d[0]()}function g(a){var b=a.match(/^\/(.*)\/([a-z]*)$/);return b?new RegExp(b[1],-1==b[2].indexOf("i")?"":"i"):a}function h(b,d){var f=c(b);return f.query?i(b,d):(e(b,l,"Search for:",function(c){b.operation(function(){c&&!f.query&&(f.query=g(c),b.removeOverlay(f.overlay),f.overlay=a(f.query),b.addOverlay(f.overlay),f.posFrom=f.posTo=b.getCursor(),i(b,d))})}),void 0)}function i(a,b){a.operation(function(){var e=c(a),f=d(a,e.query,b?e.posFrom:e.posTo);(f.find(b)||(f=d(a,e.query,b?CodeMirror.Pos(a.lastLine()):CodeMirror.Pos(a.firstLine(),0)),f.find(b)))&&(a.setSelection(f.from(),f.to()),e.posFrom=f.from(),e.posTo=f.to())})}function j(a){a.operation(function(){var b=c(a);b.query&&(b.query=null,a.removeOverlay(b.overlay))})}function k(a,b){e(a,m,"Replace:",function(c){c&&(c=g(c),e(a,n,"Replace with:",function(e){if(b)a.operation(function(){for(var b=d(a,c);b.findNext();)if("string"!=typeof c){var f=a.getRange(b.from(),b.to()).match(c);b.replace(e.replace(/\$(\d)/,function(a,b){return f[b]}))}else b.replace(e)});else{j(a);var g=d(a,c,a.getCursor()),h=function(){var b,e=g.from();!(b=g.findNext())&&(g=d(a,c),!(b=g.findNext())||e&&g.from().line==e.line&&g.from().ch==e.ch)||(a.setSelection(g.from(),g.to()),f(a,o,"Replace?",[function(){i(b)},h]))},i=function(a){g.replace("string"==typeof c?e:e.replace(/\$(\d)/,function(b,c){return a[c]})),h()};h()}}))})}var l='Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>',m='Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>',n='With: <input type="text" style="width: 10em"/>',o="Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";CodeMirror.commands.find=function(a){j(a),h(a)},CodeMirror.commands.findNext=h,CodeMirror.commands.findPrev=function(a){h(a,!0)},CodeMirror.commands.clearSearch=j,CodeMirror.commands.replace=k,CodeMirror.commands.replaceAll=function(a){k(a,!0)}}(),function(){function a(a,b,c){function d(b,c,d){if(b.text){var g=m?0:b.text.length-1,i=m?b.text.length:-1;if(b.text.length>h)return null;for(null!=d&&(g=d+n);g!=i;g+=n){var j=b.text.charAt(g);if(r.test(j)&&a.getTokenTypeAt(e(c,g+1))==p){var k=f[j];if(">"==k.charAt(1)==m)q.push(j);else{if(q.pop()!=k.charAt(0))return{pos:g,match:!1};if(!q.length)return{pos:g,match:!0}}}}}}var g=a.state.matchBrackets,h=g&&g.maxScanLineLength||1e4,i=b||a.getCursor(),j=a.getLineHandle(i.line),k=i.ch-1,l=k>=0&&f[j.text.charAt(k)]||f[j.text.charAt(++k)];if(!l)return null;var m=">"==l.charAt(1),n=m?1:-1;if(c&&m!=(k==i.ch))return null;for(var o,p=a.getTokenTypeAt(e(i.line,k+1)),q=[j.text.charAt(k)],r=/[(){}[\]]/,s=i.line,t=m?Math.min(s+100,a.lineCount()):Math.max(-1,s-100);s!=t&&!(o=s==i.line?d(j,s,k):d(a.getLineHandle(s),s));s+=n);return{from:e(i.line,k),to:o&&e(s,o.pos),match:o&&o.match,forward:m}}function b(b,c){var f=b.state.matchBrackets.maxHighlightLineLength||1e3,g=a(b);if(!(!g||b.getLine(g.from.line).length>f||g.to&&b.getLine(g.to.line).length>f)){var h=g.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket",i=b.markText(g.from,e(g.from.line,g.from.ch+1),{className:h}),j=g.to&&b.markText(g.to,e(g.to.line,g.to.ch+1),{className:h});d&&b.state.focused&&b.display.input.focus();var k=function(){b.operation(function(){i.clear(),j&&j.clear()})};return c?(setTimeout(k,800),void 0):k}}function c(a){a.operation(function(){g&&(g(),g=null),a.somethingSelected()||(g=b(a,!1))})}var d=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),e=CodeMirror.Pos,f={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"},g=null;CodeMirror.defineOption("matchBrackets",!1,function(a,b,d){d&&d!=CodeMirror.Init&&a.off("cursorActivity",c),b&&(a.state.matchBrackets="object"==typeof b?b:{},a.on("cursorActivity",c))}),CodeMirror.defineExtension("matchBrackets",function(){b(this,!0)}),CodeMirror.defineExtension("findMatchingBracket",function(b,c){return a(this,b,c)})}();
 
 
 
 
 
vendor/codemirror/addon/matchbrackets.js DELETED
@@ -1,86 +0,0 @@
1
- (function() {
2
- var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
3
- (document.documentMode == null || document.documentMode < 8);
4
-
5
- var Pos = CodeMirror.Pos;
6
-
7
- var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
8
- function findMatchingBracket(cm, where, strict) {
9
- var state = cm.state.matchBrackets;
10
- var maxScanLen = (state && state.maxScanLineLength) || 10000;
11
-
12
- var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
13
- var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
14
- if (!match) return null;
15
- var forward = match.charAt(1) == ">", d = forward ? 1 : -1;
16
- if (strict && forward != (pos == cur.ch)) return null;
17
- var style = cm.getTokenTypeAt(Pos(cur.line, pos + 1));
18
-
19
- var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
20
- function scan(line, lineNo, start) {
21
- if (!line.text) return;
22
- var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;
23
- if (line.text.length > maxScanLen) return null;
24
- if (start != null) pos = start + d;
25
- for (; pos != end; pos += d) {
26
- var ch = line.text.charAt(pos);
27
- if (re.test(ch) && cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style) {
28
- var match = matching[ch];
29
- if (match.charAt(1) == ">" == forward) stack.push(ch);
30
- else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
31
- else if (!stack.length) return {pos: pos, match: true};
32
- }
33
- }
34
- }
35
- for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
36
- if (i == cur.line) found = scan(line, i, pos);
37
- else found = scan(cm.getLineHandle(i), i);
38
- if (found) break;
39
- }
40
- return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos),
41
- match: found && found.match, forward: forward};
42
- }
43
-
44
- function matchBrackets(cm, autoclear) {
45
- // Disable brace matching in long lines, since it'll cause hugely slow updates
46
- var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
47
- var found = findMatchingBracket(cm);
48
- if (!found || cm.getLine(found.from.line).length > maxHighlightLen ||
49
- found.to && cm.getLine(found.to.line).length > maxHighlightLen)
50
- return;
51
-
52
- var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
53
- var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style});
54
- var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style});
55
- // Kludge to work around the IE bug from issue #1193, where text
56
- // input stops going to the textare whever this fires.
57
- if (ie_lt8 && cm.state.focused) cm.display.input.focus();
58
- var clear = function() {
59
- cm.operation(function() { one.clear(); two && two.clear(); });
60
- };
61
- if (autoclear) setTimeout(clear, 800);
62
- else return clear;
63
- }
64
-
65
- var currentlyHighlighted = null;
66
- function doMatchBrackets(cm) {
67
- cm.operation(function() {
68
- if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
69
- if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);
70
- });
71
- }
72
-
73
- CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
74
- if (old && old != CodeMirror.Init)
75
- cm.off("cursorActivity", doMatchBrackets);
76
- if (val) {
77
- cm.state.matchBrackets = typeof val == "object" ? val : {};
78
- cm.on("cursorActivity", doMatchBrackets);
79
- }
80
- });
81
-
82
- CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
83
- CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){
84
- return findMatchingBracket(this, pos, strict);
85
- });
86
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codemirror/addon/search.js DELETED
@@ -1,131 +0,0 @@
1
- // Define search commands. Depends on dialog.js or another
2
- // implementation of the openDialog method.
3
-
4
- // Replace works a little oddly -- it will do the replace on the next
5
- // Ctrl-G (or whatever is bound to findNext) press. You prevent a
6
- // replace by making sure the match is no longer selected when hitting
7
- // Ctrl-G.
8
-
9
- (function() {
10
- function searchOverlay(query) {
11
- if (typeof query == "string") return {token: function(stream) {
12
- if (stream.match(query)) return "searching";
13
- stream.next();
14
- stream.skipTo(query.charAt(0)) || stream.skipToEnd();
15
- }};
16
- return {token: function(stream) {
17
- if (stream.match(query)) return "searching";
18
- while (!stream.eol()) {
19
- stream.next();
20
- if (stream.match(query, false)) break;
21
- }
22
- }};
23
- }
24
-
25
- function SearchState() {
26
- this.posFrom = this.posTo = this.query = null;
27
- this.overlay = null;
28
- }
29
- function getSearchState(cm) {
30
- return cm.state.search || (cm.state.search = new SearchState());
31
- }
32
- function getSearchCursor(cm, query, pos) {
33
- // Heuristic: if the query string is all lowercase, do a case insensitive search.
34
- return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase());
35
- }
36
- function dialog(cm, text, shortText, f) {
37
- if (cm.openDialog) cm.openDialog(text, f);
38
- else f(prompt(shortText, ""));
39
- }
40
- function confirmDialog(cm, text, shortText, fs) {
41
- if (cm.openConfirm) cm.openConfirm(text, fs);
42
- else if (confirm(shortText)) fs[0]();
43
- }
44
- function parseQuery(query) {
45
- var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
46
- return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
47
- }
48
- var queryDialog =
49
- 'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
50
- function doSearch(cm, rev) {
51
- var state = getSearchState(cm);
52
- if (state.query) return findNext(cm, rev);
53
- dialog(cm, queryDialog, "Search for:", function(query) {
54
- cm.operation(function() {
55
- if (!query || state.query) return;
56
- state.query = parseQuery(query);
57
- cm.removeOverlay(state.overlay);
58
- state.overlay = searchOverlay(state.query);
59
- cm.addOverlay(state.overlay);
60
- state.posFrom = state.posTo = cm.getCursor();
61
- findNext(cm, rev);
62
- });
63
- });
64
- }
65
- function findNext(cm, rev) {cm.operation(function() {
66
- var state = getSearchState(cm);
67
- var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
68
- if (!cursor.find(rev)) {
69
- cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
70
- if (!cursor.find(rev)) return;
71
- }
72
- cm.setSelection(cursor.from(), cursor.to());
73
- state.posFrom = cursor.from(); state.posTo = cursor.to();
74
- });}
75
- function clearSearch(cm) {cm.operation(function() {
76
- var state = getSearchState(cm);
77
- if (!state.query) return;
78
- state.query = null;
79
- cm.removeOverlay(state.overlay);
80
- });}
81
-
82
- var replaceQueryDialog =
83
- 'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
84
- var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
85
- var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
86
- function replace(cm, all) {
87
- dialog(cm, replaceQueryDialog, "Replace:", function(query) {
88
- if (!query) return;
89
- query = parseQuery(query);
90
- dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
91
- if (all) {
92
- cm.operation(function() {
93
- for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
94
- if (typeof query != "string") {
95
- var match = cm.getRange(cursor.from(), cursor.to()).match(query);
96
- cursor.replace(text.replace(/\$(\d)/, function(_, i) {return match[i];}));
97
- } else cursor.replace(text);
98
- }
99
- });
100
- } else {
101
- clearSearch(cm);
102
- var cursor = getSearchCursor(cm, query, cm.getCursor());
103
- var advance = function() {
104
- var start = cursor.from(), match;
105
- if (!(match = cursor.findNext())) {
106
- cursor = getSearchCursor(cm, query);
107
- if (!(match = cursor.findNext()) ||
108
- (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
109
- }
110
- cm.setSelection(cursor.from(), cursor.to());
111
- confirmDialog(cm, doReplaceConfirm, "Replace?",
112
- [function() {doReplace(match);}, advance]);
113
- };
114
- var doReplace = function(match) {
115
- cursor.replace(typeof query == "string" ? text :
116
- text.replace(/\$(\d)/, function(_, i) {return match[i];}));
117
- advance();
118
- };
119
- advance();
120
- }
121
- });
122
- });
123
- }
124
-
125
- CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
126
- CodeMirror.commands.findNext = doSearch;
127
- CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
128
- CodeMirror.commands.clearSearch = clearSearch;
129
- CodeMirror.commands.replace = replace;
130
- CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
131
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codemirror/addon/searchcursor.js DELETED
@@ -1,143 +0,0 @@
1
- (function(){
2
- var Pos = CodeMirror.Pos;
3
-
4
- function SearchCursor(doc, query, pos, caseFold) {
5
- this.atOccurrence = false; this.doc = doc;
6
- if (caseFold == null && typeof query == "string") caseFold = false;
7
-
8
- pos = pos ? doc.clipPos(pos) : Pos(0, 0);
9
- this.pos = {from: pos, to: pos};
10
-
11
- // The matches method is filled in based on the type of query.
12
- // It takes a position and a direction, and returns an object
13
- // describing the next occurrence of the query, or null if no
14
- // more matches were found.
15
- if (typeof query != "string") { // Regexp match
16
- if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
17
- this.matches = function(reverse, pos) {
18
- if (reverse) {
19
- query.lastIndex = 0;
20
- var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
21
- for (;;) {
22
- query.lastIndex = cutOff;
23
- var newMatch = query.exec(line);
24
- if (!newMatch) break;
25
- match = newMatch;
26
- start = match.index;
27
- cutOff = match.index + (match[0].length || 1);
28
- if (cutOff == line.length) break;
29
- }
30
- var matchLen = (match && match[0].length) || 0;
31
- if (!matchLen) {
32
- if (start == 0 && line.length == 0) {match = undefined;}
33
- else if (start != doc.getLine(pos.line).length) {
34
- matchLen++;
35
- }
36
- }
37
- } else {
38
- query.lastIndex = pos.ch;
39
- var line = doc.getLine(pos.line), match = query.exec(line);
40
- var matchLen = (match && match[0].length) || 0;
41
- var start = match && match.index;
42
- if (start + matchLen != line.length && !matchLen) matchLen = 1;
43
- }
44
- if (match && matchLen)
45
- return {from: Pos(pos.line, start),
46
- to: Pos(pos.line, start + matchLen),
47
- match: match};
48
- };
49
- } else { // String query
50
- if (caseFold) query = query.toLowerCase();
51
- var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
52
- var target = query.split("\n");
53
- // Different methods for single-line and multi-line queries
54
- if (target.length == 1) {
55
- if (!query.length) {
56
- // Empty string would match anything and never progress, so
57
- // we define it to match nothing instead.
58
- this.matches = function() {};
59
- } else {
60
- this.matches = function(reverse, pos) {
61
- var line = fold(doc.getLine(pos.line)), len = query.length, match;
62
- if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
63
- : (match = line.indexOf(query, pos.ch)) != -1)
64
- return {from: Pos(pos.line, match),
65
- to: Pos(pos.line, match + len)};
66
- };
67
- }
68
- } else {
69
- this.matches = function(reverse, pos) {
70
- var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln));
71
- var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
72
- if (reverse ? offsetA >= pos.ch || offsetA != match.length
73
- : offsetA <= pos.ch || offsetA != line.length - match.length)
74
- return;
75
- for (;;) {
76
- if (reverse ? !ln : ln == doc.lineCount() - 1) return;
77
- line = fold(doc.getLine(ln += reverse ? -1 : 1));
78
- match = target[reverse ? --idx : ++idx];
79
- if (idx > 0 && idx < target.length - 1) {
80
- if (line != match) return;
81
- else continue;
82
- }
83
- var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
84
- if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
85
- return;
86
- var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB);
87
- return {from: reverse ? end : start, to: reverse ? start : end};
88
- }
89
- };
90
- }
91
- }
92
- }
93
-
94
- SearchCursor.prototype = {
95
- findNext: function() {return this.find(false);},
96
- findPrevious: function() {return this.find(true);},
97
-
98
- find: function(reverse) {
99
- var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
100
- function savePosAndFail(line) {
101
- var pos = Pos(line, 0);
102
- self.pos = {from: pos, to: pos};
103
- self.atOccurrence = false;
104
- return false;
105
- }
106
-
107
- for (;;) {
108
- if (this.pos = this.matches(reverse, pos)) {
109
- if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); }
110
- this.atOccurrence = true;
111
- return this.pos.match || true;
112
- }
113
- if (reverse) {
114
- if (!pos.line) return savePosAndFail(0);
115
- pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
116
- }
117
- else {
118
- var maxLine = this.doc.lineCount();
119
- if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
120
- pos = Pos(pos.line + 1, 0);
121
- }
122
- }
123
- },
124
-
125
- from: function() {if (this.atOccurrence) return this.pos.from;},
126
- to: function() {if (this.atOccurrence) return this.pos.to;},
127
-
128
- replace: function(newText) {
129
- if (!this.atOccurrence) return;
130
- var lines = CodeMirror.splitLines(newText);
131
- this.doc.replaceRange(lines, this.pos.from, this.pos.to);
132
- this.pos.to = Pos(this.pos.from.line + lines.length - 1,
133
- lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
134
- }
135
- };
136
-
137
- CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
138
- return new SearchCursor(this.doc, query, pos, caseFold);
139
- });
140
- CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
141
- return new SearchCursor(this, query, pos, caseFold);
142
- });
143
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codemirror/lib/codemirror.css DELETED
@@ -1,258 +0,0 @@
1
- /* BASICS */
2
-
3
- .CodeMirror {
4
- /* Set height, width, borders, and global font properties here */
5
- font-family: monospace;
6
- height: 300px;
7
- }
8
- .CodeMirror-scroll {
9
- /* Set scrolling behaviour here */
10
- overflow: auto;
11
- }
12
-
13
- /* PADDING */
14
-
15
- .CodeMirror-lines {
16
- padding: 4px 0; /* Vertical padding around content */
17
- }
18
- .CodeMirror pre {
19
- padding: 0 4px; /* Horizontal padding of content */
20
- }
21
-
22
- .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
23
- background-color: white; /* The little square between H and V scrollbars */
24
- }
25
-
26
- /* GUTTER */
27
-
28
- .CodeMirror-gutters {
29
- border-right: 1px solid #ddd;
30
- background-color: #f7f7f7;
31
- white-space: nowrap;
32
- }
33
- .CodeMirror-linenumbers {}
34
- .CodeMirror-linenumber {
35
- padding: 0 3px 0 5px;
36
- min-width: 20px;
37
- text-align: right;
38
- color: #999;
39
- }
40
-
41
- /* CURSOR */
42
-
43
- .CodeMirror div.CodeMirror-cursor {
44
- border-left: 1px solid black;
45
- z-index: 3;
46
- }
47
- /* Shown when moving in bi-directional text */
48
- .CodeMirror div.CodeMirror-secondarycursor {
49
- border-left: 1px solid silver;
50
- }
51
- .CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
52
- width: auto;
53
- border: 0;
54
- background: #7e7;
55
- z-index: 1;
56
- }
57
- /* Can style cursor different in overwrite (non-insert) mode */
58
- .CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
59
-
60
- .cm-tab { display: inline-block; }
61
-
62
- /* DEFAULT THEME */
63
-
64
- .cm-s-default .cm-keyword {color: #708;}
65
- .cm-s-default .cm-atom {color: #219;}
66
- .cm-s-default .cm-number {color: #164;}
67
- .cm-s-default .cm-def {color: #00f;}
68
- .cm-s-default .cm-variable {color: black;}
69
- .cm-s-default .cm-variable-2 {color: #05a;}
70
- .cm-s-default .cm-variable-3 {color: #085;}
71
- .cm-s-default .cm-property {color: black;}
72
- .cm-s-default .cm-operator {color: black;}
73
- .cm-s-default .cm-comment {color: #a50;}
74
- .cm-s-default .cm-string {color: #a11;}
75
- .cm-s-default .cm-string-2 {color: #f50;}
76
- .cm-s-default .cm-meta {color: #555;}
77
- .cm-s-default .cm-error {color: #f00;}
78
- .cm-s-default .cm-qualifier {color: #555;}
79
- .cm-s-default .cm-builtin {color: #30a;}
80
- .cm-s-default .cm-bracket {color: #997;}
81
- .cm-s-default .cm-tag {color: #170;}
82
- .cm-s-default .cm-attribute {color: #00c;}
83
- .cm-s-default .cm-header {color: blue;}
84
- .cm-s-default .cm-quote {color: #090;}
85
- .cm-s-default .cm-hr {color: #999;}
86
- .cm-s-default .cm-link {color: #00c;}
87
-
88
- .cm-negative {color: #d44;}
89
- .cm-positive {color: #292;}
90
- .cm-header, .cm-strong {font-weight: bold;}
91
- .cm-em {font-style: italic;}
92
- .cm-link {text-decoration: underline;}
93
-
94
- .cm-invalidchar {color: #f00;}
95
-
96
- div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
97
- div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
98
-
99
- /* STOP */
100
-
101
- /* The rest of this file contains styles related to the mechanics of
102
- the editor. You probably shouldn't touch them. */
103
-
104
- .CodeMirror {
105
- line-height: 1;
106
- position: relative;
107
- overflow: hidden;
108
- background: white;
109
- color: black;
110
- }
111
-
112
- .CodeMirror-scroll {
113
- /* 30px is the magic margin used to hide the element's real scrollbars */
114
- /* See overflow: hidden in .CodeMirror */
115
- margin-bottom: -30px; margin-right: -30px;
116
- padding-bottom: 30px; padding-right: 30px;
117
- height: 100%;
118
- outline: none; /* Prevent dragging from highlighting the element */
119
- position: relative;
120
- }
121
- .CodeMirror-sizer {
122
- position: relative;
123
- }
124
-
125
- /* The fake, visible scrollbars. Used to force redraw during scrolling
126
- before actuall scrolling happens, thus preventing shaking and
127
- flickering artifacts. */
128
- .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
129
- position: absolute;
130
- z-index: 6;
131
- display: none;
132
- }
133
- .CodeMirror-vscrollbar {
134
- right: 0; top: 0;
135
- overflow-x: hidden;
136
- overflow-y: scroll;
137
- }
138
- .CodeMirror-hscrollbar {
139
- bottom: 0; left: 0;
140
- overflow-y: hidden;
141
- overflow-x: scroll;
142
- }
143
- .CodeMirror-scrollbar-filler {
144
- right: 0; bottom: 0;
145
- }
146
- .CodeMirror-gutter-filler {
147
- left: 0; bottom: 0;
148
- }
149
-
150
- .CodeMirror-gutters {
151
- position: absolute; left: 0; top: 0;
152
- padding-bottom: 30px;
153
- z-index: 3;
154
- }
155
- .CodeMirror-gutter {
156
- white-space: normal;
157
- height: 100%;
158
- padding-bottom: 30px;
159
- margin-bottom: -32px;
160
- display: inline-block;
161
- /* Hack to make IE7 behave */
162
- *zoom:1;
163
- *display:inline;
164
- }
165
- .CodeMirror-gutter-elt {
166
- position: absolute;
167
- cursor: default;
168
- z-index: 4;
169
- }
170
-
171
- .CodeMirror-lines {
172
- cursor: text;
173
- }
174
- .CodeMirror pre {
175
- /* Reset some styles that the rest of the page might have set */
176
- -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
177
- border-width: 0;
178
- background: transparent;
179
- font-family: inherit;
180
- font-size: inherit;
181
- margin: 0;
182
- white-space: pre;
183
- word-wrap: normal;
184
- line-height: inherit;
185
- color: inherit;
186
- z-index: 2;
187
- position: relative;
188
- overflow: visible;
189
- }
190
- .CodeMirror-wrap pre {
191
- word-wrap: break-word;
192
- white-space: pre-wrap;
193
- word-break: normal;
194
- }
195
- .CodeMirror-code pre {
196
- border-right: 30px solid transparent;
197
- width: -webkit-fit-content;
198
- width: -moz-fit-content;
199
- width: fit-content;
200
- }
201
- .CodeMirror-wrap .CodeMirror-code pre {
202
- border-right: none;
203
- width: auto;
204
- }
205
- .CodeMirror-linebackground {
206
- position: absolute;
207
- left: 0; right: 0; top: 0; bottom: 0;
208
- z-index: 0;
209
- }
210
-
211
- .CodeMirror-linewidget {
212
- position: relative;
213
- z-index: 2;
214
- overflow: auto;
215
- }
216
-
217
- .CodeMirror-widget {
218
- }
219
-
220
- .CodeMirror-wrap .CodeMirror-scroll {
221
- overflow-x: hidden;
222
- }
223
-
224
- .CodeMirror-measure {
225
- position: absolute;
226
- width: 100%; height: 0px;
227
- overflow: hidden;
228
- visibility: hidden;
229
- }
230
- .CodeMirror-measure pre { position: static; }
231
-
232
- .CodeMirror div.CodeMirror-cursor {
233
- position: absolute;
234
- visibility: hidden;
235
- border-right: none;
236
- width: 0;
237
- }
238
- .CodeMirror-focused div.CodeMirror-cursor {
239
- visibility: visible;
240
- }
241
-
242
- .CodeMirror-selected { background: #d9d9d9; }
243
- .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
244
-
245
- .cm-searching {
246
- background: #ffa;
247
- background: rgba(255, 255, 0, .4);
248
- }
249
-
250
- /* IE7 hack to prevent it from returning funny offsetTops on the spans */
251
- .CodeMirror span { *vertical-align: text-bottom; }
252
-
253
- @media print {
254
- /* Hide the cursor when printing */
255
- .CodeMirror div.CodeMirror-cursor {
256
- visibility: hidden;
257
- }
258
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codemirror/lib/codemirror.js DELETED
@@ -1,5799 +0,0 @@
1
- // CodeMirror version 3.15
2
- //
3
- // CodeMirror is the only global var we claim
4
- window.CodeMirror = (function() {
5
- "use strict";
6
-
7
- // BROWSER SNIFFING
8
-
9
- // Crude, but necessary to handle a number of hard-to-feature-detect
10
- // bugs and behavior differences.
11
- var gecko = /gecko\/\d/i.test(navigator.userAgent);
12
- var ie = /MSIE \d/.test(navigator.userAgent);
13
- var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
14
- var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
15
- var webkit = /WebKit\//.test(navigator.userAgent);
16
- var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
17
- var chrome = /Chrome\//.test(navigator.userAgent);
18
- var opera = /Opera\//.test(navigator.userAgent);
19
- var safari = /Apple Computer/.test(navigator.vendor);
20
- var khtml = /KHTML\//.test(navigator.userAgent);
21
- var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
22
- var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
23
- var phantom = /PhantomJS/.test(navigator.userAgent);
24
-
25
- var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
26
- // This is woefully incomplete. Suggestions for alternative methods welcome.
27
- var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
28
- var mac = ios || /Mac/.test(navigator.platform);
29
- var windows = /windows/i.test(navigator.platform);
30
-
31
- var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
32
- if (opera_version) opera_version = Number(opera_version[1]);
33
- if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
34
- // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
35
- var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
36
- var captureMiddleClick = gecko || (ie && !ie_lt9);
37
-
38
- // Optimize some code when these features are not used
39
- var sawReadOnlySpans = false, sawCollapsedSpans = false;
40
-
41
- // CONSTRUCTOR
42
-
43
- function CodeMirror(place, options) {
44
- if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
45
-
46
- this.options = options = options || {};
47
- // Determine effective options based on given values and defaults.
48
- for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
49
- options[opt] = defaults[opt];
50
- setGuttersForLineNumbers(options);
51
-
52
- var docStart = typeof options.value == "string" ? 0 : options.value.first;
53
- var display = this.display = makeDisplay(place, docStart);
54
- display.wrapper.CodeMirror = this;
55
- updateGutters(this);
56
- if (options.autofocus && !mobile) focusInput(this);
57
-
58
- this.state = {keyMaps: [],
59
- overlays: [],
60
- modeGen: 0,
61
- overwrite: false, focused: false,
62
- suppressEdits: false, pasteIncoming: false,
63
- draggingText: false,
64
- highlight: new Delayed()};
65
-
66
- themeChanged(this);
67
- if (options.lineWrapping)
68
- this.display.wrapper.className += " CodeMirror-wrap";
69
-
70
- var doc = options.value;
71
- if (typeof doc == "string") doc = new Doc(options.value, options.mode);
72
- operation(this, attachDoc)(this, doc);
73
-
74
- // Override magic textarea content restore that IE sometimes does
75
- // on our hidden textarea on reload
76
- if (ie) setTimeout(bind(resetInput, this, true), 20);
77
-
78
- registerEventHandlers(this);
79
- // IE throws unspecified error in certain cases, when
80
- // trying to access activeElement before onload
81
- var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
82
- if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
83
- else onBlur(this);
84
-
85
- operation(this, function() {
86
- for (var opt in optionHandlers)
87
- if (optionHandlers.propertyIsEnumerable(opt))
88
- optionHandlers[opt](this, options[opt], Init);
89
- for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
90
- })();
91
- }
92
-
93
- // DISPLAY CONSTRUCTOR
94
-
95
- function makeDisplay(place, docStart) {
96
- var d = {};
97
-
98
- var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
99
- if (webkit) input.style.width = "1000px";
100
- else input.setAttribute("wrap", "off");
101
- // if border: 0; -- iOS fails to open keyboard (issue #1287)
102
- if (ios) input.style.border = "1px solid black";
103
- input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
104
-
105
- // Wraps and hides input textarea
106
- d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
107
- // The actual fake scrollbars.
108
- d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
109
- d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
110
- d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
111
- d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
112
- // DIVs containing the selection and the actual code
113
- d.lineDiv = elt("div", null, "CodeMirror-code");
114
- d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
115
- // Blinky cursor, and element used to ensure cursor fits at the end of a line
116
- d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
117
- // Secondary cursor, shown when on a 'jump' in bi-directional text
118
- d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
119
- // Used to measure text size
120
- d.measure = elt("div", null, "CodeMirror-measure");
121
- // Wraps everything that needs to exist inside the vertically-padded coordinate system
122
- d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
123
- null, "position: relative; outline: none");
124
- // Moved around its parent to cover visible view
125
- d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
126
- // Set to the height of the text, causes scrolling
127
- d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
128
- // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
129
- d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
130
- // Will contain the gutters, if any
131
- d.gutters = elt("div", null, "CodeMirror-gutters");
132
- d.lineGutter = null;
133
- // Provides scrolling
134
- d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
135
- d.scroller.setAttribute("tabIndex", "-1");
136
- // The element in which the editor lives.
137
- d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
138
- d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
139
- // Work around IE7 z-index bug
140
- if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
141
- if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
142
-
143
- // Needed to hide big blue blinking cursor on Mobile Safari
144
- if (ios) input.style.width = "0px";
145
- if (!webkit) d.scroller.draggable = true;
146
- // Needed to handle Tab key in KHTML
147
- if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
148
- // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
149
- else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
150
-
151
- // Current visible range (may be bigger than the view window).
152
- d.viewOffset = d.lastSizeC = 0;
153
- d.showingFrom = d.showingTo = docStart;
154
-
155
- // Used to only resize the line number gutter when necessary (when
156
- // the amount of lines crosses a boundary that makes its width change)
157
- d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
158
- // See readInput and resetInput
159
- d.prevInput = "";
160
- // Set to true when a non-horizontal-scrolling widget is added. As
161
- // an optimization, widget aligning is skipped when d is false.
162
- d.alignWidgets = false;
163
- // Flag that indicates whether we currently expect input to appear
164
- // (after some event like 'keypress' or 'input') and are polling
165
- // intensively.
166
- d.pollingFast = false;
167
- // Self-resetting timeout for the poller
168
- d.poll = new Delayed();
169
-
170
- d.cachedCharWidth = d.cachedTextHeight = null;
171
- d.measureLineCache = [];
172
- d.measureLineCachePos = 0;
173
-
174
- // Tracks when resetInput has punted to just putting a short
175
- // string instead of the (large) selection.
176
- d.inaccurateSelection = false;
177
-
178
- // Tracks the maximum line length so that the horizontal scrollbar
179
- // can be kept static when scrolling.
180
- d.maxLine = null;
181
- d.maxLineLength = 0;
182
- d.maxLineChanged = false;
183
-
184
- // Used for measuring wheel scrolling granularity
185
- d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
186
-
187
- return d;
188
- }
189
-
190
- // STATE UPDATES
191
-
192
- // Used to get the editor into a consistent state again when options change.
193
-
194
- function loadMode(cm) {
195
- cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
196
- cm.doc.iter(function(line) {
197
- if (line.stateAfter) line.stateAfter = null;
198
- if (line.styles) line.styles = null;
199
- });
200
- cm.doc.frontier = cm.doc.first;
201
- startWorker(cm, 100);
202
- cm.state.modeGen++;
203
- if (cm.curOp) regChange(cm);
204
- }
205
-
206
- function wrappingChanged(cm) {
207
- if (cm.options.lineWrapping) {
208
- cm.display.wrapper.className += " CodeMirror-wrap";
209
- cm.display.sizer.style.minWidth = "";
210
- } else {
211
- cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
212
- computeMaxLength(cm);
213
- }
214
- estimateLineHeights(cm);
215
- regChange(cm);
216
- clearCaches(cm);
217
- setTimeout(function(){updateScrollbars(cm);}, 100);
218
- }
219
-
220
- function estimateHeight(cm) {
221
- var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
222
- var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
223
- return function(line) {
224
- if (lineIsHidden(cm.doc, line))
225
- return 0;
226
- else if (wrapping)
227
- return (Math.ceil(line.text.length / perLine) || 1) * th;
228
- else
229
- return th;
230
- };
231
- }
232
-
233
- function estimateLineHeights(cm) {
234
- var doc = cm.doc, est = estimateHeight(cm);
235
- doc.iter(function(line) {
236
- var estHeight = est(line);
237
- if (estHeight != line.height) updateLineHeight(line, estHeight);
238
- });
239
- }
240
-
241
- function keyMapChanged(cm) {
242
- var map = keyMap[cm.options.keyMap], style = map.style;
243
- cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
244
- (style ? " cm-keymap-" + style : "");
245
- cm.state.disableInput = map.disableInput;
246
- }
247
-
248
- function themeChanged(cm) {
249
- cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
250
- cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
251
- clearCaches(cm);
252
- }
253
-
254
- function guttersChanged(cm) {
255
- updateGutters(cm);
256
- regChange(cm);
257
- setTimeout(function(){alignHorizontally(cm);}, 20);
258
- }
259
-
260
- function updateGutters(cm) {
261
- var gutters = cm.display.gutters, specs = cm.options.gutters;
262
- removeChildren(gutters);
263
- for (var i = 0; i < specs.length; ++i) {
264
- var gutterClass = specs[i];
265
- var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
266
- if (gutterClass == "CodeMirror-linenumbers") {
267
- cm.display.lineGutter = gElt;
268
- gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
269
- }
270
- }
271
- gutters.style.display = i ? "" : "none";
272
- }
273
-
274
- function lineLength(doc, line) {
275
- if (line.height == 0) return 0;
276
- var len = line.text.length, merged, cur = line;
277
- while (merged = collapsedSpanAtStart(cur)) {
278
- var found = merged.find();
279
- cur = getLine(doc, found.from.line);
280
- len += found.from.ch - found.to.ch;
281
- }
282
- cur = line;
283
- while (merged = collapsedSpanAtEnd(cur)) {
284
- var found = merged.find();
285
- len -= cur.text.length - found.from.ch;
286
- cur = getLine(doc, found.to.line);
287
- len += cur.text.length - found.to.ch;
288
- }
289
- return len;
290
- }
291
-
292
- function computeMaxLength(cm) {
293
- var d = cm.display, doc = cm.doc;
294
- d.maxLine = getLine(doc, doc.first);
295
- d.maxLineLength = lineLength(doc, d.maxLine);
296
- d.maxLineChanged = true;
297
- doc.iter(function(line) {
298
- var len = lineLength(doc, line);
299
- if (len > d.maxLineLength) {
300
- d.maxLineLength = len;
301
- d.maxLine = line;
302
- }
303
- });
304
- }
305
-
306
- // Make sure the gutters options contains the element
307
- // "CodeMirror-linenumbers" when the lineNumbers option is true.
308
- function setGuttersForLineNumbers(options) {
309
- var found = false;
310
- for (var i = 0; i < options.gutters.length; ++i) {
311
- if (options.gutters[i] == "CodeMirror-linenumbers") {
312
- if (options.lineNumbers) found = true;
313
- else options.gutters.splice(i--, 1);
314
- }
315
- }
316
- if (!found && options.lineNumbers)
317
- options.gutters.push("CodeMirror-linenumbers");
318
- }
319
-
320
- // SCROLLBARS
321
-
322
- // Re-synchronize the fake scrollbars with the actual size of the
323
- // content. Optionally force a scrollTop.
324
- function updateScrollbars(cm) {
325
- var d = cm.display, docHeight = cm.doc.height;
326
- var totalHeight = docHeight + paddingVert(d);
327
- d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
328
- d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
329
- var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
330
- var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
331
- var needsV = scrollHeight > (d.scroller.clientHeight + 1);
332
- if (needsV) {
333
- d.scrollbarV.style.display = "block";
334
- d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
335
- d.scrollbarV.firstChild.style.height =
336
- (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
337
- } else d.scrollbarV.style.display = "";
338
- if (needsH) {
339
- d.scrollbarH.style.display = "block";
340
- d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
341
- d.scrollbarH.firstChild.style.width =
342
- (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
343
- } else d.scrollbarH.style.display = "";
344
- if (needsH && needsV) {
345
- d.scrollbarFiller.style.display = "block";
346
- d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
347
- } else d.scrollbarFiller.style.display = "";
348
- if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
349
- d.gutterFiller.style.display = "block";
350
- d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
351
- d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
352
- } else d.gutterFiller.style.display = "";
353
-
354
- if (mac_geLion && scrollbarWidth(d.measure) === 0)
355
- d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
356
- }
357
-
358
- function visibleLines(display, doc, viewPort) {
359
- var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
360
- if (typeof viewPort == "number") top = viewPort;
361
- else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
362
- top = Math.floor(top - paddingTop(display));
363
- var bottom = Math.ceil(top + height);
364
- return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
365
- }
366
-
367
- // LINE NUMBERS
368
-
369
- function alignHorizontally(cm) {
370
- var display = cm.display;
371
- if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
372
- var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
373
- var gutterW = display.gutters.offsetWidth, l = comp + "px";
374
- for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
375
- for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
376
- }
377
- if (cm.options.fixedGutter)
378
- display.gutters.style.left = (comp + gutterW) + "px";
379
- }
380
-
381
- function maybeUpdateLineNumberWidth(cm) {
382
- if (!cm.options.lineNumbers) return false;
383
- var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
384
- if (last.length != display.lineNumChars) {
385
- var test = display.measure.appendChild(elt("div", [elt("div", last)],
386
- "CodeMirror-linenumber CodeMirror-gutter-elt"));
387
- var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
388
- display.lineGutter.style.width = "";
389
- display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
390
- display.lineNumWidth = display.lineNumInnerWidth + padding;
391
- display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
392
- display.lineGutter.style.width = display.lineNumWidth + "px";
393
- return true;
394
- }
395
- return false;
396
- }
397
-
398
- function lineNumberFor(options, i) {
399
- return String(options.lineNumberFormatter(i + options.firstLineNumber));
400
- }
401
- function compensateForHScroll(display) {
402
- return getRect(display.scroller).left - getRect(display.sizer).left;
403
- }
404
-
405
- // DISPLAY DRAWING
406
-
407
- function updateDisplay(cm, changes, viewPort, forced) {
408
- var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
409
- var visible = visibleLines(cm.display, cm.doc, viewPort);
410
- for (;;) {
411
- if (!updateDisplayInner(cm, changes, visible, forced)) break;
412
- forced = false;
413
- updated = true;
414
- updateSelection(cm);
415
- updateScrollbars(cm);
416
-
417
- // Clip forced viewport to actual scrollable area
418
- if (viewPort)
419
- viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
420
- typeof viewPort == "number" ? viewPort : viewPort.top);
421
- visible = visibleLines(cm.display, cm.doc, viewPort);
422
- if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
423
- break;
424
- changes = [];
425
- }
426
-
427
- if (updated) {
428
- signalLater(cm, "update", cm);
429
- if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
430
- signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
431
- }
432
- return updated;
433
- }
434
-
435
- // Uses a set of changes plus the current scroll position to
436
- // determine which DOM updates have to be made, and makes the
437
- // updates.
438
- function updateDisplayInner(cm, changes, visible, forced) {
439
- var display = cm.display, doc = cm.doc;
440
- if (!display.wrapper.clientWidth) {
441
- display.showingFrom = display.showingTo = doc.first;
442
- display.viewOffset = 0;
443
- return;
444
- }
445
-
446
- // Bail out if the visible area is already rendered and nothing changed.
447
- if (!forced && changes.length == 0 &&
448
- visible.from > display.showingFrom && visible.to < display.showingTo)
449
- return;
450
-
451
- if (maybeUpdateLineNumberWidth(cm))
452
- changes = [{from: doc.first, to: doc.first + doc.size}];
453
- var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
454
- display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
455
-
456
- // Used to determine which lines need their line numbers updated
457
- var positionsChangedFrom = Infinity;
458
- if (cm.options.lineNumbers)
459
- for (var i = 0; i < changes.length; ++i)
460
- if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
461
-
462
- var end = doc.first + doc.size;
463
- var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
464
- var to = Math.min(end, visible.to + cm.options.viewportMargin);
465
- if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
466
- if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
467
- if (sawCollapsedSpans) {
468
- from = lineNo(visualLine(doc, getLine(doc, from)));
469
- while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
470
- }
471
-
472
- // Create a range of theoretically intact lines, and punch holes
473
- // in that using the change info.
474
- var intact = [{from: Math.max(display.showingFrom, doc.first),
475
- to: Math.min(display.showingTo, end)}];
476
- if (intact[0].from >= intact[0].to) intact = [];
477
- else intact = computeIntact(intact, changes);
478
- // When merged lines are present, we might have to reduce the
479
- // intact ranges because changes in continued fragments of the
480
- // intact lines do require the lines to be redrawn.
481
- if (sawCollapsedSpans)
482
- for (var i = 0; i < intact.length; ++i) {
483
- var range = intact[i], merged;
484
- while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
485
- var newTo = merged.find().from.line;
486
- if (newTo > range.from) range.to = newTo;
487
- else { intact.splice(i--, 1); break; }
488
- }
489
- }
490
-
491
- // Clip off the parts that won't be visible
492
- var intactLines = 0;
493
- for (var i = 0; i < intact.length; ++i) {
494
- var range = intact[i];
495
- if (range.from < from) range.from = from;
496
- if (range.to > to) range.to = to;
497
- if (range.from >= range.to) intact.splice(i--, 1);
498
- else intactLines += range.to - range.from;
499
- }
500
- if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
501
- updateViewOffset(cm);
502
- return;
503
- }
504
- intact.sort(function(a, b) {return a.from - b.from;});
505
-
506
- // Avoid crashing on IE's "unspecified error" when in iframes
507
- try {
508
- var focused = document.activeElement;
509
- } catch(e) {}
510
- if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
511
- patchDisplay(cm, from, to, intact, positionsChangedFrom);
512
- display.lineDiv.style.display = "";
513
- if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
514
-
515
- var different = from != display.showingFrom || to != display.showingTo ||
516
- display.lastSizeC != display.wrapper.clientHeight;
517
- // This is just a bogus formula that detects when the editor is
518
- // resized or the font size changes.
519
- if (different) {
520
- display.lastSizeC = display.wrapper.clientHeight;
521
- startWorker(cm, 400);
522
- }
523
- display.showingFrom = from; display.showingTo = to;
524
-
525
- updateHeightsInViewport(cm);
526
- updateViewOffset(cm);
527
-
528
- return true;
529
- }
530
-
531
- function updateHeightsInViewport(cm) {
532
- var display = cm.display;
533
- var prevBottom = display.lineDiv.offsetTop;
534
- for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
535
- if (ie_lt8) {
536
- var bot = node.offsetTop + node.offsetHeight;
537
- height = bot - prevBottom;
538
- prevBottom = bot;
539
- } else {
540
- var box = getRect(node);
541
- height = box.bottom - box.top;
542
- }
543
- var diff = node.lineObj.height - height;
544
- if (height < 2) height = textHeight(display);
545
- if (diff > .001 || diff < -.001) {
546
- updateLineHeight(node.lineObj, height);
547
- var widgets = node.lineObj.widgets;
548
- if (widgets) for (var i = 0; i < widgets.length; ++i)
549
- widgets[i].height = widgets[i].node.offsetHeight;
550
- }
551
- }
552
- }
553
-
554
- function updateViewOffset(cm) {
555
- var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
556
- // Position the mover div to align with the current virtual scroll position
557
- cm.display.mover.style.top = off + "px";
558
- }
559
-
560
- function computeIntact(intact, changes) {
561
- for (var i = 0, l = changes.length || 0; i < l; ++i) {
562
- var change = changes[i], intact2 = [], diff = change.diff || 0;
563
- for (var j = 0, l2 = intact.length; j < l2; ++j) {
564
- var range = intact[j];
565
- if (change.to <= range.from && change.diff) {
566
- intact2.push({from: range.from + diff, to: range.to + diff});
567
- } else if (change.to <= range.from || change.from >= range.to) {
568
- intact2.push(range);
569
- } else {
570
- if (change.from > range.from)
571
- intact2.push({from: range.from, to: change.from});
572
- if (change.to < range.to)
573
- intact2.push({from: change.to + diff, to: range.to + diff});
574
- }
575
- }
576
- intact = intact2;
577
- }
578
- return intact;
579
- }
580
-
581
- function getDimensions(cm) {
582
- var d = cm.display, left = {}, width = {};
583
- for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
584
- left[cm.options.gutters[i]] = n.offsetLeft;
585
- width[cm.options.gutters[i]] = n.offsetWidth;
586
- }
587
- return {fixedPos: compensateForHScroll(d),
588
- gutterTotalWidth: d.gutters.offsetWidth,
589
- gutterLeft: left,
590
- gutterWidth: width,
591
- wrapperWidth: d.wrapper.clientWidth};
592
- }
593
-
594
- function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
595
- var dims = getDimensions(cm);
596
- var display = cm.display, lineNumbers = cm.options.lineNumbers;
597
- if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
598
- removeChildren(display.lineDiv);
599
- var container = display.lineDiv, cur = container.firstChild;
600
-
601
- function rm(node) {
602
- var next = node.nextSibling;
603
- if (webkit && mac && cm.display.currentWheelTarget == node) {
604
- node.style.display = "none";
605
- node.lineObj = null;
606
- } else {
607
- node.parentNode.removeChild(node);
608
- }
609
- return next;
610
- }
611
-
612
- var nextIntact = intact.shift(), lineN = from;
613
- cm.doc.iter(from, to, function(line) {
614
- if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
615
- if (lineIsHidden(cm.doc, line)) {
616
- if (line.height != 0) updateLineHeight(line, 0);
617
- if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
618
- var w = line.widgets[i];
619
- if (w.showIfHidden) {
620
- var prev = cur.previousSibling;
621
- if (/pre/i.test(prev.nodeName)) {
622
- var wrap = elt("div", null, null, "position: relative");
623
- prev.parentNode.replaceChild(wrap, prev);
624
- wrap.appendChild(prev);
625
- prev = wrap;
626
- }
627
- var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
628
- if (!w.handleMouseEvents) wnode.ignoreEvents = true;
629
- positionLineWidget(w, wnode, prev, dims);
630
- }
631
- }
632
- } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
633
- // This line is intact. Skip to the actual node. Update its
634
- // line number if needed.
635
- while (cur.lineObj != line) cur = rm(cur);
636
- if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
637
- setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
638
- cur = cur.nextSibling;
639
- } else {
640
- // For lines with widgets, make an attempt to find and reuse
641
- // the existing element, so that widgets aren't needlessly
642
- // removed and re-inserted into the dom
643
- if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
644
- if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
645
- // This line needs to be generated.
646
- var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
647
- if (lineNode != reuse) {
648
- container.insertBefore(lineNode, cur);
649
- } else {
650
- while (cur != reuse) cur = rm(cur);
651
- cur = cur.nextSibling;
652
- }
653
-
654
- lineNode.lineObj = line;
655
- }
656
- ++lineN;
657
- });
658
- while (cur) cur = rm(cur);
659
- }
660
-
661
- function buildLineElement(cm, line, lineNo, dims, reuse) {
662
- var lineElement = lineContent(cm, line);
663
- var markers = line.gutterMarkers, display = cm.display, wrap;
664
-
665
- if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
666
- return lineElement;
667
-
668
- // Lines with gutter elements, widgets or a background class need
669
- // to be wrapped again, and have the extra elements added to the
670
- // wrapper div
671
-
672
- if (reuse) {
673
- reuse.alignable = null;
674
- var isOk = true, widgetsSeen = 0, insertBefore = null;
675
- for (var n = reuse.firstChild, next; n; n = next) {
676
- next = n.nextSibling;
677
- if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
678
- reuse.removeChild(n);
679
- } else {
680
- for (var i = 0; i < line.widgets.length; ++i) {
681
- var widget = line.widgets[i];
682
- if (widget.node == n.firstChild) {
683
- if (!widget.above && !insertBefore) insertBefore = n;
684
- positionLineWidget(widget, n, reuse, dims);
685
- ++widgetsSeen;
686
- break;
687
- }
688
- }
689
- if (i == line.widgets.length) { isOk = false; break; }
690
- }
691
- }
692
- reuse.insertBefore(lineElement, insertBefore);
693
- if (isOk && widgetsSeen == line.widgets.length) {
694
- wrap = reuse;
695
- reuse.className = line.wrapClass || "";
696
- }
697
- }
698
- if (!wrap) {
699
- wrap = elt("div", null, line.wrapClass, "position: relative");
700
- wrap.appendChild(lineElement);
701
- }
702
- // Kludge to make sure the styled element lies behind the selection (by z-index)
703
- if (line.bgClass)
704
- wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
705
- if (cm.options.lineNumbers || markers) {
706
- var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
707
- (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
708
- wrap.firstChild);
709
- if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
710
- if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
711
- wrap.lineNumber = gutterWrap.appendChild(
712
- elt("div", lineNumberFor(cm.options, lineNo),
713
- "CodeMirror-linenumber CodeMirror-gutter-elt",
714
- "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
715
- + display.lineNumInnerWidth + "px"));
716
- if (markers)
717
- for (var k = 0; k < cm.options.gutters.length; ++k) {
718
- var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
719
- if (found)
720
- gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
721
- dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
722
- }
723
- }
724
- if (ie_lt8) wrap.style.zIndex = 2;
725
- if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
726
- var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
727
- if (!widget.handleMouseEvents) node.ignoreEvents = true;
728
- positionLineWidget(widget, node, wrap, dims);
729
- if (widget.above)
730
- wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
731
- else
732
- wrap.appendChild(node);
733
- signalLater(widget, "redraw");
734
- }
735
- return wrap;
736
- }
737
-
738
- function positionLineWidget(widget, node, wrap, dims) {
739
- if (widget.noHScroll) {
740
- (wrap.alignable || (wrap.alignable = [])).push(node);
741
- var width = dims.wrapperWidth;
742
- node.style.left = dims.fixedPos + "px";
743
- if (!widget.coverGutter) {
744
- width -= dims.gutterTotalWidth;
745
- node.style.paddingLeft = dims.gutterTotalWidth + "px";
746
- }
747
- node.style.width = width + "px";
748
- }
749
- if (widget.coverGutter) {
750
- node.style.zIndex = 5;
751
- node.style.position = "relative";
752
- if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
753
- }
754
- }
755
-
756
- // SELECTION / CURSOR
757
-
758
- function updateSelection(cm) {
759
- var display = cm.display;
760
- var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
761
- if (collapsed || cm.options.showCursorWhenSelecting)
762
- updateSelectionCursor(cm);
763
- else
764
- display.cursor.style.display = display.otherCursor.style.display = "none";
765
- if (!collapsed)
766
- updateSelectionRange(cm);
767
- else
768
- display.selectionDiv.style.display = "none";
769
-
770
- // Move the hidden textarea near the cursor to prevent scrolling artifacts
771
- if (cm.options.moveInputWithCursor) {
772
- var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
773
- var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
774
- display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
775
- headPos.top + lineOff.top - wrapOff.top)) + "px";
776
- display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
777
- headPos.left + lineOff.left - wrapOff.left)) + "px";
778
- }
779
- }
780
-
781
- // No selection, plain cursor
782
- function updateSelectionCursor(cm) {
783
- var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
784
- display.cursor.style.left = pos.left + "px";
785
- display.cursor.style.top = pos.top + "px";
786
- display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
787
- display.cursor.style.display = "";
788
-
789
- if (pos.other) {
790
- display.otherCursor.style.display = "";
791
- display.otherCursor.style.left = pos.other.left + "px";
792
- display.otherCursor.style.top = pos.other.top + "px";
793
- display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
794
- } else { display.otherCursor.style.display = "none"; }
795
- }
796
-
797
- // Highlight selection
798
- function updateSelectionRange(cm) {
799
- var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
800
- var fragment = document.createDocumentFragment();
801
- var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
802
-
803
- function add(left, top, width, bottom) {
804
- if (top < 0) top = 0;
805
- fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
806
- "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
807
- "px; height: " + (bottom - top) + "px"));
808
- }
809
-
810
- function drawForLine(line, fromArg, toArg) {
811
- var lineObj = getLine(doc, line);
812
- var lineLen = lineObj.text.length;
813
- var start, end;
814
- function coords(ch, bias) {
815
- return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
816
- }
817
-
818
- iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
819
- var leftPos = coords(from, "left"), rightPos, left, right;
820
- if (from == to) {
821
- rightPos = leftPos;
822
- left = right = leftPos.left;
823
- } else {
824
- rightPos = coords(to - 1, "right");
825
- if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
826
- left = leftPos.left;
827
- right = rightPos.right;
828
- }
829
- if (fromArg == null && from == 0) left = pl;
830
- if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
831
- add(left, leftPos.top, null, leftPos.bottom);
832
- left = pl;
833
- if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
834
- }
835
- if (toArg == null && to == lineLen) right = clientWidth;
836
- if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
837
- start = leftPos;
838
- if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
839
- end = rightPos;
840
- if (left < pl + 1) left = pl;
841
- add(left, rightPos.top, right - left, rightPos.bottom);
842
- });
843
- return {start: start, end: end};
844
- }
845
-
846
- if (sel.from.line == sel.to.line) {
847
- drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
848
- } else {
849
- var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
850
- var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
851
- var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
852
- var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
853
- if (singleVLine) {
854
- if (leftEnd.top < rightStart.top - 2) {
855
- add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
856
- add(pl, rightStart.top, rightStart.left, rightStart.bottom);
857
- } else {
858
- add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
859
- }
860
- }
861
- if (leftEnd.bottom < rightStart.top)
862
- add(pl, leftEnd.bottom, null, rightStart.top);
863
- }
864
-
865
- removeChildrenAndAdd(display.selectionDiv, fragment);
866
- display.selectionDiv.style.display = "";
867
- }
868
-
869
- // Cursor-blinking
870
- function restartBlink(cm) {
871
- if (!cm.state.focused) return;
872
- var display = cm.display;
873
- clearInterval(display.blinker);
874
- var on = true;
875
- display.cursor.style.visibility = display.otherCursor.style.visibility = "";
876
- display.blinker = setInterval(function() {
877
- display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
878
- }, cm.options.cursorBlinkRate);
879
- }
880
-
881
- // HIGHLIGHT WORKER
882
-
883
- function startWorker(cm, time) {
884
- if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
885
- cm.state.highlight.set(time, bind(highlightWorker, cm));
886
- }
887
-
888
- function highlightWorker(cm) {
889
- var doc = cm.doc;
890
- if (doc.frontier < doc.first) doc.frontier = doc.first;
891
- if (doc.frontier >= cm.display.showingTo) return;
892
- var end = +new Date + cm.options.workTime;
893
- var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
894
- var changed = [], prevChange;
895
- doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
896
- if (doc.frontier >= cm.display.showingFrom) { // Visible
897
- var oldStyles = line.styles;
898
- line.styles = highlightLine(cm, line, state);
899
- var ischange = !oldStyles || oldStyles.length != line.styles.length;
900
- for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
901
- if (ischange) {
902
- if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
903
- else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
904
- }
905
- line.stateAfter = copyState(doc.mode, state);
906
- } else {
907
- processLine(cm, line, state);
908
- line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
909
- }
910
- ++doc.frontier;
911
- if (+new Date > end) {
912
- startWorker(cm, cm.options.workDelay);
913
- return true;
914
- }
915
- });
916
- if (changed.length)
917
- operation(cm, function() {
918
- for (var i = 0; i < changed.length; ++i)
919
- regChange(this, changed[i].start, changed[i].end);
920
- })();
921
- }
922
-
923
- // Finds the line to start with when starting a parse. Tries to
924
- // find a line with a stateAfter, so that it can start with a
925
- // valid state. If that fails, it returns the line with the
926
- // smallest indentation, which tends to need the least context to
927
- // parse correctly.
928
- function findStartLine(cm, n, precise) {
929
- var minindent, minline, doc = cm.doc;
930
- for (var search = n, lim = n - 100; search > lim; --search) {
931
- if (search <= doc.first) return doc.first;
932
- var line = getLine(doc, search - 1);
933
- if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
934
- var indented = countColumn(line.text, null, cm.options.tabSize);
935
- if (minline == null || minindent > indented) {
936
- minline = search - 1;
937
- minindent = indented;
938
- }
939
- }
940
- return minline;
941
- }
942
-
943
- function getStateBefore(cm, n, precise) {
944
- var doc = cm.doc, display = cm.display;
945
- if (!doc.mode.startState) return true;
946
- var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
947
- if (!state) state = startState(doc.mode);
948
- else state = copyState(doc.mode, state);
949
- doc.iter(pos, n, function(line) {
950
- processLine(cm, line, state);
951
- var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
952
- line.stateAfter = save ? copyState(doc.mode, state) : null;
953
- ++pos;
954
- });
955
- return state;
956
- }
957
-
958
- // POSITION MEASUREMENT
959
-
960
- function paddingTop(display) {return display.lineSpace.offsetTop;}
961
- function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
962
- function paddingLeft(display) {
963
- var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
964
- return e.offsetLeft;
965
- }
966
-
967
- function measureChar(cm, line, ch, data, bias) {
968
- var dir = -1;
969
- data = data || measureLine(cm, line);
970
-
971
- for (var pos = ch;; pos += dir) {
972
- var r = data[pos];
973
- if (r) break;
974
- if (dir < 0 && pos == 0) dir = 1;
975
- }
976
- bias = pos > ch ? "left" : pos < ch ? "right" : bias;
977
- if (bias == "left" && r.leftSide) r = r.leftSide;
978
- else if (bias == "right" && r.rightSide) r = r.rightSide;
979
- return {left: pos < ch ? r.right : r.left,
980
- right: pos > ch ? r.left : r.right,
981
- top: r.top,
982
- bottom: r.bottom};
983
- }
984
-
985
- function findCachedMeasurement(cm, line) {
986
- var cache = cm.display.measureLineCache;
987
- for (var i = 0; i < cache.length; ++i) {
988
- var memo = cache[i];
989
- if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
990
- cm.display.scroller.clientWidth == memo.width &&
991
- memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
992
- return memo;
993
- }
994
- }
995
-
996
- function clearCachedMeasurement(cm, line) {
997
- var exists = findCachedMeasurement(cm, line);
998
- if (exists) exists.text = exists.measure = exists.markedSpans = null;
999
- }
1000
-
1001
- function measureLine(cm, line) {
1002
- // First look in the cache
1003
- var cached = findCachedMeasurement(cm, line);
1004
- if (cached) return cached.measure;
1005
-
1006
- // Failing that, recompute and store result in cache
1007
- var measure = measureLineInner(cm, line);
1008
- var cache = cm.display.measureLineCache;
1009
- var memo = {text: line.text, width: cm.display.scroller.clientWidth,
1010
- markedSpans: line.markedSpans, measure: measure,
1011
- classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
1012
- if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
1013
- else cache.push(memo);
1014
- return measure;
1015
- }
1016
-
1017
- function measureLineInner(cm, line) {
1018
- var display = cm.display, measure = emptyArray(line.text.length);
1019
- var pre = lineContent(cm, line, measure, true);
1020
-
1021
- // IE does not cache element positions of inline elements between
1022
- // calls to getBoundingClientRect. This makes the loop below,
1023
- // which gathers the positions of all the characters on the line,
1024
- // do an amount of layout work quadratic to the number of
1025
- // characters. When line wrapping is off, we try to improve things
1026
- // by first subdividing the line into a bunch of inline blocks, so
1027
- // that IE can reuse most of the layout information from caches
1028
- // for those blocks. This does interfere with line wrapping, so it
1029
- // doesn't work when wrapping is on, but in that case the
1030
- // situation is slightly better, since IE does cache line-wrapping
1031
- // information and only recomputes per-line.
1032
- if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
1033
- var fragment = document.createDocumentFragment();
1034
- var chunk = 10, n = pre.childNodes.length;
1035
- for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
1036
- var wrap = elt("div", null, null, "display: inline-block");
1037
- for (var j = 0; j < chunk && n; ++j) {
1038
- wrap.appendChild(pre.firstChild);
1039
- --n;
1040
- }
1041
- fragment.appendChild(wrap);
1042
- }
1043
- pre.appendChild(fragment);
1044
- }
1045
-
1046
- removeChildrenAndAdd(display.measure, pre);
1047
-
1048
- var outer = getRect(display.lineDiv);
1049
- var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
1050
- // Work around an IE7/8 bug where it will sometimes have randomly
1051
- // replaced our pre with a clone at this point.
1052
- if (ie_lt9 && display.measure.first != pre)
1053
- removeChildrenAndAdd(display.measure, pre);
1054
-
1055
- function measureRect(rect) {
1056
- var top = rect.top - outer.top, bot = rect.bottom - outer.top;
1057
- if (bot > maxBot) bot = maxBot;
1058
- if (top < 0) top = 0;
1059
- for (var i = vranges.length - 2; i >= 0; i -= 2) {
1060
- var rtop = vranges[i], rbot = vranges[i+1];
1061
- if (rtop > bot || rbot < top) continue;
1062
- if (rtop <= top && rbot >= bot ||
1063
- top <= rtop && bot >= rbot ||
1064
- Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
1065
- vranges[i] = Math.min(top, rtop);
1066
- vranges[i+1] = Math.max(bot, rbot);
1067
- break;
1068
- }
1069
- }
1070
- if (i < 0) { i = vranges.length; vranges.push(top, bot); }
1071
- return {left: rect.left - outer.left,
1072
- right: rect.right - outer.left,
1073
- top: i, bottom: null};
1074
- }
1075
- function finishRect(rect) {
1076
- rect.bottom = vranges[rect.top+1];
1077
- rect.top = vranges[rect.top];
1078
- }
1079
-
1080
- for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
1081
- var node = cur, rect = null;
1082
- // A widget might wrap, needs special care
1083
- if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
1084
- if (cur.firstChild.nodeType == 1) node = cur.firstChild;
1085
- var rects = node.getClientRects();
1086
- if (rects.length > 1) {
1087
- rect = data[i] = measureRect(rects[0]);
1088
- rect.rightSide = measureRect(rects[rects.length - 1]);
1089
- }
1090
- }
1091
- if (!rect) rect = data[i] = measureRect(getRect(node));
1092
- if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
1093
- if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
1094
- }
1095
- for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
1096
- finishRect(cur);
1097
- if (cur.leftSide) finishRect(cur.leftSide);
1098
- if (cur.rightSide) finishRect(cur.rightSide);
1099
- }
1100
- return data;
1101
- }
1102
-
1103
- function measureLineWidth(cm, line) {
1104
- var hasBadSpan = false;
1105
- if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
1106
- var sp = line.markedSpans[i];
1107
- if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
1108
- }
1109
- var cached = !hasBadSpan && findCachedMeasurement(cm, line);
1110
- if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
1111
-
1112
- var pre = lineContent(cm, line, null, true);
1113
- var end = pre.appendChild(zeroWidthElement(cm.display.measure));
1114
- removeChildrenAndAdd(cm.display.measure, pre);
1115
- return getRect(end).right - getRect(cm.display.lineDiv).left;
1116
- }
1117
-
1118
- function clearCaches(cm) {
1119
- cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
1120
- cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
1121
- if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
1122
- cm.display.lineNumChars = null;
1123
- }
1124
-
1125
- function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
1126
- function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
1127
-
1128
- // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
1129
- function intoCoordSystem(cm, lineObj, rect, context) {
1130
- if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
1131
- var size = widgetHeight(lineObj.widgets[i]);
1132
- rect.top += size; rect.bottom += size;
1133
- }
1134
- if (context == "line") return rect;
1135
- if (!context) context = "local";
1136
- var yOff = heightAtLine(cm, lineObj);
1137
- if (context == "local") yOff += paddingTop(cm.display);
1138
- else yOff -= cm.display.viewOffset;
1139
- if (context == "page" || context == "window") {
1140
- var lOff = getRect(cm.display.lineSpace);
1141
- yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
1142
- var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
1143
- rect.left += xOff; rect.right += xOff;
1144
- }
1145
- rect.top += yOff; rect.bottom += yOff;
1146
- return rect;
1147
- }
1148
-
1149
- // Context may be "window", "page", "div", or "local"/null
1150
- // Result is in "div" coords
1151
- function fromCoordSystem(cm, coords, context) {
1152
- if (context == "div") return coords;
1153
- var left = coords.left, top = coords.top;
1154
- // First move into "page" coordinate system
1155
- if (context == "page") {
1156
- left -= pageScrollX();
1157
- top -= pageScrollY();
1158
- } else if (context == "local" || !context) {
1159
- var localBox = getRect(cm.display.sizer);
1160
- left += localBox.left;
1161
- top += localBox.top;
1162
- }
1163
-
1164
- var lineSpaceBox = getRect(cm.display.lineSpace);
1165
- return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
1166
- }
1167
-
1168
- function charCoords(cm, pos, context, lineObj, bias) {
1169
- if (!lineObj) lineObj = getLine(cm.doc, pos.line);
1170
- return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
1171
- }
1172
-
1173
- function cursorCoords(cm, pos, context, lineObj, measurement) {
1174
- lineObj = lineObj || getLine(cm.doc, pos.line);
1175
- if (!measurement) measurement = measureLine(cm, lineObj);
1176
- function get(ch, right) {
1177
- var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
1178
- if (right) m.left = m.right; else m.right = m.left;
1179
- return intoCoordSystem(cm, lineObj, m, context);
1180
- }
1181
- function getBidi(ch, partPos) {
1182
- var part = order[partPos], right = part.level % 2;
1183
- if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
1184
- part = order[--partPos];
1185
- ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
1186
- right = true;
1187
- } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
1188
- part = order[++partPos];
1189
- ch = bidiLeft(part) - part.level % 2;
1190
- right = false;
1191
- }
1192
- if (right && ch == part.to && ch > part.from) return get(ch - 1);
1193
- return get(ch, right);
1194
- }
1195
- var order = getOrder(lineObj), ch = pos.ch;
1196
- if (!order) return get(ch);
1197
- var partPos = getBidiPartAt(order, ch);
1198
- var val = getBidi(ch, partPos);
1199
- if (bidiOther != null) val.other = getBidi(ch, bidiOther);
1200
- return val;
1201
- }
1202
-
1203
- function PosWithInfo(line, ch, outside, xRel) {
1204
- var pos = new Pos(line, ch);
1205
- pos.xRel = xRel;
1206
- if (outside) pos.outside = true;
1207
- return pos;
1208
- }
1209
-
1210
- // Coords must be lineSpace-local
1211
- function coordsChar(cm, x, y) {
1212
- var doc = cm.doc;
1213
- y += cm.display.viewOffset;
1214
- if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
1215
- var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
1216
- if (lineNo > last)
1217
- return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
1218
- if (x < 0) x = 0;
1219
-
1220
- for (;;) {
1221
- var lineObj = getLine(doc, lineNo);
1222
- var found = coordsCharInner(cm, lineObj, lineNo, x, y);
1223
- var merged = collapsedSpanAtEnd(lineObj);
1224
- var mergedPos = merged && merged.find();
1225
- if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
1226
- lineNo = mergedPos.to.line;
1227
- else
1228
- return found;
1229
- }
1230
- }
1231
-
1232
- function coordsCharInner(cm, lineObj, lineNo, x, y) {
1233
- var innerOff = y - heightAtLine(cm, lineObj);
1234
- var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
1235
- var measurement = measureLine(cm, lineObj);
1236
-
1237
- function getX(ch) {
1238
- var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
1239
- lineObj, measurement);
1240
- wrongLine = true;
1241
- if (innerOff > sp.bottom) return sp.left - adjust;
1242
- else if (innerOff < sp.top) return sp.left + adjust;
1243
- else wrongLine = false;
1244
- return sp.left;
1245
- }
1246
-
1247
- var bidi = getOrder(lineObj), dist = lineObj.text.length;
1248
- var from = lineLeft(lineObj), to = lineRight(lineObj);
1249
- var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
1250
-
1251
- if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
1252
- // Do a binary search between these bounds.
1253
- for (;;) {
1254
- if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
1255
- var ch = x < fromX || x - fromX <= toX - x ? from : to;
1256
- var xDiff = x - (ch == from ? fromX : toX);
1257
- while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
1258
- var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
1259
- xDiff < 0 ? -1 : xDiff ? 1 : 0);
1260
- return pos;
1261
- }
1262
- var step = Math.ceil(dist / 2), middle = from + step;
1263
- if (bidi) {
1264
- middle = from;
1265
- for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
1266
- }
1267
- var middleX = getX(middle);
1268
- if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
1269
- else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
1270
- }
1271
- }
1272
-
1273
- var measureText;
1274
- function textHeight(display) {
1275
- if (display.cachedTextHeight != null) return display.cachedTextHeight;
1276
- if (measureText == null) {
1277
- measureText = elt("pre");
1278
- // Measure a bunch of lines, for browsers that compute
1279
- // fractional heights.
1280
- for (var i = 0; i < 49; ++i) {
1281
- measureText.appendChild(document.createTextNode("x"));
1282
- measureText.appendChild(elt("br"));
1283
- }
1284
- measureText.appendChild(document.createTextNode("x"));
1285
- }
1286
- removeChildrenAndAdd(display.measure, measureText);
1287
- var height = measureText.offsetHeight / 50;
1288
- if (height > 3) display.cachedTextHeight = height;
1289
- removeChildren(display.measure);
1290
- return height || 1;
1291
- }
1292
-
1293
- function charWidth(display) {
1294
- if (display.cachedCharWidth != null) return display.cachedCharWidth;
1295
- var anchor = elt("span", "x");
1296
- var pre = elt("pre", [anchor]);
1297
- removeChildrenAndAdd(display.measure, pre);
1298
- var width = anchor.offsetWidth;
1299
- if (width > 2) display.cachedCharWidth = width;
1300
- return width || 10;
1301
- }
1302
-
1303
- // OPERATIONS
1304
-
1305
- // Operations are used to wrap changes in such a way that each
1306
- // change won't have to update the cursor and display (which would
1307
- // be awkward, slow, and error-prone), but instead updates are
1308
- // batched and then all combined and executed at once.
1309
-
1310
- var nextOpId = 0;
1311
- function startOperation(cm) {
1312
- cm.curOp = {
1313
- // An array of ranges of lines that have to be updated. See
1314
- // updateDisplay.
1315
- changes: [],
1316
- forceUpdate: false,
1317
- updateInput: null,
1318
- userSelChange: null,
1319
- textChanged: null,
1320
- selectionChanged: false,
1321
- cursorActivity: false,
1322
- updateMaxLine: false,
1323
- updateScrollPos: false,
1324
- id: ++nextOpId
1325
- };
1326
- if (!delayedCallbackDepth++) delayedCallbacks = [];
1327
- }
1328
-
1329
- function endOperation(cm) {
1330
- var op = cm.curOp, doc = cm.doc, display = cm.display;
1331
- cm.curOp = null;
1332
-
1333
- if (op.updateMaxLine) computeMaxLength(cm);
1334
- if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
1335
- var width = measureLineWidth(cm, display.maxLine);
1336
- display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
1337
- display.maxLineChanged = false;
1338
- var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
1339
- if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
1340
- setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
1341
- }
1342
- var newScrollPos, updated;
1343
- if (op.updateScrollPos) {
1344
- newScrollPos = op.updateScrollPos;
1345
- } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
1346
- var coords = cursorCoords(cm, doc.sel.head);
1347
- newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
1348
- }
1349
- if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
1350
- updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
1351
- if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
1352
- }
1353
- if (!updated && op.selectionChanged) updateSelection(cm);
1354
- if (op.updateScrollPos) {
1355
- display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
1356
- display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
1357
- alignHorizontally(cm);
1358
- if (op.scrollToPos)
1359
- scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
1360
- } else if (newScrollPos) {
1361
- scrollCursorIntoView(cm);
1362
- }
1363
- if (op.selectionChanged) restartBlink(cm);
1364
-
1365
- if (cm.state.focused && op.updateInput)
1366
- resetInput(cm, op.userSelChange);
1367
-
1368
- var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
1369
- if (hidden) for (var i = 0; i < hidden.length; ++i)
1370
- if (!hidden[i].lines.length) signal(hidden[i], "hide");
1371
- if (unhidden) for (var i = 0; i < unhidden.length; ++i)
1372
- if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
1373
-
1374
- var delayed;
1375
- if (!--delayedCallbackDepth) {
1376
- delayed = delayedCallbacks;
1377
- delayedCallbacks = null;
1378
- }
1379
- if (op.textChanged)
1380
- signal(cm, "change", cm, op.textChanged);
1381
- if (op.cursorActivity) signal(cm, "cursorActivity", cm);
1382
- if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
1383
- }
1384
-
1385
- // Wraps a function in an operation. Returns the wrapped function.
1386
- function operation(cm1, f) {
1387
- return function() {
1388
- var cm = cm1 || this, withOp = !cm.curOp;
1389
- if (withOp) startOperation(cm);
1390
- try { var result = f.apply(cm, arguments); }
1391
- finally { if (withOp) endOperation(cm); }
1392
- return result;
1393
- };
1394
- }
1395
- function docOperation(f) {
1396
- return function() {
1397
- var withOp = this.cm && !this.cm.curOp, result;
1398
- if (withOp) startOperation(this.cm);
1399
- try { result = f.apply(this, arguments); }
1400
- finally { if (withOp) endOperation(this.cm); }
1401
- return result;
1402
- };
1403
- }
1404
- function runInOp(cm, f) {
1405
- var withOp = !cm.curOp, result;
1406
- if (withOp) startOperation(cm);
1407
- try { result = f(); }
1408
- finally { if (withOp) endOperation(cm); }
1409
- return result;
1410
- }
1411
-
1412
- function regChange(cm, from, to, lendiff) {
1413
- if (from == null) from = cm.doc.first;
1414
- if (to == null) to = cm.doc.first + cm.doc.size;
1415
- cm.curOp.changes.push({from: from, to: to, diff: lendiff});
1416
- }
1417
-
1418
- // INPUT HANDLING
1419
-
1420
- function slowPoll(cm) {
1421
- if (cm.display.pollingFast) return;
1422
- cm.display.poll.set(cm.options.pollInterval, function() {
1423
- readInput(cm);
1424
- if (cm.state.focused) slowPoll(cm);
1425
- });
1426
- }
1427
-
1428
- function fastPoll(cm) {
1429
- var missed = false;
1430
- cm.display.pollingFast = true;
1431
- function p() {
1432
- var changed = readInput(cm);
1433
- if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
1434
- else {cm.display.pollingFast = false; slowPoll(cm);}
1435
- }
1436
- cm.display.poll.set(20, p);
1437
- }
1438
-
1439
- // prevInput is a hack to work with IME. If we reset the textarea
1440
- // on every change, that breaks IME. So we look for changes
1441
- // compared to the previous content instead. (Modern browsers have
1442
- // events that indicate IME taking place, but these are not widely
1443
- // supported or compatible enough yet to rely on.)
1444
- function readInput(cm) {
1445
- var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
1446
- if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
1447
- var text = input.value;
1448
- if (text == prevInput && posEq(sel.from, sel.to)) return false;
1449
- if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
1450
- resetInput(cm, true);
1451
- return false;
1452
- }
1453
-
1454
- var withOp = !cm.curOp;
1455
- if (withOp) startOperation(cm);
1456
- sel.shift = false;
1457
- var same = 0, l = Math.min(prevInput.length, text.length);
1458
- while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1459
- var from = sel.from, to = sel.to;
1460
- if (same < prevInput.length)
1461
- from = Pos(from.line, from.ch - (prevInput.length - same));
1462
- else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
1463
- to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
1464
-
1465
- var updateInput = cm.curOp.updateInput;
1466
- var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
1467
- origin: cm.state.pasteIncoming ? "paste" : "+input"};
1468
- makeChange(cm.doc, changeEvent, "end");
1469
- cm.curOp.updateInput = updateInput;
1470
- signalLater(cm, "inputRead", cm, changeEvent);
1471
-
1472
- if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
1473
- else cm.display.prevInput = text;
1474
- if (withOp) endOperation(cm);
1475
- cm.state.pasteIncoming = false;
1476
- return true;
1477
- }
1478
-
1479
- function resetInput(cm, user) {
1480
- var minimal, selected, doc = cm.doc;
1481
- if (!posEq(doc.sel.from, doc.sel.to)) {
1482
- cm.display.prevInput = "";
1483
- minimal = hasCopyEvent &&
1484
- (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
1485
- var content = minimal ? "-" : selected || cm.getSelection();
1486
- cm.display.input.value = content;
1487
- if (cm.state.focused) selectInput(cm.display.input);
1488
- if (ie && !ie_lt9) cm.display.inputHasSelection = content;
1489
- } else if (user) {
1490
- cm.display.prevInput = cm.display.input.value = "";
1491
- if (ie && !ie_lt9) cm.display.inputHasSelection = null;
1492
- }
1493
- cm.display.inaccurateSelection = minimal;
1494
- }
1495
-
1496
- function focusInput(cm) {
1497
- if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
1498
- cm.display.input.focus();
1499
- }
1500
-
1501
- function isReadOnly(cm) {
1502
- return cm.options.readOnly || cm.doc.cantEdit;
1503
- }
1504
-
1505
- // EVENT HANDLERS
1506
-
1507
- function registerEventHandlers(cm) {
1508
- var d = cm.display;
1509
- on(d.scroller, "mousedown", operation(cm, onMouseDown));
1510
- if (ie)
1511
- on(d.scroller, "dblclick", operation(cm, function(e) {
1512
- if (signalDOMEvent(cm, e)) return;
1513
- var pos = posFromMouse(cm, e);
1514
- if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
1515
- e_preventDefault(e);
1516
- var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
1517
- extendSelection(cm.doc, word.from, word.to);
1518
- }));
1519
- else
1520
- on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
1521
- on(d.lineSpace, "selectstart", function(e) {
1522
- if (!eventInWidget(d, e)) e_preventDefault(e);
1523
- });
1524
- // Gecko browsers fire contextmenu *after* opening the menu, at
1525
- // which point we can't mess with it anymore. Context menu is
1526
- // handled in onMouseDown for Gecko.
1527
- if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
1528
-
1529
- on(d.scroller, "scroll", function() {
1530
- if (d.scroller.clientHeight) {
1531
- setScrollTop(cm, d.scroller.scrollTop);
1532
- setScrollLeft(cm, d.scroller.scrollLeft, true);
1533
- signal(cm, "scroll", cm);
1534
- }
1535
- });
1536
- on(d.scrollbarV, "scroll", function() {
1537
- if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
1538
- });
1539
- on(d.scrollbarH, "scroll", function() {
1540
- if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
1541
- });
1542
-
1543
- on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
1544
- on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
1545
-
1546
- function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
1547
- on(d.scrollbarH, "mousedown", reFocus);
1548
- on(d.scrollbarV, "mousedown", reFocus);
1549
- // Prevent wrapper from ever scrolling
1550
- on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
1551
-
1552
- var resizeTimer;
1553
- function onResize() {
1554
- if (resizeTimer == null) resizeTimer = setTimeout(function() {
1555
- resizeTimer = null;
1556
- // Might be a text scaling operation, clear size caches.
1557
- d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
1558
- clearCaches(cm);
1559
- runInOp(cm, bind(regChange, cm));
1560
- }, 100);
1561
- }
1562
- on(window, "resize", onResize);
1563
- // Above handler holds on to the editor and its data structures.
1564
- // Here we poll to unregister it when the editor is no longer in
1565
- // the document, so that it can be garbage-collected.
1566
- function unregister() {
1567
- for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
1568
- if (p) setTimeout(unregister, 5000);
1569
- else off(window, "resize", onResize);
1570
- }
1571
- setTimeout(unregister, 5000);
1572
-
1573
- on(d.input, "keyup", operation(cm, function(e) {
1574
- if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
1575
- if (e.keyCode == 16) cm.doc.sel.shift = false;
1576
- }));
1577
- on(d.input, "input", bind(fastPoll, cm));
1578
- on(d.input, "keydown", operation(cm, onKeyDown));
1579
- on(d.input, "keypress", operation(cm, onKeyPress));
1580
- on(d.input, "focus", bind(onFocus, cm));
1581
- on(d.input, "blur", bind(onBlur, cm));
1582
-
1583
- function drag_(e) {
1584
- if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
1585
- e_stop(e);
1586
- }
1587
- if (cm.options.dragDrop) {
1588
- on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
1589
- on(d.scroller, "dragenter", drag_);
1590
- on(d.scroller, "dragover", drag_);
1591
- on(d.scroller, "drop", operation(cm, onDrop));
1592
- }
1593
- on(d.scroller, "paste", function(e){
1594
- if (eventInWidget(d, e)) return;
1595
- focusInput(cm);
1596
- fastPoll(cm);
1597
- });
1598
- on(d.input, "paste", function() {
1599
- cm.state.pasteIncoming = true;
1600
- fastPoll(cm);
1601
- });
1602
-
1603
- function prepareCopy() {
1604
- if (d.inaccurateSelection) {
1605
- d.prevInput = "";
1606
- d.inaccurateSelection = false;
1607
- d.input.value = cm.getSelection();
1608
- selectInput(d.input);
1609
- }
1610
- }
1611
- on(d.input, "cut", prepareCopy);
1612
- on(d.input, "copy", prepareCopy);
1613
-
1614
- // Needed to handle Tab key in KHTML
1615
- if (khtml) on(d.sizer, "mouseup", function() {
1616
- if (document.activeElement == d.input) d.input.blur();
1617
- focusInput(cm);
1618
- });
1619
- }
1620
-
1621
- function eventInWidget(display, e) {
1622
- for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
1623
- if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
1624
- }
1625
- }
1626
-
1627
- function posFromMouse(cm, e, liberal) {
1628
- var display = cm.display;
1629
- if (!liberal) {
1630
- var target = e_target(e);
1631
- if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
1632
- target == display.scrollbarV || target == display.scrollbarV.firstChild ||
1633
- target == display.scrollbarFiller || target == display.gutterFiller) return null;
1634
- }
1635
- var x, y, space = getRect(display.lineSpace);
1636
- // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1637
- try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
1638
- return coordsChar(cm, x - space.left, y - space.top);
1639
- }
1640
-
1641
- var lastClick, lastDoubleClick;
1642
- function onMouseDown(e) {
1643
- if (signalDOMEvent(this, e)) return;
1644
- var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
1645
- sel.shift = e.shiftKey;
1646
-
1647
- if (eventInWidget(display, e)) {
1648
- if (!webkit) {
1649
- display.scroller.draggable = false;
1650
- setTimeout(function(){display.scroller.draggable = true;}, 100);
1651
- }
1652
- return;
1653
- }
1654
- if (clickInGutter(cm, e)) return;
1655
- var start = posFromMouse(cm, e);
1656
-
1657
- switch (e_button(e)) {
1658
- case 3:
1659
- if (captureMiddleClick) onContextMenu.call(cm, cm, e);
1660
- return;
1661
- case 2:
1662
- if (start) extendSelection(cm.doc, start);
1663
- setTimeout(bind(focusInput, cm), 20);
1664
- e_preventDefault(e);
1665
- return;
1666
- }
1667
- // For button 1, if it was clicked inside the editor
1668
- // (posFromMouse returning non-null), we have to adjust the
1669
- // selection.
1670
- if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
1671
-
1672
- if (!cm.state.focused) onFocus(cm);
1673
-
1674
- var now = +new Date, type = "single";
1675
- if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
1676
- type = "triple";
1677
- e_preventDefault(e);
1678
- setTimeout(bind(focusInput, cm), 20);
1679
- selectLine(cm, start.line);
1680
- } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
1681
- type = "double";
1682
- lastDoubleClick = {time: now, pos: start};
1683
- e_preventDefault(e);
1684
- var word = findWordAt(getLine(doc, start.line).text, start);
1685
- extendSelection(cm.doc, word.from, word.to);
1686
- } else { lastClick = {time: now, pos: start}; }
1687
-
1688
- var last = start;
1689
- if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
1690
- !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
1691
- var dragEnd = operation(cm, function(e2) {
1692
- if (webkit) display.scroller.draggable = false;
1693
- cm.state.draggingText = false;
1694
- off(document, "mouseup", dragEnd);
1695
- off(display.scroller, "drop", dragEnd);
1696
- if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
1697
- e_preventDefault(e2);
1698
- extendSelection(cm.doc, start);
1699
- focusInput(cm);
1700
- }
1701
- });
1702
- // Let the drag handler handle this.
1703
- if (webkit) display.scroller.draggable = true;
1704
- cm.state.draggingText = dragEnd;
1705
- // IE's approach to draggable
1706
- if (display.scroller.dragDrop) display.scroller.dragDrop();
1707
- on(document, "mouseup", dragEnd);
1708
- on(display.scroller, "drop", dragEnd);
1709
- return;
1710
- }
1711
- e_preventDefault(e);
1712
- if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
1713
-
1714
- var startstart = sel.from, startend = sel.to, lastPos = start;
1715
-
1716
- function doSelect(cur) {
1717
- if (posEq(lastPos, cur)) return;
1718
- lastPos = cur;
1719
-
1720
- if (type == "single") {
1721
- extendSelection(cm.doc, clipPos(doc, start), cur);
1722
- return;
1723
- }
1724
-
1725
- startstart = clipPos(doc, startstart);
1726
- startend = clipPos(doc, startend);
1727
- if (type == "double") {
1728
- var word = findWordAt(getLine(doc, cur.line).text, cur);
1729
- if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
1730
- else extendSelection(cm.doc, startstart, word.to);
1731
- } else if (type == "triple") {
1732
- if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
1733
- else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
1734
- }
1735
- }
1736
-
1737
- var editorSize = getRect(display.wrapper);
1738
- // Used to ensure timeout re-tries don't fire when another extend
1739
- // happened in the meantime (clearTimeout isn't reliable -- at
1740
- // least on Chrome, the timeouts still happen even when cleared,
1741
- // if the clear happens after their scheduled firing time).
1742
- var counter = 0;
1743
-
1744
- function extend(e) {
1745
- var curCount = ++counter;
1746
- var cur = posFromMouse(cm, e, true);
1747
- if (!cur) return;
1748
- if (!posEq(cur, last)) {
1749
- if (!cm.state.focused) onFocus(cm);
1750
- last = cur;
1751
- doSelect(cur);
1752
- var visible = visibleLines(display, doc);
1753
- if (cur.line >= visible.to || cur.line < visible.from)
1754
- setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
1755
- } else {
1756
- var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
1757
- if (outside) setTimeout(operation(cm, function() {
1758
- if (counter != curCount) return;
1759
- display.scroller.scrollTop += outside;
1760
- extend(e);
1761
- }), 50);
1762
- }
1763
- }
1764
-
1765
- function done(e) {
1766
- counter = Infinity;
1767
- e_preventDefault(e);
1768
- focusInput(cm);
1769
- off(document, "mousemove", move);
1770
- off(document, "mouseup", up);
1771
- }
1772
-
1773
- var move = operation(cm, function(e) {
1774
- if (!ie && !e_button(e)) done(e);
1775
- else extend(e);
1776
- });
1777
- var up = operation(cm, done);
1778
- on(document, "mousemove", move);
1779
- on(document, "mouseup", up);
1780
- }
1781
-
1782
- function clickInGutter(cm, e) {
1783
- var display = cm.display;
1784
- try { var mX = e.clientX, mY = e.clientY; }
1785
- catch(e) { return false; }
1786
-
1787
- if (mX >= Math.floor(getRect(display.gutters).right)) return false;
1788
- e_preventDefault(e);
1789
- if (!hasHandler(cm, "gutterClick")) return true;
1790
-
1791
- var lineBox = getRect(display.lineDiv);
1792
- if (mY > lineBox.bottom) return true;
1793
- mY -= lineBox.top - display.viewOffset;
1794
-
1795
- for (var i = 0; i < cm.options.gutters.length; ++i) {
1796
- var g = display.gutters.childNodes[i];
1797
- if (g && getRect(g).right >= mX) {
1798
- var line = lineAtHeight(cm.doc, mY);
1799
- var gutter = cm.options.gutters[i];
1800
- signalLater(cm, "gutterClick", cm, line, gutter, e);
1801
- break;
1802
- }
1803
- }
1804
- return true;
1805
- }
1806
-
1807
- // Kludge to work around strange IE behavior where it'll sometimes
1808
- // re-fire a series of drag-related events right after the drop (#1551)
1809
- var lastDrop = 0;
1810
-
1811
- function onDrop(e) {
1812
- var cm = this;
1813
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
1814
- return;
1815
- e_preventDefault(e);
1816
- if (ie) lastDrop = +new Date;
1817
- var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
1818
- if (!pos || isReadOnly(cm)) return;
1819
- if (files && files.length && window.FileReader && window.File) {
1820
- var n = files.length, text = Array(n), read = 0;
1821
- var loadFile = function(file, i) {
1822
- var reader = new FileReader;
1823
- reader.onload = function() {
1824
- text[i] = reader.result;
1825
- if (++read == n) {
1826
- pos = clipPos(cm.doc, pos);
1827
- makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
1828
- }
1829
- };
1830
- reader.readAsText(file);
1831
- };
1832
- for (var i = 0; i < n; ++i) loadFile(files[i], i);
1833
- } else {
1834
- // Don't do a replace if the drop happened inside of the selected text.
1835
- if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
1836
- cm.state.draggingText(e);
1837
- // Ensure the editor is re-focused
1838
- setTimeout(bind(focusInput, cm), 20);
1839
- return;
1840
- }
1841
- try {
1842
- var text = e.dataTransfer.getData("Text");
1843
- if (text) {
1844
- var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
1845
- setSelection(cm.doc, pos, pos);
1846
- if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
1847
- cm.replaceSelection(text, null, "paste");
1848
- focusInput(cm);
1849
- onFocus(cm);
1850
- }
1851
- }
1852
- catch(e){}
1853
- }
1854
- }
1855
-
1856
- function onDragStart(cm, e) {
1857
- if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
1858
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
1859
-
1860
- var txt = cm.getSelection();
1861
- e.dataTransfer.setData("Text", txt);
1862
-
1863
- // Use dummy image instead of default browsers image.
1864
- // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
1865
- if (e.dataTransfer.setDragImage && !safari) {
1866
- var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
1867
- if (opera) {
1868
- img.width = img.height = 1;
1869
- cm.display.wrapper.appendChild(img);
1870
- // Force a relayout, or Opera won't use our image for some obscure reason
1871
- img._top = img.offsetTop;
1872
- }
1873
- e.dataTransfer.setDragImage(img, 0, 0);
1874
- if (opera) img.parentNode.removeChild(img);
1875
- }
1876
- }
1877
-
1878
- function setScrollTop(cm, val) {
1879
- if (Math.abs(cm.doc.scrollTop - val) < 2) return;
1880
- cm.doc.scrollTop = val;
1881
- if (!gecko) updateDisplay(cm, [], val);
1882
- if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
1883
- if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
1884
- if (gecko) updateDisplay(cm, []);
1885
- startWorker(cm, 100);
1886
- }
1887
- function setScrollLeft(cm, val, isScroller) {
1888
- if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
1889
- val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
1890
- cm.doc.scrollLeft = val;
1891
- alignHorizontally(cm);
1892
- if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
1893
- if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
1894
- }
1895
-
1896
- // Since the delta values reported on mouse wheel events are
1897
- // unstandardized between browsers and even browser versions, and
1898
- // generally horribly unpredictable, this code starts by measuring
1899
- // the scroll effect that the first few mouse wheel events have,
1900
- // and, from that, detects the way it can convert deltas to pixel
1901
- // offsets afterwards.
1902
- //
1903
- // The reason we want to know the amount a wheel event will scroll
1904
- // is that it gives us a chance to update the display before the
1905
- // actual scrolling happens, reducing flickering.
1906
-
1907
- var wheelSamples = 0, wheelPixelsPerUnit = null;
1908
- // Fill in a browser-detected starting value on browsers where we
1909
- // know one. These don't have to be accurate -- the result of them
1910
- // being wrong would just be a slight flicker on the first wheel
1911
- // scroll (if it is large enough).
1912
- if (ie) wheelPixelsPerUnit = -.53;
1913
- else if (gecko) wheelPixelsPerUnit = 15;
1914
- else if (chrome) wheelPixelsPerUnit = -.7;
1915
- else if (safari) wheelPixelsPerUnit = -1/3;
1916
-
1917
- function onScrollWheel(cm, e) {
1918
- var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
1919
- if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
1920
- if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
1921
- else if (dy == null) dy = e.wheelDelta;
1922
-
1923
- var display = cm.display, scroll = display.scroller;
1924
- // Quit if there's nothing to scroll here
1925
- if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
1926
- dy && scroll.scrollHeight > scroll.clientHeight)) return;
1927
-
1928
- // Webkit browsers on OS X abort momentum scrolls when the target
1929
- // of the scroll event is removed from the scrollable element.
1930
- // This hack (see related code in patchDisplay) makes sure the
1931
- // element is kept around.
1932
- if (dy && mac && webkit) {
1933
- for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
1934
- if (cur.lineObj) {
1935
- cm.display.currentWheelTarget = cur;
1936
- break;
1937
- }
1938
- }
1939
- }
1940
-
1941
- // On some browsers, horizontal scrolling will cause redraws to
1942
- // happen before the gutter has been realigned, causing it to
1943
- // wriggle around in a most unseemly way. When we have an
1944
- // estimated pixels/delta value, we just handle horizontal
1945
- // scrolling entirely here. It'll be slightly off from native, but
1946
- // better than glitching out.
1947
- if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
1948
- if (dy)
1949
- setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
1950
- setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
1951
- e_preventDefault(e);
1952
- display.wheelStartX = null; // Abort measurement, if in progress
1953
- return;
1954
- }
1955
-
1956
- if (dy && wheelPixelsPerUnit != null) {
1957
- var pixels = dy * wheelPixelsPerUnit;
1958
- var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
1959
- if (pixels < 0) top = Math.max(0, top + pixels - 50);
1960
- else bot = Math.min(cm.doc.height, bot + pixels + 50);
1961
- updateDisplay(cm, [], {top: top, bottom: bot});
1962
- }
1963
-
1964
- if (wheelSamples < 20) {
1965
- if (display.wheelStartX == null) {
1966
- display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
1967
- display.wheelDX = dx; display.wheelDY = dy;
1968
- setTimeout(function() {
1969
- if (display.wheelStartX == null) return;
1970
- var movedX = scroll.scrollLeft - display.wheelStartX;
1971
- var movedY = scroll.scrollTop - display.wheelStartY;
1972
- var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
1973
- (movedX && display.wheelDX && movedX / display.wheelDX);
1974
- display.wheelStartX = display.wheelStartY = null;
1975
- if (!sample) return;
1976
- wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
1977
- ++wheelSamples;
1978
- }, 200);
1979
- } else {
1980
- display.wheelDX += dx; display.wheelDY += dy;
1981
- }
1982
- }
1983
- }
1984
-
1985
- function doHandleBinding(cm, bound, dropShift) {
1986
- if (typeof bound == "string") {
1987
- bound = commands[bound];
1988
- if (!bound) return false;
1989
- }
1990
- // Ensure previous input has been read, so that the handler sees a
1991
- // consistent view of the document
1992
- if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
1993
- var doc = cm.doc, prevShift = doc.sel.shift, done = false;
1994
- try {
1995
- if (isReadOnly(cm)) cm.state.suppressEdits = true;
1996
- if (dropShift) doc.sel.shift = false;
1997
- done = bound(cm) != Pass;
1998
- } finally {
1999
- doc.sel.shift = prevShift;
2000
- cm.state.suppressEdits = false;
2001
- }
2002
- return done;
2003
- }
2004
-
2005
- function allKeyMaps(cm) {
2006
- var maps = cm.state.keyMaps.slice(0);
2007
- if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
2008
- maps.push(cm.options.keyMap);
2009
- return maps;
2010
- }
2011
-
2012
- var maybeTransition;
2013
- function handleKeyBinding(cm, e) {
2014
- // Handle auto keymap transitions
2015
- var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
2016
- clearTimeout(maybeTransition);
2017
- if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
2018
- if (getKeyMap(cm.options.keyMap) == startMap) {
2019
- cm.options.keyMap = (next.call ? next.call(null, cm) : next);
2020
- keyMapChanged(cm);
2021
- }
2022
- }, 50);
2023
-
2024
- var name = keyName(e, true), handled = false;
2025
- if (!name) return false;
2026
- var keymaps = allKeyMaps(cm);
2027
-
2028
- if (e.shiftKey) {
2029
- // First try to resolve full name (including 'Shift-'). Failing
2030
- // that, see if there is a cursor-motion command (starting with
2031
- // 'go') bound to the keyname without 'Shift-'.
2032
- handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
2033
- || lookupKey(name, keymaps, function(b) {
2034
- if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
2035
- return doHandleBinding(cm, b);
2036
- });
2037
- } else {
2038
- handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
2039
- }
2040
-
2041
- if (handled) {
2042
- e_preventDefault(e);
2043
- restartBlink(cm);
2044
- if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
2045
- signalLater(cm, "keyHandled", cm, name, e);
2046
- }
2047
- return handled;
2048
- }
2049
-
2050
- function handleCharBinding(cm, e, ch) {
2051
- var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
2052
- function(b) { return doHandleBinding(cm, b, true); });
2053
- if (handled) {
2054
- e_preventDefault(e);
2055
- restartBlink(cm);
2056
- signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
2057
- }
2058
- return handled;
2059
- }
2060
-
2061
- var lastStoppedKey = null;
2062
- function onKeyDown(e) {
2063
- var cm = this;
2064
- if (!cm.state.focused) onFocus(cm);
2065
- if (ie && e.keyCode == 27) { e.returnValue = false; }
2066
- if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2067
- var code = e.keyCode;
2068
- // IE does strange things with escape.
2069
- cm.doc.sel.shift = code == 16 || e.shiftKey;
2070
- // First give onKeyEvent option a chance to handle this.
2071
- var handled = handleKeyBinding(cm, e);
2072
- if (opera) {
2073
- lastStoppedKey = handled ? code : null;
2074
- // Opera has no cut event... we try to at least catch the key combo
2075
- if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
2076
- cm.replaceSelection("");
2077
- }
2078
- }
2079
-
2080
- function onKeyPress(e) {
2081
- var cm = this;
2082
- if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
2083
- var keyCode = e.keyCode, charCode = e.charCode;
2084
- if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
2085
- if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
2086
- var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
2087
- if (this.options.electricChars && this.doc.mode.electricChars &&
2088
- this.options.smartIndent && !isReadOnly(this) &&
2089
- this.doc.mode.electricChars.indexOf(ch) > -1)
2090
- setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
2091
- if (handleCharBinding(cm, e, ch)) return;
2092
- if (ie && !ie_lt9) cm.display.inputHasSelection = null;
2093
- fastPoll(cm);
2094
- }
2095
-
2096
- function onFocus(cm) {
2097
- if (cm.options.readOnly == "nocursor") return;
2098
- if (!cm.state.focused) {
2099
- signal(cm, "focus", cm);
2100
- cm.state.focused = true;
2101
- if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
2102
- cm.display.wrapper.className += " CodeMirror-focused";
2103
- resetInput(cm, true);
2104
- }
2105
- slowPoll(cm);
2106
- restartBlink(cm);
2107
- }
2108
- function onBlur(cm) {
2109
- if (cm.state.focused) {
2110
- signal(cm, "blur", cm);
2111
- cm.state.focused = false;
2112
- cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
2113
- }
2114
- clearInterval(cm.display.blinker);
2115
- setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
2116
- }
2117
-
2118
- var detectingSelectAll;
2119
- function onContextMenu(cm, e) {
2120
- if (signalDOMEvent(cm, e, "contextmenu")) return;
2121
- var display = cm.display, sel = cm.doc.sel;
2122
- if (eventInWidget(display, e)) return;
2123
-
2124
- var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
2125
- if (!pos || opera) return; // Opera is difficult.
2126
- if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
2127
- operation(cm, setSelection)(cm.doc, pos, pos);
2128
-
2129
- var oldCSS = display.input.style.cssText;
2130
- display.inputDiv.style.position = "absolute";
2131
- display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
2132
- "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
2133
- "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
2134
- focusInput(cm);
2135
- resetInput(cm, true);
2136
- // Adds "Select all" to context menu in FF
2137
- if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
2138
-
2139
- function prepareSelectAllHack() {
2140
- if (display.input.selectionStart != null) {
2141
- var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
2142
- display.prevInput = " ";
2143
- display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
2144
- }
2145
- }
2146
- function rehide() {
2147
- display.inputDiv.style.position = "relative";
2148
- display.input.style.cssText = oldCSS;
2149
- if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
2150
- slowPoll(cm);
2151
-
2152
- // Try to detect the user choosing select-all
2153
- if (display.input.selectionStart != null) {
2154
- if (!ie || ie_lt9) prepareSelectAllHack();
2155
- clearTimeout(detectingSelectAll);
2156
- var i = 0, poll = function(){
2157
- if (display.prevInput == " " && display.input.selectionStart == 0)
2158
- operation(cm, commands.selectAll)(cm);
2159
- else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
2160
- else resetInput(cm);
2161
- };
2162
- detectingSelectAll = setTimeout(poll, 200);
2163
- }
2164
- }
2165
-
2166
- if (ie && !ie_lt9) prepareSelectAllHack();
2167
- if (captureMiddleClick) {
2168
- e_stop(e);
2169
- var mouseup = function() {
2170
- off(window, "mouseup", mouseup);
2171
- setTimeout(rehide, 20);
2172
- };
2173
- on(window, "mouseup", mouseup);
2174
- } else {
2175
- setTimeout(rehide, 50);
2176
- }
2177
- }
2178
-
2179
- // UPDATING
2180
-
2181
- var changeEnd = CodeMirror.changeEnd = function(change) {
2182
- if (!change.text) return change.to;
2183
- return Pos(change.from.line + change.text.length - 1,
2184
- lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
2185
- };
2186
-
2187
- // Make sure a position will be valid after the given change.
2188
- function clipPostChange(doc, change, pos) {
2189
- if (!posLess(change.from, pos)) return clipPos(doc, pos);
2190
- var diff = (change.text.length - 1) - (change.to.line - change.from.line);
2191
- if (pos.line > change.to.line + diff) {
2192
- var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
2193
- if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
2194
- return clipToLen(pos, getLine(doc, preLine).text.length);
2195
- }
2196
- if (pos.line == change.to.line + diff)
2197
- return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
2198
- getLine(doc, change.to.line).text.length - change.to.ch);
2199
- var inside = pos.line - change.from.line;
2200
- return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
2201
- }
2202
-
2203
- // Hint can be null|"end"|"start"|"around"|{anchor,head}
2204
- function computeSelAfterChange(doc, change, hint) {
2205
- if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
2206
- return {anchor: clipPostChange(doc, change, hint.anchor),
2207
- head: clipPostChange(doc, change, hint.head)};
2208
-
2209
- if (hint == "start") return {anchor: change.from, head: change.from};
2210
-
2211
- var end = changeEnd(change);
2212
- if (hint == "around") return {anchor: change.from, head: end};
2213
- if (hint == "end") return {anchor: end, head: end};
2214
-
2215
- // hint is null, leave the selection alone as much as possible
2216
- var adjustPos = function(pos) {
2217
- if (posLess(pos, change.from)) return pos;
2218
- if (!posLess(change.to, pos)) return end;
2219
-
2220
- var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
2221
- if (pos.line == change.to.line) ch += end.ch - change.to.ch;
2222
- return Pos(line, ch);
2223
- };
2224
- return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
2225
- }
2226
-
2227
- function filterChange(doc, change, update) {
2228
- var obj = {
2229
- canceled: false,
2230
- from: change.from,
2231
- to: change.to,
2232
- text: change.text,
2233
- origin: change.origin,
2234
- cancel: function() { this.canceled = true; }
2235
- };
2236
- if (update) obj.update = function(from, to, text, origin) {
2237
- if (from) this.from = clipPos(doc, from);
2238
- if (to) this.to = clipPos(doc, to);
2239
- if (text) this.text = text;
2240
- if (origin !== undefined) this.origin = origin;
2241
- };
2242
- signal(doc, "beforeChange", doc, obj);
2243
- if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
2244
-
2245
- if (obj.canceled) return null;
2246
- return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
2247
- }
2248
-
2249
- // Replace the range from from to to by the strings in replacement.
2250
- // change is a {from, to, text [, origin]} object
2251
- function makeChange(doc, change, selUpdate, ignoreReadOnly) {
2252
- if (doc.cm) {
2253
- if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
2254
- if (doc.cm.state.suppressEdits) return;
2255
- }
2256
-
2257
- if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
2258
- change = filterChange(doc, change, true);
2259
- if (!change) return;
2260
- }
2261
-
2262
- // Possibly split or suppress the update based on the presence
2263
- // of read-only spans in its range.
2264
- var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
2265
- if (split) {
2266
- for (var i = split.length - 1; i >= 1; --i)
2267
- makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
2268
- if (split.length)
2269
- makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
2270
- } else {
2271
- makeChangeNoReadonly(doc, change, selUpdate);
2272
- }
2273
- }
2274
-
2275
- function makeChangeNoReadonly(doc, change, selUpdate) {
2276
- var selAfter = computeSelAfterChange(doc, change, selUpdate);
2277
- addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
2278
-
2279
- makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
2280
- var rebased = [];
2281
-
2282
- linkedDocs(doc, function(doc, sharedHist) {
2283
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2284
- rebaseHist(doc.history, change);
2285
- rebased.push(doc.history);
2286
- }
2287
- makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
2288
- });
2289
- }
2290
-
2291
- function makeChangeFromHistory(doc, type) {
2292
- if (doc.cm && doc.cm.state.suppressEdits) return;
2293
-
2294
- var hist = doc.history;
2295
- var event = (type == "undo" ? hist.done : hist.undone).pop();
2296
- if (!event) return;
2297
-
2298
- var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
2299
- anchorAfter: event.anchorBefore, headAfter: event.headBefore,
2300
- generation: hist.generation};
2301
- (type == "undo" ? hist.undone : hist.done).push(anti);
2302
- hist.generation = event.generation || ++hist.maxGeneration;
2303
-
2304
- var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
2305
-
2306
- for (var i = event.changes.length - 1; i >= 0; --i) {
2307
- var change = event.changes[i];
2308
- change.origin = type;
2309
- if (filter && !filterChange(doc, change, false)) {
2310
- (type == "undo" ? hist.done : hist.undone).length = 0;
2311
- return;
2312
- }
2313
-
2314
- anti.changes.push(historyChangeFromChange(doc, change));
2315
-
2316
- var after = i ? computeSelAfterChange(doc, change, null)
2317
- : {anchor: event.anchorBefore, head: event.headBefore};
2318
- makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
2319
- var rebased = [];
2320
-
2321
- linkedDocs(doc, function(doc, sharedHist) {
2322
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
2323
- rebaseHist(doc.history, change);
2324
- rebased.push(doc.history);
2325
- }
2326
- makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
2327
- });
2328
- }
2329
- }
2330
-
2331
- function shiftDoc(doc, distance) {
2332
- function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
2333
- doc.first += distance;
2334
- if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
2335
- doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
2336
- doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
2337
- }
2338
-
2339
- function makeChangeSingleDoc(doc, change, selAfter, spans) {
2340
- if (doc.cm && !doc.cm.curOp)
2341
- return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
2342
-
2343
- if (change.to.line < doc.first) {
2344
- shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
2345
- return;
2346
- }
2347
- if (change.from.line > doc.lastLine()) return;
2348
-
2349
- // Clip the change to the size of this doc
2350
- if (change.from.line < doc.first) {
2351
- var shift = change.text.length - 1 - (doc.first - change.from.line);
2352
- shiftDoc(doc, shift);
2353
- change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
2354
- text: [lst(change.text)], origin: change.origin};
2355
- }
2356
- var last = doc.lastLine();
2357
- if (change.to.line > last) {
2358
- change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
2359
- text: [change.text[0]], origin: change.origin};
2360
- }
2361
-
2362
- change.removed = getBetween(doc, change.from, change.to);
2363
-
2364
- if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
2365
- if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
2366
- else updateDoc(doc, change, spans, selAfter);
2367
- }
2368
-
2369
- function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
2370
- var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
2371
-
2372
- var recomputeMaxLength = false, checkWidthStart = from.line;
2373
- if (!cm.options.lineWrapping) {
2374
- checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
2375
- doc.iter(checkWidthStart, to.line + 1, function(line) {
2376
- if (line == display.maxLine) {
2377
- recomputeMaxLength = true;
2378
- return true;
2379
- }
2380
- });
2381
- }
2382
-
2383
- if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
2384
- cm.curOp.cursorActivity = true;
2385
-
2386
- updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
2387
-
2388
- if (!cm.options.lineWrapping) {
2389
- doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
2390
- var len = lineLength(doc, line);
2391
- if (len > display.maxLineLength) {
2392
- display.maxLine = line;
2393
- display.maxLineLength = len;
2394
- display.maxLineChanged = true;
2395
- recomputeMaxLength = false;
2396
- }
2397
- });
2398
- if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
2399
- }
2400
-
2401
- // Adjust frontier, schedule worker
2402
- doc.frontier = Math.min(doc.frontier, from.line);
2403
- startWorker(cm, 400);
2404
-
2405
- var lendiff = change.text.length - (to.line - from.line) - 1;
2406
- // Remember that these lines changed, for updating the display
2407
- regChange(cm, from.line, to.line + 1, lendiff);
2408
-
2409
- if (hasHandler(cm, "change")) {
2410
- var changeObj = {from: from, to: to,
2411
- text: change.text,
2412
- removed: change.removed,
2413
- origin: change.origin};
2414
- if (cm.curOp.textChanged) {
2415
- for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
2416
- cur.next = changeObj;
2417
- } else cm.curOp.textChanged = changeObj;
2418
- }
2419
- }
2420
-
2421
- function replaceRange(doc, code, from, to, origin) {
2422
- if (!to) to = from;
2423
- if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
2424
- if (typeof code == "string") code = splitLines(code);
2425
- makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
2426
- }
2427
-
2428
- // POSITION OBJECT
2429
-
2430
- function Pos(line, ch) {
2431
- if (!(this instanceof Pos)) return new Pos(line, ch);
2432
- this.line = line; this.ch = ch;
2433
- }
2434
- CodeMirror.Pos = Pos;
2435
-
2436
- function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
2437
- function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2438
- function copyPos(x) {return Pos(x.line, x.ch);}
2439
-
2440
- // SELECTION
2441
-
2442
- function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
2443
- function clipPos(doc, pos) {
2444
- if (pos.line < doc.first) return Pos(doc.first, 0);
2445
- var last = doc.first + doc.size - 1;
2446
- if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2447
- return clipToLen(pos, getLine(doc, pos.line).text.length);
2448
- }
2449
- function clipToLen(pos, linelen) {
2450
- var ch = pos.ch;
2451
- if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2452
- else if (ch < 0) return Pos(pos.line, 0);
2453
- else return pos;
2454
- }
2455
- function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2456
-
2457
- // If shift is held, this will move the selection anchor. Otherwise,
2458
- // it'll set the whole selection.
2459
- function extendSelection(doc, pos, other, bias) {
2460
- if (doc.sel.shift || doc.sel.extend) {
2461
- var anchor = doc.sel.anchor;
2462
- if (other) {
2463
- var posBefore = posLess(pos, anchor);
2464
- if (posBefore != posLess(other, anchor)) {
2465
- anchor = pos;
2466
- pos = other;
2467
- } else if (posBefore != posLess(pos, other)) {
2468
- pos = other;
2469
- }
2470
- }
2471
- setSelection(doc, anchor, pos, bias);
2472
- } else {
2473
- setSelection(doc, pos, other || pos, bias);
2474
- }
2475
- if (doc.cm) doc.cm.curOp.userSelChange = true;
2476
- }
2477
-
2478
- function filterSelectionChange(doc, anchor, head) {
2479
- var obj = {anchor: anchor, head: head};
2480
- signal(doc, "beforeSelectionChange", doc, obj);
2481
- if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2482
- obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
2483
- return obj;
2484
- }
2485
-
2486
- // Update the selection. Last two args are only used by
2487
- // updateDoc, since they have to be expressed in the line
2488
- // numbers before the update.
2489
- function setSelection(doc, anchor, head, bias, checkAtomic) {
2490
- if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
2491
- var filtered = filterSelectionChange(doc, anchor, head);
2492
- head = filtered.head;
2493
- anchor = filtered.anchor;
2494
- }
2495
-
2496
- var sel = doc.sel;
2497
- sel.goalColumn = null;
2498
- // Skip over atomic spans.
2499
- if (checkAtomic || !posEq(anchor, sel.anchor))
2500
- anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
2501
- if (checkAtomic || !posEq(head, sel.head))
2502
- head = skipAtomic(doc, head, bias, checkAtomic != "push");
2503
-
2504
- if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
2505
-
2506
- sel.anchor = anchor; sel.head = head;
2507
- var inv = posLess(head, anchor);
2508
- sel.from = inv ? head : anchor;
2509
- sel.to = inv ? anchor : head;
2510
-
2511
- if (doc.cm)
2512
- doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
2513
- doc.cm.curOp.cursorActivity = true;
2514
-
2515
- signalLater(doc, "cursorActivity", doc);
2516
- }
2517
-
2518
- function reCheckSelection(cm) {
2519
- setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
2520
- }
2521
-
2522
- function skipAtomic(doc, pos, bias, mayClear) {
2523
- var flipped = false, curPos = pos;
2524
- var dir = bias || 1;
2525
- doc.cantEdit = false;
2526
- search: for (;;) {
2527
- var line = getLine(doc, curPos.line);
2528
- if (line.markedSpans) {
2529
- for (var i = 0; i < line.markedSpans.length; ++i) {
2530
- var sp = line.markedSpans[i], m = sp.marker;
2531
- if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
2532
- (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
2533
- if (mayClear) {
2534
- signal(m, "beforeCursorEnter");
2535
- if (m.explicitlyCleared) {
2536
- if (!line.markedSpans) break;
2537
- else {--i; continue;}
2538
- }
2539
- }
2540
- if (!m.atomic) continue;
2541
- var newPos = m.find()[dir < 0 ? "from" : "to"];
2542
- if (posEq(newPos, curPos)) {
2543
- newPos.ch += dir;
2544
- if (newPos.ch < 0) {
2545
- if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
2546
- else newPos = null;
2547
- } else if (newPos.ch > line.text.length) {
2548
- if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
2549
- else newPos = null;
2550
- }
2551
- if (!newPos) {
2552
- if (flipped) {
2553
- // Driven in a corner -- no valid cursor position found at all
2554
- // -- try again *with* clearing, if we didn't already
2555
- if (!mayClear) return skipAtomic(doc, pos, bias, true);
2556
- // Otherwise, turn off editing until further notice, and return the start of the doc
2557
- doc.cantEdit = true;
2558
- return Pos(doc.first, 0);
2559
- }
2560
- flipped = true; newPos = pos; dir = -dir;
2561
- }
2562
- }
2563
- curPos = newPos;
2564
- continue search;
2565
- }
2566
- }
2567
- }
2568
- return curPos;
2569
- }
2570
- }
2571
-
2572
- // SCROLLING
2573
-
2574
- function scrollCursorIntoView(cm) {
2575
- var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
2576
- if (!cm.state.focused) return;
2577
- var display = cm.display, box = getRect(display.sizer), doScroll = null;
2578
- if (coords.top + box.top < 0) doScroll = true;
2579
- else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
2580
- if (doScroll != null && !phantom) {
2581
- var hidden = display.cursor.style.display == "none";
2582
- if (hidden) {
2583
- display.cursor.style.display = "";
2584
- display.cursor.style.left = coords.left + "px";
2585
- display.cursor.style.top = (coords.top - display.viewOffset) + "px";
2586
- }
2587
- display.cursor.scrollIntoView(doScroll);
2588
- if (hidden) display.cursor.style.display = "none";
2589
- }
2590
- }
2591
-
2592
- function scrollPosIntoView(cm, pos, margin) {
2593
- if (margin == null) margin = 0;
2594
- for (;;) {
2595
- var changed = false, coords = cursorCoords(cm, pos);
2596
- var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
2597
- var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
2598
- if (scrollPos.scrollTop != null) {
2599
- setScrollTop(cm, scrollPos.scrollTop);
2600
- if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
2601
- }
2602
- if (scrollPos.scrollLeft != null) {
2603
- setScrollLeft(cm, scrollPos.scrollLeft);
2604
- if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
2605
- }
2606
- if (!changed) return coords;
2607
- }
2608
- }
2609
-
2610
- function scrollIntoView(cm, x1, y1, x2, y2) {
2611
- var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
2612
- if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
2613
- if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
2614
- }
2615
-
2616
- function calculateScrollPos(cm, x1, y1, x2, y2) {
2617
- var display = cm.display, snapMargin = textHeight(cm.display);
2618
- if (y1 < 0) y1 = 0;
2619
- var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
2620
- var docBottom = cm.doc.height + paddingVert(display);
2621
- var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
2622
- if (y1 < screentop) {
2623
- result.scrollTop = atTop ? 0 : y1;
2624
- } else if (y2 > screentop + screen) {
2625
- var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
2626
- if (newTop != screentop) result.scrollTop = newTop;
2627
- }
2628
-
2629
- var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
2630
- x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
2631
- var gutterw = display.gutters.offsetWidth;
2632
- var atLeft = x1 < gutterw + 10;
2633
- if (x1 < screenleft + gutterw || atLeft) {
2634
- if (atLeft) x1 = 0;
2635
- result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
2636
- } else if (x2 > screenw + screenleft - 3) {
2637
- result.scrollLeft = x2 + 10 - screenw;
2638
- }
2639
- return result;
2640
- }
2641
-
2642
- function updateScrollPos(cm, left, top) {
2643
- cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
2644
- scrollTop: top == null ? cm.doc.scrollTop : top};
2645
- }
2646
-
2647
- function addToScrollPos(cm, left, top) {
2648
- var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
2649
- var scroll = cm.display.scroller;
2650
- pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
2651
- pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
2652
- }
2653
-
2654
- // API UTILITIES
2655
-
2656
- function indentLine(cm, n, how, aggressive) {
2657
- var doc = cm.doc;
2658
- if (how == null) how = "add";
2659
- if (how == "smart") {
2660
- if (!cm.doc.mode.indent) how = "prev";
2661
- else var state = getStateBefore(cm, n);
2662
- }
2663
-
2664
- var tabSize = cm.options.tabSize;
2665
- var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
2666
- var curSpaceString = line.text.match(/^\s*/)[0], indentation;
2667
- if (how == "smart") {
2668
- indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
2669
- if (indentation == Pass) {
2670
- if (!aggressive) return;
2671
- how = "prev";
2672
- }
2673
- }
2674
- if (how == "prev") {
2675
- if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
2676
- else indentation = 0;
2677
- } else if (how == "add") {
2678
- indentation = curSpace + cm.options.indentUnit;
2679
- } else if (how == "subtract") {
2680
- indentation = curSpace - cm.options.indentUnit;
2681
- } else if (typeof how == "number") {
2682
- indentation = curSpace + how;
2683
- }
2684
- indentation = Math.max(0, indentation);
2685
-
2686
- var indentString = "", pos = 0;
2687
- if (cm.options.indentWithTabs)
2688
- for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
2689
- if (pos < indentation) indentString += spaceStr(indentation - pos);
2690
-
2691
- if (indentString != curSpaceString)
2692
- replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
2693
- line.stateAfter = null;
2694
- }
2695
-
2696
- function changeLine(cm, handle, op) {
2697
- var no = handle, line = handle, doc = cm.doc;
2698
- if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
2699
- else no = lineNo(handle);
2700
- if (no == null) return null;
2701
- if (op(line, no)) regChange(cm, no, no + 1);
2702
- else return null;
2703
- return line;
2704
- }
2705
-
2706
- function findPosH(doc, pos, dir, unit, visually) {
2707
- var line = pos.line, ch = pos.ch, origDir = dir;
2708
- var lineObj = getLine(doc, line);
2709
- var possible = true;
2710
- function findNextLine() {
2711
- var l = line + dir;
2712
- if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
2713
- line = l;
2714
- return lineObj = getLine(doc, l);
2715
- }
2716
- function moveOnce(boundToLine) {
2717
- var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
2718
- if (next == null) {
2719
- if (!boundToLine && findNextLine()) {
2720
- if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
2721
- else ch = dir < 0 ? lineObj.text.length : 0;
2722
- } else return (possible = false);
2723
- } else ch = next;
2724
- return true;
2725
- }
2726
-
2727
- if (unit == "char") moveOnce();
2728
- else if (unit == "column") moveOnce(true);
2729
- else if (unit == "word" || unit == "group") {
2730
- var sawType = null, group = unit == "group";
2731
- for (var first = true;; first = false) {
2732
- if (dir < 0 && !moveOnce(!first)) break;
2733
- var cur = lineObj.text.charAt(ch) || "\n";
2734
- var type = isWordChar(cur) ? "w"
2735
- : !group ? null
2736
- : /\s/.test(cur) ? null
2737
- : "p";
2738
- if (sawType && sawType != type) {
2739
- if (dir < 0) {dir = 1; moveOnce();}
2740
- break;
2741
- }
2742
- if (type) sawType = type;
2743
- if (dir > 0 && !moveOnce(!first)) break;
2744
- }
2745
- }
2746
- var result = skipAtomic(doc, Pos(line, ch), origDir, true);
2747
- if (!possible) result.hitSide = true;
2748
- return result;
2749
- }
2750
-
2751
- function findPosV(cm, pos, dir, unit) {
2752
- var doc = cm.doc, x = pos.left, y;
2753
- if (unit == "page") {
2754
- var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
2755
- y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
2756
- } else if (unit == "line") {
2757
- y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
2758
- }
2759
- for (;;) {
2760
- var target = coordsChar(cm, x, y);
2761
- if (!target.outside) break;
2762
- if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
2763
- y += dir * 5;
2764
- }
2765
- return target;
2766
- }
2767
-
2768
- function findWordAt(line, pos) {
2769
- var start = pos.ch, end = pos.ch;
2770
- if (line) {
2771
- if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
2772
- var startChar = line.charAt(start);
2773
- var check = isWordChar(startChar) ? isWordChar
2774
- : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
2775
- : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
2776
- while (start > 0 && check(line.charAt(start - 1))) --start;
2777
- while (end < line.length && check(line.charAt(end))) ++end;
2778
- }
2779
- return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
2780
- }
2781
-
2782
- function selectLine(cm, line) {
2783
- extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
2784
- }
2785
-
2786
- // PROTOTYPE
2787
-
2788
- // The publicly visible API. Note that operation(null, f) means
2789
- // 'wrap f in an operation, performed on its `this` parameter'
2790
-
2791
- CodeMirror.prototype = {
2792
- constructor: CodeMirror,
2793
- focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
2794
-
2795
- setOption: function(option, value) {
2796
- var options = this.options, old = options[option];
2797
- if (options[option] == value && option != "mode") return;
2798
- options[option] = value;
2799
- if (optionHandlers.hasOwnProperty(option))
2800
- operation(this, optionHandlers[option])(this, value, old);
2801
- },
2802
-
2803
- getOption: function(option) {return this.options[option];},
2804
- getDoc: function() {return this.doc;},
2805
-
2806
- addKeyMap: function(map, bottom) {
2807
- this.state.keyMaps[bottom ? "push" : "unshift"](map);
2808
- },
2809
- removeKeyMap: function(map) {
2810
- var maps = this.state.keyMaps;
2811
- for (var i = 0; i < maps.length; ++i)
2812
- if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
2813
- maps.splice(i, 1);
2814
- return true;
2815
- }
2816
- },
2817
-
2818
- addOverlay: operation(null, function(spec, options) {
2819
- var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
2820
- if (mode.startState) throw new Error("Overlays may not be stateful.");
2821
- this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
2822
- this.state.modeGen++;
2823
- regChange(this);
2824
- }),
2825
- removeOverlay: operation(null, function(spec) {
2826
- var overlays = this.state.overlays;
2827
- for (var i = 0; i < overlays.length; ++i) {
2828
- var cur = overlays[i].modeSpec;
2829
- if (cur == spec || typeof spec == "string" && cur.name == spec) {
2830
- overlays.splice(i, 1);
2831
- this.state.modeGen++;
2832
- regChange(this);
2833
- return;
2834
- }
2835
- }
2836
- }),
2837
-
2838
- indentLine: operation(null, function(n, dir, aggressive) {
2839
- if (typeof dir != "string" && typeof dir != "number") {
2840
- if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
2841
- else dir = dir ? "add" : "subtract";
2842
- }
2843
- if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
2844
- }),
2845
- indentSelection: operation(null, function(how) {
2846
- var sel = this.doc.sel;
2847
- if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
2848
- var e = sel.to.line - (sel.to.ch ? 0 : 1);
2849
- for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
2850
- }),
2851
-
2852
- // Fetch the parser token for a given character. Useful for hacks
2853
- // that want to inspect the mode state (say, for completion).
2854
- getTokenAt: function(pos, precise) {
2855
- var doc = this.doc;
2856
- pos = clipPos(doc, pos);
2857
- var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
2858
- var line = getLine(doc, pos.line);
2859
- var stream = new StringStream(line.text, this.options.tabSize);
2860
- while (stream.pos < pos.ch && !stream.eol()) {
2861
- stream.start = stream.pos;
2862
- var style = mode.token(stream, state);
2863
- }
2864
- return {start: stream.start,
2865
- end: stream.pos,
2866
- string: stream.current(),
2867
- className: style || null, // Deprecated, use 'type' instead
2868
- type: style || null,
2869
- state: state};
2870
- },
2871
-
2872
- getTokenTypeAt: function(pos) {
2873
- pos = clipPos(this.doc, pos);
2874
- var styles = getLineStyles(this, getLine(this.doc, pos.line));
2875
- var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
2876
- if (ch == 0) return styles[2];
2877
- for (;;) {
2878
- var mid = (before + after) >> 1;
2879
- if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
2880
- else if (styles[mid * 2 + 1] < ch) before = mid + 1;
2881
- else return styles[mid * 2 + 2];
2882
- }
2883
- },
2884
-
2885
- getModeAt: function(pos) {
2886
- var mode = this.doc.mode;
2887
- if (!mode.innerMode) return mode;
2888
- return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
2889
- },
2890
-
2891
- getHelper: function(pos, type) {
2892
- if (!helpers.hasOwnProperty(type)) return;
2893
- var help = helpers[type], mode = this.getModeAt(pos);
2894
- return mode[type] && help[mode[type]] ||
2895
- mode.helperType && help[mode.helperType] ||
2896
- help[mode.name];
2897
- },
2898
-
2899
- getStateAfter: function(line, precise) {
2900
- var doc = this.doc;
2901
- line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
2902
- return getStateBefore(this, line + 1, precise);
2903
- },
2904
-
2905
- cursorCoords: function(start, mode) {
2906
- var pos, sel = this.doc.sel;
2907
- if (start == null) pos = sel.head;
2908
- else if (typeof start == "object") pos = clipPos(this.doc, start);
2909
- else pos = start ? sel.from : sel.to;
2910
- return cursorCoords(this, pos, mode || "page");
2911
- },
2912
-
2913
- charCoords: function(pos, mode) {
2914
- return charCoords(this, clipPos(this.doc, pos), mode || "page");
2915
- },
2916
-
2917
- coordsChar: function(coords, mode) {
2918
- coords = fromCoordSystem(this, coords, mode || "page");
2919
- return coordsChar(this, coords.left, coords.top);
2920
- },
2921
-
2922
- lineAtHeight: function(height, mode) {
2923
- height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
2924
- return lineAtHeight(this.doc, height + this.display.viewOffset);
2925
- },
2926
- heightAtLine: function(line, mode) {
2927
- var end = false, last = this.doc.first + this.doc.size - 1;
2928
- if (line < this.doc.first) line = this.doc.first;
2929
- else if (line > last) { line = last; end = true; }
2930
- var lineObj = getLine(this.doc, line);
2931
- return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
2932
- (end ? lineObj.height : 0);
2933
- },
2934
-
2935
- defaultTextHeight: function() { return textHeight(this.display); },
2936
- defaultCharWidth: function() { return charWidth(this.display); },
2937
-
2938
- setGutterMarker: operation(null, function(line, gutterID, value) {
2939
- return changeLine(this, line, function(line) {
2940
- var markers = line.gutterMarkers || (line.gutterMarkers = {});
2941
- markers[gutterID] = value;
2942
- if (!value && isEmpty(markers)) line.gutterMarkers = null;
2943
- return true;
2944
- });
2945
- }),
2946
-
2947
- clearGutter: operation(null, function(gutterID) {
2948
- var cm = this, doc = cm.doc, i = doc.first;
2949
- doc.iter(function(line) {
2950
- if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
2951
- line.gutterMarkers[gutterID] = null;
2952
- regChange(cm, i, i + 1);
2953
- if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
2954
- }
2955
- ++i;
2956
- });
2957
- }),
2958
-
2959
- addLineClass: operation(null, function(handle, where, cls) {
2960
- return changeLine(this, handle, function(line) {
2961
- var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2962
- if (!line[prop]) line[prop] = cls;
2963
- else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
2964
- else line[prop] += " " + cls;
2965
- return true;
2966
- });
2967
- }),
2968
-
2969
- removeLineClass: operation(null, function(handle, where, cls) {
2970
- return changeLine(this, handle, function(line) {
2971
- var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
2972
- var cur = line[prop];
2973
- if (!cur) return false;
2974
- else if (cls == null) line[prop] = null;
2975
- else {
2976
- var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
2977
- if (!found) return false;
2978
- var end = found.index + found[0].length;
2979
- line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
2980
- }
2981
- return true;
2982
- });
2983
- }),
2984
-
2985
- addLineWidget: operation(null, function(handle, node, options) {
2986
- return addLineWidget(this, handle, node, options);
2987
- }),
2988
-
2989
- removeLineWidget: function(widget) { widget.clear(); },
2990
-
2991
- lineInfo: function(line) {
2992
- if (typeof line == "number") {
2993
- if (!isLine(this.doc, line)) return null;
2994
- var n = line;
2995
- line = getLine(this.doc, line);
2996
- if (!line) return null;
2997
- } else {
2998
- var n = lineNo(line);
2999
- if (n == null) return null;
3000
- }
3001
- return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
3002
- textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
3003
- widgets: line.widgets};
3004
- },
3005
-
3006
- getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
3007
-
3008
- addWidget: function(pos, node, scroll, vert, horiz) {
3009
- var display = this.display;
3010
- pos = cursorCoords(this, clipPos(this.doc, pos));
3011
- var top = pos.bottom, left = pos.left;
3012
- node.style.position = "absolute";
3013
- display.sizer.appendChild(node);
3014
- if (vert == "over") {
3015
- top = pos.top;
3016
- } else if (vert == "above" || vert == "near") {
3017
- var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
3018
- hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
3019
- // Default to positioning above (if specified and possible); otherwise default to positioning below
3020
- if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
3021
- top = pos.top - node.offsetHeight;
3022
- else if (pos.bottom + node.offsetHeight <= vspace)
3023
- top = pos.bottom;
3024
- if (left + node.offsetWidth > hspace)
3025
- left = hspace - node.offsetWidth;
3026
- }
3027
- node.style.top = top + "px";
3028
- node.style.left = node.style.right = "";
3029
- if (horiz == "right") {
3030
- left = display.sizer.clientWidth - node.offsetWidth;
3031
- node.style.right = "0px";
3032
- } else {
3033
- if (horiz == "left") left = 0;
3034
- else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
3035
- node.style.left = left + "px";
3036
- }
3037
- if (scroll)
3038
- scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
3039
- },
3040
-
3041
- triggerOnKeyDown: operation(null, onKeyDown),
3042
-
3043
- execCommand: function(cmd) {return commands[cmd](this);},
3044
-
3045
- findPosH: function(from, amount, unit, visually) {
3046
- var dir = 1;
3047
- if (amount < 0) { dir = -1; amount = -amount; }
3048
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3049
- cur = findPosH(this.doc, cur, dir, unit, visually);
3050
- if (cur.hitSide) break;
3051
- }
3052
- return cur;
3053
- },
3054
-
3055
- moveH: operation(null, function(dir, unit) {
3056
- var sel = this.doc.sel, pos;
3057
- if (sel.shift || sel.extend || posEq(sel.from, sel.to))
3058
- pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
3059
- else
3060
- pos = dir < 0 ? sel.from : sel.to;
3061
- extendSelection(this.doc, pos, pos, dir);
3062
- }),
3063
-
3064
- deleteH: operation(null, function(dir, unit) {
3065
- var sel = this.doc.sel;
3066
- if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
3067
- else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
3068
- this.curOp.userSelChange = true;
3069
- }),
3070
-
3071
- findPosV: function(from, amount, unit, goalColumn) {
3072
- var dir = 1, x = goalColumn;
3073
- if (amount < 0) { dir = -1; amount = -amount; }
3074
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
3075
- var coords = cursorCoords(this, cur, "div");
3076
- if (x == null) x = coords.left;
3077
- else coords.left = x;
3078
- cur = findPosV(this, coords, dir, unit);
3079
- if (cur.hitSide) break;
3080
- }
3081
- return cur;
3082
- },
3083
-
3084
- moveV: operation(null, function(dir, unit) {
3085
- var sel = this.doc.sel;
3086
- var pos = cursorCoords(this, sel.head, "div");
3087
- if (sel.goalColumn != null) pos.left = sel.goalColumn;
3088
- var target = findPosV(this, pos, dir, unit);
3089
-
3090
- if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
3091
- extendSelection(this.doc, target, target, dir);
3092
- sel.goalColumn = pos.left;
3093
- }),
3094
-
3095
- toggleOverwrite: function(value) {
3096
- if (value != null && value == this.state.overwrite) return;
3097
- if (this.state.overwrite = !this.state.overwrite)
3098
- this.display.cursor.className += " CodeMirror-overwrite";
3099
- else
3100
- this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
3101
- },
3102
- hasFocus: function() { return this.state.focused; },
3103
-
3104
- scrollTo: operation(null, function(x, y) {
3105
- updateScrollPos(this, x, y);
3106
- }),
3107
- getScrollInfo: function() {
3108
- var scroller = this.display.scroller, co = scrollerCutOff;
3109
- return {left: scroller.scrollLeft, top: scroller.scrollTop,
3110
- height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
3111
- clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
3112
- },
3113
-
3114
- scrollIntoView: operation(null, function(pos, margin) {
3115
- if (typeof pos == "number") pos = Pos(pos, 0);
3116
- if (!margin) margin = 0;
3117
- var coords = pos;
3118
-
3119
- if (!pos || pos.line != null) {
3120
- this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
3121
- this.curOp.scrollToPosMargin = margin;
3122
- coords = cursorCoords(this, this.curOp.scrollToPos);
3123
- }
3124
- var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
3125
- updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
3126
- }),
3127
-
3128
- setSize: operation(null, function(width, height) {
3129
- function interpret(val) {
3130
- return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
3131
- }
3132
- if (width != null) this.display.wrapper.style.width = interpret(width);
3133
- if (height != null) this.display.wrapper.style.height = interpret(height);
3134
- if (this.options.lineWrapping)
3135
- this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
3136
- this.curOp.forceUpdate = true;
3137
- }),
3138
-
3139
- operation: function(f){return runInOp(this, f);},
3140
-
3141
- refresh: operation(null, function() {
3142
- clearCaches(this);
3143
- updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
3144
- regChange(this);
3145
- }),
3146
-
3147
- swapDoc: operation(null, function(doc) {
3148
- var old = this.doc;
3149
- old.cm = null;
3150
- attachDoc(this, doc);
3151
- clearCaches(this);
3152
- resetInput(this, true);
3153
- updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
3154
- return old;
3155
- }),
3156
-
3157
- getInputField: function(){return this.display.input;},
3158
- getWrapperElement: function(){return this.display.wrapper;},
3159
- getScrollerElement: function(){return this.display.scroller;},
3160
- getGutterElement: function(){return this.display.gutters;}
3161
- };
3162
- eventMixin(CodeMirror);
3163
-
3164
- // OPTION DEFAULTS
3165
-
3166
- var optionHandlers = CodeMirror.optionHandlers = {};
3167
-
3168
- // The default configuration options.
3169
- var defaults = CodeMirror.defaults = {};
3170
-
3171
- function option(name, deflt, handle, notOnInit) {
3172
- CodeMirror.defaults[name] = deflt;
3173
- if (handle) optionHandlers[name] =
3174
- notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
3175
- }
3176
-
3177
- var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
3178
-
3179
- // These two are, on init, called from the constructor because they
3180
- // have to be initialized before the editor can start at all.
3181
- option("value", "", function(cm, val) {
3182
- cm.setValue(val);
3183
- }, true);
3184
- option("mode", null, function(cm, val) {
3185
- cm.doc.modeOption = val;
3186
- loadMode(cm);
3187
- }, true);
3188
-
3189
- option("indentUnit", 2, loadMode, true);
3190
- option("indentWithTabs", false);
3191
- option("smartIndent", true);
3192
- option("tabSize", 4, function(cm) {
3193
- loadMode(cm);
3194
- clearCaches(cm);
3195
- regChange(cm);
3196
- }, true);
3197
- option("electricChars", true);
3198
- option("rtlMoveVisually", !windows);
3199
-
3200
- option("theme", "default", function(cm) {
3201
- themeChanged(cm);
3202
- guttersChanged(cm);
3203
- }, true);
3204
- option("keyMap", "default", keyMapChanged);
3205
- option("extraKeys", null);
3206
-
3207
- option("onKeyEvent", null);
3208
- option("onDragEvent", null);
3209
-
3210
- option("lineWrapping", false, wrappingChanged, true);
3211
- option("gutters", [], function(cm) {
3212
- setGuttersForLineNumbers(cm.options);
3213
- guttersChanged(cm);
3214
- }, true);
3215
- option("fixedGutter", true, function(cm, val) {
3216
- cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
3217
- cm.refresh();
3218
- }, true);
3219
- option("coverGutterNextToScrollbar", false, updateScrollbars, true);
3220
- option("lineNumbers", false, function(cm) {
3221
- setGuttersForLineNumbers(cm.options);
3222
- guttersChanged(cm);
3223
- }, true);
3224
- option("firstLineNumber", 1, guttersChanged, true);
3225
- option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
3226
- option("showCursorWhenSelecting", false, updateSelection, true);
3227
-
3228
- option("readOnly", false, function(cm, val) {
3229
- if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
3230
- else if (!val) resetInput(cm, true);
3231
- });
3232
- option("dragDrop", true);
3233
-
3234
- option("cursorBlinkRate", 530);
3235
- option("cursorScrollMargin", 0);
3236
- option("cursorHeight", 1);
3237
- option("workTime", 100);
3238
- option("workDelay", 100);
3239
- option("flattenSpans", true);
3240
- option("pollInterval", 100);
3241
- option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
3242
- option("historyEventDelay", 500);
3243
- option("viewportMargin", 10, function(cm){cm.refresh();}, true);
3244
- option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
3245
- option("moveInputWithCursor", true, function(cm, val) {
3246
- if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
3247
- });
3248
-
3249
- option("tabindex", null, function(cm, val) {
3250
- cm.display.input.tabIndex = val || "";
3251
- });
3252
- option("autofocus", null);
3253
-
3254
- // MODE DEFINITION AND QUERYING
3255
-
3256
- // Known modes, by name and by MIME
3257
- var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
3258
-
3259
- CodeMirror.defineMode = function(name, mode) {
3260
- if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
3261
- if (arguments.length > 2) {
3262
- mode.dependencies = [];
3263
- for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
3264
- }
3265
- modes[name] = mode;
3266
- };
3267
-
3268
- CodeMirror.defineMIME = function(mime, spec) {
3269
- mimeModes[mime] = spec;
3270
- };
3271
-
3272
- CodeMirror.resolveMode = function(spec) {
3273
- if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
3274
- spec = mimeModes[spec];
3275
- } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
3276
- var found = mimeModes[spec.name];
3277
- spec = createObj(found, spec);
3278
- spec.name = found.name;
3279
- } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
3280
- return CodeMirror.resolveMode("application/xml");
3281
- }
3282
- if (typeof spec == "string") return {name: spec};
3283
- else return spec || {name: "null"};
3284
- };
3285
-
3286
- CodeMirror.getMode = function(options, spec) {
3287
- var spec = CodeMirror.resolveMode(spec);
3288
- var mfactory = modes[spec.name];
3289
- if (!mfactory) return CodeMirror.getMode(options, "text/plain");
3290
- var modeObj = mfactory(options, spec);
3291
- if (modeExtensions.hasOwnProperty(spec.name)) {
3292
- var exts = modeExtensions[spec.name];
3293
- for (var prop in exts) {
3294
- if (!exts.hasOwnProperty(prop)) continue;
3295
- if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
3296
- modeObj[prop] = exts[prop];
3297
- }
3298
- }
3299
- modeObj.name = spec.name;
3300
-
3301
- return modeObj;
3302
- };
3303
-
3304
- CodeMirror.defineMode("null", function() {
3305
- return {token: function(stream) {stream.skipToEnd();}};
3306
- });
3307
- CodeMirror.defineMIME("text/plain", "null");
3308
-
3309
- var modeExtensions = CodeMirror.modeExtensions = {};
3310
- CodeMirror.extendMode = function(mode, properties) {
3311
- var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
3312
- copyObj(properties, exts);
3313
- };
3314
-
3315
- // EXTENSIONS
3316
-
3317
- CodeMirror.defineExtension = function(name, func) {
3318
- CodeMirror.prototype[name] = func;
3319
- };
3320
- CodeMirror.defineDocExtension = function(name, func) {
3321
- Doc.prototype[name] = func;
3322
- };
3323
- CodeMirror.defineOption = option;
3324
-
3325
- var initHooks = [];
3326
- CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
3327
-
3328
- var helpers = CodeMirror.helpers = {};
3329
- CodeMirror.registerHelper = function(type, name, value) {
3330
- if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
3331
- helpers[type][name] = value;
3332
- };
3333
-
3334
- // UTILITIES
3335
-
3336
- CodeMirror.isWordChar = isWordChar;
3337
-
3338
- // MODE STATE HANDLING
3339
-
3340
- // Utility functions for working with state. Exported because modes
3341
- // sometimes need to do this.
3342
- function copyState(mode, state) {
3343
- if (state === true) return state;
3344
- if (mode.copyState) return mode.copyState(state);
3345
- var nstate = {};
3346
- for (var n in state) {
3347
- var val = state[n];
3348
- if (val instanceof Array) val = val.concat([]);
3349
- nstate[n] = val;
3350
- }
3351
- return nstate;
3352
- }
3353
- CodeMirror.copyState = copyState;
3354
-
3355
- function startState(mode, a1, a2) {
3356
- return mode.startState ? mode.startState(a1, a2) : true;
3357
- }
3358
- CodeMirror.startState = startState;
3359
-
3360
- CodeMirror.innerMode = function(mode, state) {
3361
- while (mode.innerMode) {
3362
- var info = mode.innerMode(state);
3363
- if (!info || info.mode == mode) break;
3364
- state = info.state;
3365
- mode = info.mode;
3366
- }
3367
- return info || {mode: mode, state: state};
3368
- };
3369
-
3370
- // STANDARD COMMANDS
3371
-
3372
- var commands = CodeMirror.commands = {
3373
- selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
3374
- killLine: function(cm) {
3375
- var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
3376
- if (!sel && cm.getLine(from.line).length == from.ch)
3377
- cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
3378
- else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
3379
- },
3380
- deleteLine: function(cm) {
3381
- var l = cm.getCursor().line;
3382
- cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
3383
- },
3384
- delLineLeft: function(cm) {
3385
- var cur = cm.getCursor();
3386
- cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
3387
- },
3388
- undo: function(cm) {cm.undo();},
3389
- redo: function(cm) {cm.redo();},
3390
- goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
3391
- goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
3392
- goLineStart: function(cm) {
3393
- cm.extendSelection(lineStart(cm, cm.getCursor().line));
3394
- },
3395
- goLineStartSmart: function(cm) {
3396
- var cur = cm.getCursor(), start = lineStart(cm, cur.line);
3397
- var line = cm.getLineHandle(start.line);
3398
- var order = getOrder(line);
3399
- if (!order || order[0].level == 0) {
3400
- var firstNonWS = Math.max(0, line.text.search(/\S/));
3401
- var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
3402
- cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
3403
- } else cm.extendSelection(start);
3404
- },
3405
- goLineEnd: function(cm) {
3406
- cm.extendSelection(lineEnd(cm, cm.getCursor().line));
3407
- },
3408
- goLineRight: function(cm) {
3409
- var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3410
- cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
3411
- },
3412
- goLineLeft: function(cm) {
3413
- var top = cm.charCoords(cm.getCursor(), "div").top + 5;
3414
- cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
3415
- },
3416
- goLineUp: function(cm) {cm.moveV(-1, "line");},
3417
- goLineDown: function(cm) {cm.moveV(1, "line");},
3418
- goPageUp: function(cm) {cm.moveV(-1, "page");},
3419
- goPageDown: function(cm) {cm.moveV(1, "page");},
3420
- goCharLeft: function(cm) {cm.moveH(-1, "char");},
3421
- goCharRight: function(cm) {cm.moveH(1, "char");},
3422
- goColumnLeft: function(cm) {cm.moveH(-1, "column");},
3423
- goColumnRight: function(cm) {cm.moveH(1, "column");},
3424
- goWordLeft: function(cm) {cm.moveH(-1, "word");},
3425
- goGroupRight: function(cm) {cm.moveH(1, "group");},
3426
- goGroupLeft: function(cm) {cm.moveH(-1, "group");},
3427
- goWordRight: function(cm) {cm.moveH(1, "word");},
3428
- delCharBefore: function(cm) {cm.deleteH(-1, "char");},
3429
- delCharAfter: function(cm) {cm.deleteH(1, "char");},
3430
- delWordBefore: function(cm) {cm.deleteH(-1, "word");},
3431
- delWordAfter: function(cm) {cm.deleteH(1, "word");},
3432
- delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
3433
- delGroupAfter: function(cm) {cm.deleteH(1, "group");},
3434
- indentAuto: function(cm) {cm.indentSelection("smart");},
3435
- indentMore: function(cm) {cm.indentSelection("add");},
3436
- indentLess: function(cm) {cm.indentSelection("subtract");},
3437
- insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
3438
- defaultTab: function(cm) {
3439
- if (cm.somethingSelected()) cm.indentSelection("add");
3440
- else cm.replaceSelection("\t", "end", "+input");
3441
- },
3442
- transposeChars: function(cm) {
3443
- var cur = cm.getCursor(), line = cm.getLine(cur.line);
3444
- if (cur.ch > 0 && cur.ch < line.length - 1)
3445
- cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
3446
- Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
3447
- },
3448
- newlineAndIndent: function(cm) {
3449
- operation(cm, function() {
3450
- cm.replaceSelection("\n", "end", "+input");
3451
- cm.indentLine(cm.getCursor().line, null, true);
3452
- })();
3453
- },
3454
- toggleOverwrite: function(cm) {cm.toggleOverwrite();}
3455
- };
3456
-
3457
- // STANDARD KEYMAPS
3458
-
3459
- var keyMap = CodeMirror.keyMap = {};
3460
- keyMap.basic = {
3461
- "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
3462
- "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
3463
- "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
3464
- "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
3465
- };
3466
- // Note that the save and find-related commands aren't defined by
3467
- // default. Unknown commands are simply ignored.
3468
- keyMap.pcDefault = {
3469
- "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
3470
- "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
3471
- "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
3472
- "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
3473
- "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
3474
- "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
3475
- fallthrough: "basic"
3476
- };
3477
- keyMap.macDefault = {
3478
- "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
3479
- "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
3480
- "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
3481
- "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
3482
- "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
3483
- "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
3484
- fallthrough: ["basic", "emacsy"]
3485
- };
3486
- keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
3487
- keyMap.emacsy = {
3488
- "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
3489
- "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
3490
- "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
3491
- "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
3492
- };
3493
-
3494
- // KEYMAP DISPATCH
3495
-
3496
- function getKeyMap(val) {
3497
- if (typeof val == "string") return keyMap[val];
3498
- else return val;
3499
- }
3500
-
3501
- function lookupKey(name, maps, handle) {
3502
- function lookup(map) {
3503
- map = getKeyMap(map);
3504
- var found = map[name];
3505
- if (found === false) return "stop";
3506
- if (found != null && handle(found)) return true;
3507
- if (map.nofallthrough) return "stop";
3508
-
3509
- var fallthrough = map.fallthrough;
3510
- if (fallthrough == null) return false;
3511
- if (Object.prototype.toString.call(fallthrough) != "[object Array]")
3512
- return lookup(fallthrough);
3513
- for (var i = 0, e = fallthrough.length; i < e; ++i) {
3514
- var done = lookup(fallthrough[i]);
3515
- if (done) return done;
3516
- }
3517
- return false;
3518
- }
3519
-
3520
- for (var i = 0; i < maps.length; ++i) {
3521
- var done = lookup(maps[i]);
3522
- if (done) return done != "stop";
3523
- }
3524
- }
3525
- function isModifierKey(event) {
3526
- var name = keyNames[event.keyCode];
3527
- return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
3528
- }
3529
- function keyName(event, noShift) {
3530
- if (opera && event.keyCode == 34 && event["char"]) return false;
3531
- var name = keyNames[event.keyCode];
3532
- if (name == null || event.altGraphKey) return false;
3533
- if (event.altKey) name = "Alt-" + name;
3534
- if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
3535
- if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
3536
- if (!noShift && event.shiftKey) name = "Shift-" + name;
3537
- return name;
3538
- }
3539
- CodeMirror.lookupKey = lookupKey;
3540
- CodeMirror.isModifierKey = isModifierKey;
3541
- CodeMirror.keyName = keyName;
3542
-
3543
- // FROMTEXTAREA
3544
-
3545
- CodeMirror.fromTextArea = function(textarea, options) {
3546
- if (!options) options = {};
3547
- options.value = textarea.value;
3548
- if (!options.tabindex && textarea.tabindex)
3549
- options.tabindex = textarea.tabindex;
3550
- if (!options.placeholder && textarea.placeholder)
3551
- options.placeholder = textarea.placeholder;
3552
- // Set autofocus to true if this textarea is focused, or if it has
3553
- // autofocus and no other element is focused.
3554
- if (options.autofocus == null) {
3555
- var hasFocus = document.body;
3556
- // doc.activeElement occasionally throws on IE
3557
- try { hasFocus = document.activeElement; } catch(e) {}
3558
- options.autofocus = hasFocus == textarea ||
3559
- textarea.getAttribute("autofocus") != null && hasFocus == document.body;
3560
- }
3561
-
3562
- function save() {textarea.value = cm.getValue();}
3563
- if (textarea.form) {
3564
- on(textarea.form, "submit", save);
3565
- // Deplorable hack to make the submit method do the right thing.
3566
- if (!options.leaveSubmitMethodAlone) {
3567
- var form = textarea.form, realSubmit = form.submit;
3568
- try {
3569
- var wrappedSubmit = form.submit = function() {
3570
- save();
3571
- form.submit = realSubmit;
3572
- form.submit();
3573
- form.submit = wrappedSubmit;
3574
- };
3575
- } catch(e) {}
3576
- }
3577
- }
3578
-
3579
- textarea.style.display = "none";
3580
- var cm = CodeMirror(function(node) {
3581
- textarea.parentNode.insertBefore(node, textarea.nextSibling);
3582
- }, options);
3583
- cm.save = save;
3584
- cm.getTextArea = function() { return textarea; };
3585
- cm.toTextArea = function() {
3586
- save();
3587
- textarea.parentNode.removeChild(cm.getWrapperElement());
3588
- textarea.style.display = "";
3589
- if (textarea.form) {
3590
- off(textarea.form, "submit", save);
3591
- if (typeof textarea.form.submit == "function")
3592
- textarea.form.submit = realSubmit;
3593
- }
3594
- };
3595
- return cm;
3596
- };
3597
-
3598
- // STRING STREAM
3599
-
3600
- // Fed to the mode parsers, provides helper functions to make
3601
- // parsers more succinct.
3602
-
3603
- // The character stream used by a mode's parser.
3604
- function StringStream(string, tabSize) {
3605
- this.pos = this.start = 0;
3606
- this.string = string;
3607
- this.tabSize = tabSize || 8;
3608
- this.lastColumnPos = this.lastColumnValue = 0;
3609
- }
3610
-
3611
- StringStream.prototype = {
3612
- eol: function() {return this.pos >= this.string.length;},
3613
- sol: function() {return this.pos == 0;},
3614
- peek: function() {return this.string.charAt(this.pos) || undefined;},
3615
- next: function() {
3616
- if (this.pos < this.string.length)
3617
- return this.string.charAt(this.pos++);
3618
- },
3619
- eat: function(match) {
3620
- var ch = this.string.charAt(this.pos);
3621
- if (typeof match == "string") var ok = ch == match;
3622
- else var ok = ch && (match.test ? match.test(ch) : match(ch));
3623
- if (ok) {++this.pos; return ch;}
3624
- },
3625
- eatWhile: function(match) {
3626
- var start = this.pos;
3627
- while (this.eat(match)){}
3628
- return this.pos > start;
3629
- },
3630
- eatSpace: function() {
3631
- var start = this.pos;
3632
- while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
3633
- return this.pos > start;
3634
- },
3635
- skipToEnd: function() {this.pos = this.string.length;},
3636
- skipTo: function(ch) {
3637
- var found = this.string.indexOf(ch, this.pos);
3638
- if (found > -1) {this.pos = found; return true;}
3639
- },
3640
- backUp: function(n) {this.pos -= n;},
3641
- column: function() {
3642
- if (this.lastColumnPos < this.start) {
3643
- this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
3644
- this.lastColumnPos = this.start;
3645
- }
3646
- return this.lastColumnValue;
3647
- },
3648
- indentation: function() {return countColumn(this.string, null, this.tabSize);},
3649
- match: function(pattern, consume, caseInsensitive) {
3650
- if (typeof pattern == "string") {
3651
- var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
3652
- var substr = this.string.substr(this.pos, pattern.length);
3653
- if (cased(substr) == cased(pattern)) {
3654
- if (consume !== false) this.pos += pattern.length;
3655
- return true;
3656
- }
3657
- } else {
3658
- var match = this.string.slice(this.pos).match(pattern);
3659
- if (match && match.index > 0) return null;
3660
- if (match && consume !== false) this.pos += match[0].length;
3661
- return match;
3662
- }
3663
- },
3664
- current: function(){return this.string.slice(this.start, this.pos);}
3665
- };
3666
- CodeMirror.StringStream = StringStream;
3667
-
3668
- // TEXTMARKERS
3669
-
3670
- function TextMarker(doc, type) {
3671
- this.lines = [];
3672
- this.type = type;
3673
- this.doc = doc;
3674
- }
3675
- CodeMirror.TextMarker = TextMarker;
3676
- eventMixin(TextMarker);
3677
-
3678
- TextMarker.prototype.clear = function() {
3679
- if (this.explicitlyCleared) return;
3680
- var cm = this.doc.cm, withOp = cm && !cm.curOp;
3681
- if (withOp) startOperation(cm);
3682
- if (hasHandler(this, "clear")) {
3683
- var found = this.find();
3684
- if (found) signalLater(this, "clear", found.from, found.to);
3685
- }
3686
- var min = null, max = null;
3687
- for (var i = 0; i < this.lines.length; ++i) {
3688
- var line = this.lines[i];
3689
- var span = getMarkedSpanFor(line.markedSpans, this);
3690
- if (span.to != null) max = lineNo(line);
3691
- line.markedSpans = removeMarkedSpan(line.markedSpans, span);
3692
- if (span.from != null)
3693
- min = lineNo(line);
3694
- else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
3695
- updateLineHeight(line, textHeight(cm.display));
3696
- }
3697
- if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
3698
- var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
3699
- if (len > cm.display.maxLineLength) {
3700
- cm.display.maxLine = visual;
3701
- cm.display.maxLineLength = len;
3702
- cm.display.maxLineChanged = true;
3703
- }
3704
- }
3705
-
3706
- if (min != null && cm) regChange(cm, min, max + 1);
3707
- this.lines.length = 0;
3708
- this.explicitlyCleared = true;
3709
- if (this.atomic && this.doc.cantEdit) {
3710
- this.doc.cantEdit = false;
3711
- if (cm) reCheckSelection(cm);
3712
- }
3713
- if (withOp) endOperation(cm);
3714
- };
3715
-
3716
- TextMarker.prototype.find = function() {
3717
- var from, to;
3718
- for (var i = 0; i < this.lines.length; ++i) {
3719
- var line = this.lines[i];
3720
- var span = getMarkedSpanFor(line.markedSpans, this);
3721
- if (span.from != null || span.to != null) {
3722
- var found = lineNo(line);
3723
- if (span.from != null) from = Pos(found, span.from);
3724
- if (span.to != null) to = Pos(found, span.to);
3725
- }
3726
- }
3727
- if (this.type == "bookmark") return from;
3728
- return from && {from: from, to: to};
3729
- };
3730
-
3731
- TextMarker.prototype.changed = function() {
3732
- var pos = this.find(), cm = this.doc.cm;
3733
- if (!pos || !cm) return;
3734
- var line = getLine(this.doc, pos.from.line);
3735
- clearCachedMeasurement(cm, line);
3736
- if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
3737
- for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
3738
- if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
3739
- break;
3740
- }
3741
- runInOp(cm, function() {
3742
- cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
3743
- });
3744
- }
3745
- };
3746
-
3747
- TextMarker.prototype.attachLine = function(line) {
3748
- if (!this.lines.length && this.doc.cm) {
3749
- var op = this.doc.cm.curOp;
3750
- if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
3751
- (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
3752
- }
3753
- this.lines.push(line);
3754
- };
3755
- TextMarker.prototype.detachLine = function(line) {
3756
- this.lines.splice(indexOf(this.lines, line), 1);
3757
- if (!this.lines.length && this.doc.cm) {
3758
- var op = this.doc.cm.curOp;
3759
- (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
3760
- }
3761
- };
3762
-
3763
- function markText(doc, from, to, options, type) {
3764
- if (options && options.shared) return markTextShared(doc, from, to, options, type);
3765
- if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
3766
-
3767
- var marker = new TextMarker(doc, type);
3768
- if (type == "range" && !posLess(from, to)) return marker;
3769
- if (options) copyObj(options, marker);
3770
- if (marker.replacedWith) {
3771
- marker.collapsed = true;
3772
- marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
3773
- if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
3774
- }
3775
- if (marker.collapsed) sawCollapsedSpans = true;
3776
-
3777
- if (marker.addToHistory)
3778
- addToHistory(doc, {from: from, to: to, origin: "markText"},
3779
- {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);
3780
-
3781
- var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
3782
- doc.iter(curLine, to.line + 1, function(line) {
3783
- if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
3784
- updateMaxLine = true;
3785
- var span = {from: null, to: null, marker: marker};
3786
- size += line.text.length;
3787
- if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
3788
- if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
3789
- if (marker.collapsed) {
3790
- if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
3791
- if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
3792
- else updateLineHeight(line, 0);
3793
- }
3794
- addMarkedSpan(line, span);
3795
- ++curLine;
3796
- });
3797
- if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
3798
- if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
3799
- });
3800
-
3801
- if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
3802
-
3803
- if (marker.readOnly) {
3804
- sawReadOnlySpans = true;
3805
- if (doc.history.done.length || doc.history.undone.length)
3806
- doc.clearHistory();
3807
- }
3808
- if (marker.collapsed) {
3809
- if (collapsedAtStart != collapsedAtEnd)
3810
- throw new Error("Inserting collapsed marker overlapping an existing one");
3811
- marker.size = size;
3812
- marker.atomic = true;
3813
- }
3814
- if (cm) {
3815
- if (updateMaxLine) cm.curOp.updateMaxLine = true;
3816
- if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
3817
- regChange(cm, from.line, to.line + 1);
3818
- if (marker.atomic) reCheckSelection(cm);
3819
- }
3820
- return marker;
3821
- }
3822
-
3823
- // SHARED TEXTMARKERS
3824
-
3825
- function SharedTextMarker(markers, primary) {
3826
- this.markers = markers;
3827
- this.primary = primary;
3828
- for (var i = 0, me = this; i < markers.length; ++i) {
3829
- markers[i].parent = this;
3830
- on(markers[i], "clear", function(){me.clear();});
3831
- }
3832
- }
3833
- CodeMirror.SharedTextMarker = SharedTextMarker;
3834
- eventMixin(SharedTextMarker);
3835
-
3836
- SharedTextMarker.prototype.clear = function() {
3837
- if (this.explicitlyCleared) return;
3838
- this.explicitlyCleared = true;
3839
- for (var i = 0; i < this.markers.length; ++i)
3840
- this.markers[i].clear();
3841
- signalLater(this, "clear");
3842
- };
3843
- SharedTextMarker.prototype.find = function() {
3844
- return this.primary.find();
3845
- };
3846
-
3847
- function markTextShared(doc, from, to, options, type) {
3848
- options = copyObj(options);
3849
- options.shared = false;
3850
- var markers = [markText(doc, from, to, options, type)], primary = markers[0];
3851
- var widget = options.replacedWith;
3852
- linkedDocs(doc, function(doc) {
3853
- if (widget) options.replacedWith = widget.cloneNode(true);
3854
- markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
3855
- for (var i = 0; i < doc.linked.length; ++i)
3856
- if (doc.linked[i].isParent) return;
3857
- primary = lst(markers);
3858
- });
3859
- return new SharedTextMarker(markers, primary);
3860
- }
3861
-
3862
- // TEXTMARKER SPANS
3863
-
3864
- function getMarkedSpanFor(spans, marker) {
3865
- if (spans) for (var i = 0; i < spans.length; ++i) {
3866
- var span = spans[i];
3867
- if (span.marker == marker) return span;
3868
- }
3869
- }
3870
- function removeMarkedSpan(spans, span) {
3871
- for (var r, i = 0; i < spans.length; ++i)
3872
- if (spans[i] != span) (r || (r = [])).push(spans[i]);
3873
- return r;
3874
- }
3875
- function addMarkedSpan(line, span) {
3876
- line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
3877
- span.marker.attachLine(line);
3878
- }
3879
-
3880
- function markedSpansBefore(old, startCh, isInsert) {
3881
- if (old) for (var i = 0, nw; i < old.length; ++i) {
3882
- var span = old[i], marker = span.marker;
3883
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3884
- if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
3885
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
3886
- (nw || (nw = [])).push({from: span.from,
3887
- to: endsAfter ? null : span.to,
3888
- marker: marker});
3889
- }
3890
- }
3891
- return nw;
3892
- }
3893
-
3894
- function markedSpansAfter(old, endCh, isInsert) {
3895
- if (old) for (var i = 0, nw; i < old.length; ++i) {
3896
- var span = old[i], marker = span.marker;
3897
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
3898
- if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
3899
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
3900
- (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
3901
- to: span.to == null ? null : span.to - endCh,
3902
- marker: marker});
3903
- }
3904
- }
3905
- return nw;
3906
- }
3907
-
3908
- function stretchSpansOverChange(doc, change) {
3909
- var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
3910
- var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
3911
- if (!oldFirst && !oldLast) return null;
3912
-
3913
- var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
3914
- // Get the spans that 'stick out' on both sides
3915
- var first = markedSpansBefore(oldFirst, startCh, isInsert);
3916
- var last = markedSpansAfter(oldLast, endCh, isInsert);
3917
-
3918
- // Next, merge those two ends
3919
- var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
3920
- if (first) {
3921
- // Fix up .to properties of first
3922
- for (var i = 0; i < first.length; ++i) {
3923
- var span = first[i];
3924
- if (span.to == null) {
3925
- var found = getMarkedSpanFor(last, span.marker);
3926
- if (!found) span.to = startCh;
3927
- else if (sameLine) span.to = found.to == null ? null : found.to + offset;
3928
- }
3929
- }
3930
- }
3931
- if (last) {
3932
- // Fix up .from in last (or move them into first in case of sameLine)
3933
- for (var i = 0; i < last.length; ++i) {
3934
- var span = last[i];
3935
- if (span.to != null) span.to += offset;
3936
- if (span.from == null) {
3937
- var found = getMarkedSpanFor(first, span.marker);
3938
- if (!found) {
3939
- span.from = offset;
3940
- if (sameLine) (first || (first = [])).push(span);
3941
- }
3942
- } else {
3943
- span.from += offset;
3944
- if (sameLine) (first || (first = [])).push(span);
3945
- }
3946
- }
3947
- }
3948
- if (sameLine && first) {
3949
- // Make sure we didn't create any zero-length spans
3950
- for (var i = 0; i < first.length; ++i)
3951
- if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
3952
- first.splice(i--, 1);
3953
- if (!first.length) first = null;
3954
- }
3955
-
3956
- var newMarkers = [first];
3957
- if (!sameLine) {
3958
- // Fill gap with whole-line-spans
3959
- var gap = change.text.length - 2, gapMarkers;
3960
- if (gap > 0 && first)
3961
- for (var i = 0; i < first.length; ++i)
3962
- if (first[i].to == null)
3963
- (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
3964
- for (var i = 0; i < gap; ++i)
3965
- newMarkers.push(gapMarkers);
3966
- newMarkers.push(last);
3967
- }
3968
- return newMarkers;
3969
- }
3970
-
3971
- function mergeOldSpans(doc, change) {
3972
- var old = getOldSpans(doc, change);
3973
- var stretched = stretchSpansOverChange(doc, change);
3974
- if (!old) return stretched;
3975
- if (!stretched) return old;
3976
-
3977
- for (var i = 0; i < old.length; ++i) {
3978
- var oldCur = old[i], stretchCur = stretched[i];
3979
- if (oldCur && stretchCur) {
3980
- spans: for (var j = 0; j < stretchCur.length; ++j) {
3981
- var span = stretchCur[j];
3982
- for (var k = 0; k < oldCur.length; ++k)
3983
- if (oldCur[k].marker == span.marker) continue spans;
3984
- oldCur.push(span);
3985
- }
3986
- } else if (stretchCur) {
3987
- old[i] = stretchCur;
3988
- }
3989
- }
3990
- return old;
3991
- }
3992
-
3993
- function removeReadOnlyRanges(doc, from, to) {
3994
- var markers = null;
3995
- doc.iter(from.line, to.line + 1, function(line) {
3996
- if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
3997
- var mark = line.markedSpans[i].marker;
3998
- if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
3999
- (markers || (markers = [])).push(mark);
4000
- }
4001
- });
4002
- if (!markers) return null;
4003
- var parts = [{from: from, to: to}];
4004
- for (var i = 0; i < markers.length; ++i) {
4005
- var mk = markers[i], m = mk.find();
4006
- for (var j = 0; j < parts.length; ++j) {
4007
- var p = parts[j];
4008
- if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
4009
- var newParts = [j, 1];
4010
- if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
4011
- newParts.push({from: p.from, to: m.from});
4012
- if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
4013
- newParts.push({from: m.to, to: p.to});
4014
- parts.splice.apply(parts, newParts);
4015
- j += newParts.length - 1;
4016
- }
4017
- }
4018
- return parts;
4019
- }
4020
-
4021
- function collapsedSpanAt(line, ch) {
4022
- var sps = sawCollapsedSpans && line.markedSpans, found;
4023
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4024
- sp = sps[i];
4025
- if (!sp.marker.collapsed) continue;
4026
- if ((sp.from == null || sp.from < ch) &&
4027
- (sp.to == null || sp.to > ch) &&
4028
- (!found || found.width < sp.marker.width))
4029
- found = sp.marker;
4030
- }
4031
- return found;
4032
- }
4033
- function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
4034
- function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
4035
-
4036
- function visualLine(doc, line) {
4037
- var merged;
4038
- while (merged = collapsedSpanAtStart(line))
4039
- line = getLine(doc, merged.find().from.line);
4040
- return line;
4041
- }
4042
-
4043
- function lineIsHidden(doc, line) {
4044
- var sps = sawCollapsedSpans && line.markedSpans;
4045
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
4046
- sp = sps[i];
4047
- if (!sp.marker.collapsed) continue;
4048
- if (sp.from == null) return true;
4049
- if (sp.marker.replacedWith) continue;
4050
- if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
4051
- return true;
4052
- }
4053
- }
4054
- function lineIsHiddenInner(doc, line, span) {
4055
- if (span.to == null) {
4056
- var end = span.marker.find().to, endLine = getLine(doc, end.line);
4057
- return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
4058
- }
4059
- if (span.marker.inclusiveRight && span.to == line.text.length)
4060
- return true;
4061
- for (var sp, i = 0; i < line.markedSpans.length; ++i) {
4062
- sp = line.markedSpans[i];
4063
- if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
4064
- (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
4065
- lineIsHiddenInner(doc, line, sp)) return true;
4066
- }
4067
- }
4068
-
4069
- function detachMarkedSpans(line) {
4070
- var spans = line.markedSpans;
4071
- if (!spans) return;
4072
- for (var i = 0; i < spans.length; ++i)
4073
- spans[i].marker.detachLine(line);
4074
- line.markedSpans = null;
4075
- }
4076
-
4077
- function attachMarkedSpans(line, spans) {
4078
- if (!spans) return;
4079
- for (var i = 0; i < spans.length; ++i)
4080
- spans[i].marker.attachLine(line);
4081
- line.markedSpans = spans;
4082
- }
4083
-
4084
- // LINE WIDGETS
4085
-
4086
- var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
4087
- if (options) for (var opt in options) if (options.hasOwnProperty(opt))
4088
- this[opt] = options[opt];
4089
- this.cm = cm;
4090
- this.node = node;
4091
- };
4092
- eventMixin(LineWidget);
4093
- function widgetOperation(f) {
4094
- return function() {
4095
- var withOp = !this.cm.curOp;
4096
- if (withOp) startOperation(this.cm);
4097
- try {var result = f.apply(this, arguments);}
4098
- finally {if (withOp) endOperation(this.cm);}
4099
- return result;
4100
- };
4101
- }
4102
- LineWidget.prototype.clear = widgetOperation(function() {
4103
- var ws = this.line.widgets, no = lineNo(this.line);
4104
- if (no == null || !ws) return;
4105
- for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
4106
- if (!ws.length) this.line.widgets = null;
4107
- var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
4108
- updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
4109
- if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
4110
- regChange(this.cm, no, no + 1);
4111
- });
4112
- LineWidget.prototype.changed = widgetOperation(function() {
4113
- var oldH = this.height;
4114
- this.height = null;
4115
- var diff = widgetHeight(this) - oldH;
4116
- if (!diff) return;
4117
- updateLineHeight(this.line, this.line.height + diff);
4118
- var no = lineNo(this.line);
4119
- regChange(this.cm, no, no + 1);
4120
- });
4121
-
4122
- function widgetHeight(widget) {
4123
- if (widget.height != null) return widget.height;
4124
- if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
4125
- removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
4126
- return widget.height = widget.node.offsetHeight;
4127
- }
4128
-
4129
- function addLineWidget(cm, handle, node, options) {
4130
- var widget = new LineWidget(cm, node, options);
4131
- if (widget.noHScroll) cm.display.alignWidgets = true;
4132
- changeLine(cm, handle, function(line) {
4133
- var widgets = line.widgets || (line.widgets = []);
4134
- if (widget.insertAt == null) widgets.push(widget);
4135
- else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
4136
- widget.line = line;
4137
- if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
4138
- var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
4139
- updateLineHeight(line, line.height + widgetHeight(widget));
4140
- if (aboveVisible) addToScrollPos(cm, 0, widget.height);
4141
- }
4142
- return true;
4143
- });
4144
- return widget;
4145
- }
4146
-
4147
- // LINE DATA STRUCTURE
4148
-
4149
- // Line objects. These hold state related to a line, including
4150
- // highlighting info (the styles array).
4151
- var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
4152
- this.text = text;
4153
- attachMarkedSpans(this, markedSpans);
4154
- this.height = estimateHeight ? estimateHeight(this) : 1;
4155
- };
4156
- eventMixin(Line);
4157
-
4158
- function updateLine(line, text, markedSpans, estimateHeight) {
4159
- line.text = text;
4160
- if (line.stateAfter) line.stateAfter = null;
4161
- if (line.styles) line.styles = null;
4162
- if (line.order != null) line.order = null;
4163
- detachMarkedSpans(line);
4164
- attachMarkedSpans(line, markedSpans);
4165
- var estHeight = estimateHeight ? estimateHeight(line) : 1;
4166
- if (estHeight != line.height) updateLineHeight(line, estHeight);
4167
- }
4168
-
4169
- function cleanUpLine(line) {
4170
- line.parent = null;
4171
- detachMarkedSpans(line);
4172
- }
4173
-
4174
- // Run the given mode's parser over a line, update the styles
4175
- // array, which contains alternating fragments of text and CSS
4176
- // classes.
4177
- function runMode(cm, text, mode, state, f) {
4178
- var flattenSpans = mode.flattenSpans;
4179
- if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
4180
- var curStart = 0, curStyle = null;
4181
- var stream = new StringStream(text, cm.options.tabSize), style;
4182
- if (text == "" && mode.blankLine) mode.blankLine(state);
4183
- while (!stream.eol()) {
4184
- if (stream.pos > cm.options.maxHighlightLength) {
4185
- flattenSpans = false;
4186
- // Webkit seems to refuse to render text nodes longer than 57444 characters
4187
- stream.pos = Math.min(text.length, stream.start + 50000);
4188
- style = null;
4189
- } else {
4190
- style = mode.token(stream, state);
4191
- }
4192
- if (!flattenSpans || curStyle != style) {
4193
- if (curStart < stream.start) f(stream.start, curStyle);
4194
- curStart = stream.start; curStyle = style;
4195
- }
4196
- stream.start = stream.pos;
4197
- }
4198
- if (curStart < stream.pos) f(stream.pos, curStyle);
4199
- }
4200
-
4201
- function highlightLine(cm, line, state) {
4202
- // A styles array always starts with a number identifying the
4203
- // mode/overlays that it is based on (for easy invalidation).
4204
- var st = [cm.state.modeGen];
4205
- // Compute the base array of styles
4206
- runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
4207
-
4208
- // Run overlays, adjust style array.
4209
- for (var o = 0; o < cm.state.overlays.length; ++o) {
4210
- var overlay = cm.state.overlays[o], i = 1, at = 0;
4211
- runMode(cm, line.text, overlay.mode, true, function(end, style) {
4212
- var start = i;
4213
- // Ensure there's a token end at the current position, and that i points at it
4214
- while (at < end) {
4215
- var i_end = st[i];
4216
- if (i_end > end)
4217
- st.splice(i, 1, end, st[i+1], i_end);
4218
- i += 2;
4219
- at = Math.min(end, i_end);
4220
- }
4221
- if (!style) return;
4222
- if (overlay.opaque) {
4223
- st.splice(start, i - start, end, style);
4224
- i = start + 2;
4225
- } else {
4226
- for (; start < i; start += 2) {
4227
- var cur = st[start+1];
4228
- st[start+1] = cur ? cur + " " + style : style;
4229
- }
4230
- }
4231
- });
4232
- }
4233
-
4234
- return st;
4235
- }
4236
-
4237
- function getLineStyles(cm, line) {
4238
- if (!line.styles || line.styles[0] != cm.state.modeGen)
4239
- line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
4240
- return line.styles;
4241
- }
4242
-
4243
- // Lightweight form of highlight -- proceed over this line and
4244
- // update state, but don't save a style array.
4245
- function processLine(cm, line, state) {
4246
- var mode = cm.doc.mode;
4247
- var stream = new StringStream(line.text, cm.options.tabSize);
4248
- if (line.text == "" && mode.blankLine) mode.blankLine(state);
4249
- while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
4250
- mode.token(stream, state);
4251
- stream.start = stream.pos;
4252
- }
4253
- }
4254
-
4255
- var styleToClassCache = {};
4256
- function styleToClass(style) {
4257
- if (!style) return null;
4258
- return styleToClassCache[style] ||
4259
- (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
4260
- }
4261
-
4262
- function lineContent(cm, realLine, measure, copyWidgets) {
4263
- var merged, line = realLine, empty = true;
4264
- while (merged = collapsedSpanAtStart(line))
4265
- line = getLine(cm.doc, merged.find().from.line);
4266
-
4267
- var builder = {pre: elt("pre"), col: 0, pos: 0,
4268
- measure: null, measuredSomething: false, cm: cm,
4269
- copyWidgets: copyWidgets};
4270
- if (line.textClass) builder.pre.className = line.textClass;
4271
-
4272
- do {
4273
- if (line.text) empty = false;
4274
- builder.measure = line == realLine && measure;
4275
- builder.pos = 0;
4276
- builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
4277
- if ((ie || webkit) && cm.getOption("lineWrapping"))
4278
- builder.addToken = buildTokenSplitSpaces(builder.addToken);
4279
- var next = insertLineContent(line, builder, getLineStyles(cm, line));
4280
- if (measure && line == realLine && !builder.measuredSomething) {
4281
- measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
4282
- builder.measuredSomething = true;
4283
- }
4284
- if (next) line = getLine(cm.doc, next.to.line);
4285
- } while (next);
4286
-
4287
- if (measure && !builder.measuredSomething && !measure[0])
4288
- measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
4289
- if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
4290
- builder.pre.appendChild(document.createTextNode("\u00a0"));
4291
-
4292
- var order;
4293
- // Work around problem with the reported dimensions of single-char
4294
- // direction spans on IE (issue #1129). See also the comment in
4295
- // cursorCoords.
4296
- if (measure && ie && (order = getOrder(line))) {
4297
- var l = order.length - 1;
4298
- if (order[l].from == order[l].to) --l;
4299
- var last = order[l], prev = order[l - 1];
4300
- if (last.from + 1 == last.to && prev && last.level < prev.level) {
4301
- var span = measure[builder.pos - 1];
4302
- if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
4303
- span.nextSibling);
4304
- }
4305
- }
4306
-
4307
- signal(cm, "renderLine", cm, realLine, builder.pre);
4308
- return builder.pre;
4309
- }
4310
-
4311
- var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
4312
- function buildToken(builder, text, style, startStyle, endStyle, title) {
4313
- if (!text) return;
4314
- if (!tokenSpecialChars.test(text)) {
4315
- builder.col += text.length;
4316
- var content = document.createTextNode(text);
4317
- } else {
4318
- var content = document.createDocumentFragment(), pos = 0;
4319
- while (true) {
4320
- tokenSpecialChars.lastIndex = pos;
4321
- var m = tokenSpecialChars.exec(text);
4322
- var skipped = m ? m.index - pos : text.length - pos;
4323
- if (skipped) {
4324
- content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
4325
- builder.col += skipped;
4326
- }
4327
- if (!m) break;
4328
- pos += skipped + 1;
4329
- if (m[0] == "\t") {
4330
- var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
4331
- content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
4332
- builder.col += tabWidth;
4333
- } else {
4334
- var token = elt("span", "\u2022", "cm-invalidchar");
4335
- token.title = "\\u" + m[0].charCodeAt(0).toString(16);
4336
- content.appendChild(token);
4337
- builder.col += 1;
4338
- }
4339
- }
4340
- }
4341
- if (style || startStyle || endStyle || builder.measure) {
4342
- var fullStyle = style || "";
4343
- if (startStyle) fullStyle += startStyle;
4344
- if (endStyle) fullStyle += endStyle;
4345
- var token = elt("span", [content], fullStyle);
4346
- if (title) token.title = title;
4347
- return builder.pre.appendChild(token);
4348
- }
4349
- builder.pre.appendChild(content);
4350
- }
4351
-
4352
- function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
4353
- var wrapping = builder.cm.options.lineWrapping;
4354
- for (var i = 0; i < text.length; ++i) {
4355
- var ch = text.charAt(i), start = i == 0;
4356
- if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
4357
- ch = text.slice(i, i + 2);
4358
- ++i;
4359
- } else if (i && wrapping && spanAffectsWrapping(text, i)) {
4360
- builder.pre.appendChild(elt("wbr"));
4361
- }
4362
- var old = builder.measure[builder.pos];
4363
- var span = builder.measure[builder.pos] =
4364
- buildToken(builder, ch, style,
4365
- start && startStyle, i == text.length - 1 && endStyle);
4366
- if (old) span.leftSide = old.leftSide || old;
4367
- // In IE single-space nodes wrap differently than spaces
4368
- // embedded in larger text nodes, except when set to
4369
- // white-space: normal (issue #1268).
4370
- if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
4371
- i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
4372
- span.style.whiteSpace = "normal";
4373
- builder.pos += ch.length;
4374
- }
4375
- if (text.length) builder.measuredSomething = true;
4376
- }
4377
-
4378
- function buildTokenSplitSpaces(inner) {
4379
- function split(old) {
4380
- var out = " ";
4381
- for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
4382
- out += " ";
4383
- return out;
4384
- }
4385
- return function(builder, text, style, startStyle, endStyle, title) {
4386
- return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
4387
- };
4388
- }
4389
-
4390
- function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
4391
- var widget = !ignoreWidget && marker.replacedWith;
4392
- if (widget) {
4393
- if (builder.copyWidgets) widget = widget.cloneNode(true);
4394
- builder.pre.appendChild(widget);
4395
- if (builder.measure) {
4396
- if (size) {
4397
- builder.measure[builder.pos] = widget;
4398
- } else {
4399
- var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
4400
- if (marker.type != "bookmark" || marker.insertLeft)
4401
- builder.pre.insertBefore(elt, widget);
4402
- else
4403
- builder.pre.appendChild(elt);
4404
- }
4405
- builder.measuredSomething = true;
4406
- }
4407
- }
4408
- builder.pos += size;
4409
- }
4410
-
4411
- // Outputs a number of spans to make up a line, taking highlighting
4412
- // and marked text into account.
4413
- function insertLineContent(line, builder, styles) {
4414
- var spans = line.markedSpans, allText = line.text, at = 0;
4415
- if (!spans) {
4416
- for (var i = 1; i < styles.length; i+=2)
4417
- builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
4418
- return;
4419
- }
4420
-
4421
- var len = allText.length, pos = 0, i = 1, text = "", style;
4422
- var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
4423
- for (;;) {
4424
- if (nextChange == pos) { // Update current marker set
4425
- spanStyle = spanEndStyle = spanStartStyle = title = "";
4426
- collapsed = null; nextChange = Infinity;
4427
- var foundBookmark = null;
4428
- for (var j = 0; j < spans.length; ++j) {
4429
- var sp = spans[j], m = sp.marker;
4430
- if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
4431
- if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
4432
- if (m.className) spanStyle += " " + m.className;
4433
- if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
4434
- if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
4435
- if (m.title && !title) title = m.title;
4436
- if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
4437
- collapsed = sp;
4438
- } else if (sp.from > pos && nextChange > sp.from) {
4439
- nextChange = sp.from;
4440
- }
4441
- if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
4442
- }
4443
- if (collapsed && (collapsed.from || 0) == pos) {
4444
- buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
4445
- collapsed.marker, collapsed.from == null);
4446
- if (collapsed.to == null) return collapsed.marker.find();
4447
- }
4448
- if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
4449
- }
4450
- if (pos >= len) break;
4451
-
4452
- var upto = Math.min(len, nextChange);
4453
- while (true) {
4454
- if (text) {
4455
- var end = pos + text.length;
4456
- if (!collapsed) {
4457
- var tokenText = end > upto ? text.slice(0, upto - pos) : text;
4458
- builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
4459
- spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
4460
- }
4461
- if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
4462
- pos = end;
4463
- spanStartStyle = "";
4464
- }
4465
- text = allText.slice(at, at = styles[i++]);
4466
- style = styleToClass(styles[i++]);
4467
- }
4468
- }
4469
- }
4470
-
4471
- // DOCUMENT DATA STRUCTURE
4472
-
4473
- function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
4474
- function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
4475
- function update(line, text, spans) {
4476
- updateLine(line, text, spans, estimateHeight);
4477
- signalLater(line, "change", line, change);
4478
- }
4479
-
4480
- var from = change.from, to = change.to, text = change.text;
4481
- var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
4482
- var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
4483
-
4484
- // First adjust the line structure
4485
- if (from.ch == 0 && to.ch == 0 && lastText == "") {
4486
- // This is a whole-line replace. Treated specially to make
4487
- // sure line objects move the way they are supposed to.
4488
- for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
4489
- added.push(new Line(text[i], spansFor(i), estimateHeight));
4490
- update(lastLine, lastLine.text, lastSpans);
4491
- if (nlines) doc.remove(from.line, nlines);
4492
- if (added.length) doc.insert(from.line, added);
4493
- } else if (firstLine == lastLine) {
4494
- if (text.length == 1) {
4495
- update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4496
- } else {
4497
- for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
4498
- added.push(new Line(text[i], spansFor(i), estimateHeight));
4499
- added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4500
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4501
- doc.insert(from.line + 1, added);
4502
- }
4503
- } else if (text.length == 1) {
4504
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
4505
- doc.remove(from.line + 1, nlines);
4506
- } else {
4507
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4508
- update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4509
- for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
4510
- added.push(new Line(text[i], spansFor(i), estimateHeight));
4511
- if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
4512
- doc.insert(from.line + 1, added);
4513
- }
4514
-
4515
- signalLater(doc, "change", doc, change);
4516
- setSelection(doc, selAfter.anchor, selAfter.head, null, true);
4517
- }
4518
-
4519
- function LeafChunk(lines) {
4520
- this.lines = lines;
4521
- this.parent = null;
4522
- for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
4523
- lines[i].parent = this;
4524
- height += lines[i].height;
4525
- }
4526
- this.height = height;
4527
- }
4528
-
4529
- LeafChunk.prototype = {
4530
- chunkSize: function() { return this.lines.length; },
4531
- removeInner: function(at, n) {
4532
- for (var i = at, e = at + n; i < e; ++i) {
4533
- var line = this.lines[i];
4534
- this.height -= line.height;
4535
- cleanUpLine(line);
4536
- signalLater(line, "delete");
4537
- }
4538
- this.lines.splice(at, n);
4539
- },
4540
- collapse: function(lines) {
4541
- lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
4542
- },
4543
- insertInner: function(at, lines, height) {
4544
- this.height += height;
4545
- this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
4546
- for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
4547
- },
4548
- iterN: function(at, n, op) {
4549
- for (var e = at + n; at < e; ++at)
4550
- if (op(this.lines[at])) return true;
4551
- }
4552
- };
4553
-
4554
- function BranchChunk(children) {
4555
- this.children = children;
4556
- var size = 0, height = 0;
4557
- for (var i = 0, e = children.length; i < e; ++i) {
4558
- var ch = children[i];
4559
- size += ch.chunkSize(); height += ch.height;
4560
- ch.parent = this;
4561
- }
4562
- this.size = size;
4563
- this.height = height;
4564
- this.parent = null;
4565
- }
4566
-
4567
- BranchChunk.prototype = {
4568
- chunkSize: function() { return this.size; },
4569
- removeInner: function(at, n) {
4570
- this.size -= n;
4571
- for (var i = 0; i < this.children.length; ++i) {
4572
- var child = this.children[i], sz = child.chunkSize();
4573
- if (at < sz) {
4574
- var rm = Math.min(n, sz - at), oldHeight = child.height;
4575
- child.removeInner(at, rm);
4576
- this.height -= oldHeight - child.height;
4577
- if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
4578
- if ((n -= rm) == 0) break;
4579
- at = 0;
4580
- } else at -= sz;
4581
- }
4582
- if (this.size - n < 25) {
4583
- var lines = [];
4584
- this.collapse(lines);
4585
- this.children = [new LeafChunk(lines)];
4586
- this.children[0].parent = this;
4587
- }
4588
- },
4589
- collapse: function(lines) {
4590
- for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
4591
- },
4592
- insertInner: function(at, lines, height) {
4593
- this.size += lines.length;
4594
- this.height += height;
4595
- for (var i = 0, e = this.children.length; i < e; ++i) {
4596
- var child = this.children[i], sz = child.chunkSize();
4597
- if (at <= sz) {
4598
- child.insertInner(at, lines, height);
4599
- if (child.lines && child.lines.length > 50) {
4600
- while (child.lines.length > 50) {
4601
- var spilled = child.lines.splice(child.lines.length - 25, 25);
4602
- var newleaf = new LeafChunk(spilled);
4603
- child.height -= newleaf.height;
4604
- this.children.splice(i + 1, 0, newleaf);
4605
- newleaf.parent = this;
4606
- }
4607
- this.maybeSpill();
4608
- }
4609
- break;
4610
- }
4611
- at -= sz;
4612
- }
4613
- },
4614
- maybeSpill: function() {
4615
- if (this.children.length <= 10) return;
4616
- var me = this;
4617
- do {
4618
- var spilled = me.children.splice(me.children.length - 5, 5);
4619
- var sibling = new BranchChunk(spilled);
4620
- if (!me.parent) { // Become the parent node
4621
- var copy = new BranchChunk(me.children);
4622
- copy.parent = me;
4623
- me.children = [copy, sibling];
4624
- me = copy;
4625
- } else {
4626
- me.size -= sibling.size;
4627
- me.height -= sibling.height;
4628
- var myIndex = indexOf(me.parent.children, me);
4629
- me.parent.children.splice(myIndex + 1, 0, sibling);
4630
- }
4631
- sibling.parent = me.parent;
4632
- } while (me.children.length > 10);
4633
- me.parent.maybeSpill();
4634
- },
4635
- iterN: function(at, n, op) {
4636
- for (var i = 0, e = this.children.length; i < e; ++i) {
4637
- var child = this.children[i], sz = child.chunkSize();
4638
- if (at < sz) {
4639
- var used = Math.min(n, sz - at);
4640
- if (child.iterN(at, used, op)) return true;
4641
- if ((n -= used) == 0) break;
4642
- at = 0;
4643
- } else at -= sz;
4644
- }
4645
- }
4646
- };
4647
-
4648
- var nextDocId = 0;
4649
- var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
4650
- if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
4651
- if (firstLine == null) firstLine = 0;
4652
-
4653
- BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
4654
- this.first = firstLine;
4655
- this.scrollTop = this.scrollLeft = 0;
4656
- this.cantEdit = false;
4657
- this.history = makeHistory();
4658
- this.cleanGeneration = 1;
4659
- this.frontier = firstLine;
4660
- var start = Pos(firstLine, 0);
4661
- this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
4662
- this.id = ++nextDocId;
4663
- this.modeOption = mode;
4664
-
4665
- if (typeof text == "string") text = splitLines(text);
4666
- updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
4667
- };
4668
-
4669
- Doc.prototype = createObj(BranchChunk.prototype, {
4670
- constructor: Doc,
4671
- iter: function(from, to, op) {
4672
- if (op) this.iterN(from - this.first, to - from, op);
4673
- else this.iterN(this.first, this.first + this.size, from);
4674
- },
4675
-
4676
- insert: function(at, lines) {
4677
- var height = 0;
4678
- for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
4679
- this.insertInner(at - this.first, lines, height);
4680
- },
4681
- remove: function(at, n) { this.removeInner(at - this.first, n); },
4682
-
4683
- getValue: function(lineSep) {
4684
- var lines = getLines(this, this.first, this.first + this.size);
4685
- if (lineSep === false) return lines;
4686
- return lines.join(lineSep || "\n");
4687
- },
4688
- setValue: function(code) {
4689
- var top = Pos(this.first, 0), last = this.first + this.size - 1;
4690
- makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
4691
- text: splitLines(code), origin: "setValue"},
4692
- {head: top, anchor: top}, true);
4693
- },
4694
- replaceRange: function(code, from, to, origin) {
4695
- from = clipPos(this, from);
4696
- to = to ? clipPos(this, to) : from;
4697
- replaceRange(this, code, from, to, origin);
4698
- },
4699
- getRange: function(from, to, lineSep) {
4700
- var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
4701
- if (lineSep === false) return lines;
4702
- return lines.join(lineSep || "\n");
4703
- },
4704
-
4705
- getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
4706
- setLine: function(line, text) {
4707
- if (isLine(this, line))
4708
- replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
4709
- },
4710
- removeLine: function(line) {
4711
- if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));
4712
- else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));
4713
- },
4714
-
4715
- getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
4716
- getLineNumber: function(line) {return lineNo(line);},
4717
-
4718
- getLineHandleVisualStart: function(line) {
4719
- if (typeof line == "number") line = getLine(this, line);
4720
- return visualLine(this, line);
4721
- },
4722
-
4723
- lineCount: function() {return this.size;},
4724
- firstLine: function() {return this.first;},
4725
- lastLine: function() {return this.first + this.size - 1;},
4726
-
4727
- clipPos: function(pos) {return clipPos(this, pos);},
4728
-
4729
- getCursor: function(start) {
4730
- var sel = this.sel, pos;
4731
- if (start == null || start == "head") pos = sel.head;
4732
- else if (start == "anchor") pos = sel.anchor;
4733
- else if (start == "end" || start === false) pos = sel.to;
4734
- else pos = sel.from;
4735
- return copyPos(pos);
4736
- },
4737
- somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
4738
-
4739
- setCursor: docOperation(function(line, ch, extend) {
4740
- var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
4741
- if (extend) extendSelection(this, pos);
4742
- else setSelection(this, pos, pos);
4743
- }),
4744
- setSelection: docOperation(function(anchor, head) {
4745
- setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
4746
- }),
4747
- extendSelection: docOperation(function(from, to) {
4748
- extendSelection(this, clipPos(this, from), to && clipPos(this, to));
4749
- }),
4750
-
4751
- getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
4752
- replaceSelection: function(code, collapse, origin) {
4753
- makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
4754
- },
4755
- undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
4756
- redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
4757
-
4758
- setExtending: function(val) {this.sel.extend = val;},
4759
-
4760
- historySize: function() {
4761
- var hist = this.history;
4762
- return {undo: hist.done.length, redo: hist.undone.length};
4763
- },
4764
- clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},
4765
-
4766
- markClean: function() {
4767
- this.cleanGeneration = this.changeGeneration();
4768
- },
4769
- changeGeneration: function() {
4770
- this.history.lastOp = this.history.lastOrigin = null;
4771
- return this.history.generation;
4772
- },
4773
- isClean: function (gen) {
4774
- return this.history.generation == (gen || this.cleanGeneration);
4775
- },
4776
-
4777
- getHistory: function() {
4778
- return {done: copyHistoryArray(this.history.done),
4779
- undone: copyHistoryArray(this.history.undone)};
4780
- },
4781
- setHistory: function(histData) {
4782
- var hist = this.history = makeHistory(this.history.maxGeneration);
4783
- hist.done = histData.done.slice(0);
4784
- hist.undone = histData.undone.slice(0);
4785
- },
4786
-
4787
- markText: function(from, to, options) {
4788
- return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
4789
- },
4790
- setBookmark: function(pos, options) {
4791
- var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4792
- insertLeft: options && options.insertLeft};
4793
- pos = clipPos(this, pos);
4794
- return markText(this, pos, pos, realOpts, "bookmark");
4795
- },
4796
- findMarksAt: function(pos) {
4797
- pos = clipPos(this, pos);
4798
- var markers = [], spans = getLine(this, pos.line).markedSpans;
4799
- if (spans) for (var i = 0; i < spans.length; ++i) {
4800
- var span = spans[i];
4801
- if ((span.from == null || span.from <= pos.ch) &&
4802
- (span.to == null || span.to >= pos.ch))
4803
- markers.push(span.marker.parent || span.marker);
4804
- }
4805
- return markers;
4806
- },
4807
- getAllMarks: function() {
4808
- var markers = [];
4809
- this.iter(function(line) {
4810
- var sps = line.markedSpans;
4811
- if (sps) for (var i = 0; i < sps.length; ++i)
4812
- if (sps[i].from != null) markers.push(sps[i].marker);
4813
- });
4814
- return markers;
4815
- },
4816
-
4817
- posFromIndex: function(off) {
4818
- var ch, lineNo = this.first;
4819
- this.iter(function(line) {
4820
- var sz = line.text.length + 1;
4821
- if (sz > off) { ch = off; return true; }
4822
- off -= sz;
4823
- ++lineNo;
4824
- });
4825
- return clipPos(this, Pos(lineNo, ch));
4826
- },
4827
- indexFromPos: function (coords) {
4828
- coords = clipPos(this, coords);
4829
- var index = coords.ch;
4830
- if (coords.line < this.first || coords.ch < 0) return 0;
4831
- this.iter(this.first, coords.line, function (line) {
4832
- index += line.text.length + 1;
4833
- });
4834
- return index;
4835
- },
4836
-
4837
- copy: function(copyHistory) {
4838
- var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
4839
- doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
4840
- doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
4841
- shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
4842
- if (copyHistory) {
4843
- doc.history.undoDepth = this.history.undoDepth;
4844
- doc.setHistory(this.getHistory());
4845
- }
4846
- return doc;
4847
- },
4848
-
4849
- linkedDoc: function(options) {
4850
- if (!options) options = {};
4851
- var from = this.first, to = this.first + this.size;
4852
- if (options.from != null && options.from > from) from = options.from;
4853
- if (options.to != null && options.to < to) to = options.to;
4854
- var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
4855
- if (options.sharedHist) copy.history = this.history;
4856
- (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
4857
- copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
4858
- return copy;
4859
- },
4860
- unlinkDoc: function(other) {
4861
- if (other instanceof CodeMirror) other = other.doc;
4862
- if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
4863
- var link = this.linked[i];
4864
- if (link.doc != other) continue;
4865
- this.linked.splice(i, 1);
4866
- other.unlinkDoc(this);
4867
- break;
4868
- }
4869
- // If the histories were shared, split them again
4870
- if (other.history == this.history) {
4871
- var splitIds = [other.id];
4872
- linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
4873
- other.history = makeHistory();
4874
- other.history.done = copyHistoryArray(this.history.done, splitIds);
4875
- other.history.undone = copyHistoryArray(this.history.undone, splitIds);
4876
- }
4877
- },
4878
- iterLinkedDocs: function(f) {linkedDocs(this, f);},
4879
-
4880
- getMode: function() {return this.mode;},
4881
- getEditor: function() {return this.cm;}
4882
- });
4883
-
4884
- Doc.prototype.eachLine = Doc.prototype.iter;
4885
-
4886
- // The Doc methods that should be available on CodeMirror instances
4887
- var dontDelegate = "iter insert remove copy getEditor".split(" ");
4888
- for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
4889
- CodeMirror.prototype[prop] = (function(method) {
4890
- return function() {return method.apply(this.doc, arguments);};
4891
- })(Doc.prototype[prop]);
4892
-
4893
- eventMixin(Doc);
4894
-
4895
- function linkedDocs(doc, f, sharedHistOnly) {
4896
- function propagate(doc, skip, sharedHist) {
4897
- if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
4898
- var rel = doc.linked[i];
4899
- if (rel.doc == skip) continue;
4900
- var shared = sharedHist && rel.sharedHist;
4901
- if (sharedHistOnly && !shared) continue;
4902
- f(rel.doc, shared);
4903
- propagate(rel.doc, doc, shared);
4904
- }
4905
- }
4906
- propagate(doc, null, true);
4907
- }
4908
-
4909
- function attachDoc(cm, doc) {
4910
- if (doc.cm) throw new Error("This document is already in use.");
4911
- cm.doc = doc;
4912
- doc.cm = cm;
4913
- estimateLineHeights(cm);
4914
- loadMode(cm);
4915
- if (!cm.options.lineWrapping) computeMaxLength(cm);
4916
- cm.options.mode = doc.modeOption;
4917
- regChange(cm);
4918
- }
4919
-
4920
- // LINE UTILITIES
4921
-
4922
- function getLine(chunk, n) {
4923
- n -= chunk.first;
4924
- while (!chunk.lines) {
4925
- for (var i = 0;; ++i) {
4926
- var child = chunk.children[i], sz = child.chunkSize();
4927
- if (n < sz) { chunk = child; break; }
4928
- n -= sz;
4929
- }
4930
- }
4931
- return chunk.lines[n];
4932
- }
4933
-
4934
- function getBetween(doc, start, end) {
4935
- var out = [], n = start.line;
4936
- doc.iter(start.line, end.line + 1, function(line) {
4937
- var text = line.text;
4938
- if (n == end.line) text = text.slice(0, end.ch);
4939
- if (n == start.line) text = text.slice(start.ch);
4940
- out.push(text);
4941
- ++n;
4942
- });
4943
- return out;
4944
- }
4945
- function getLines(doc, from, to) {
4946
- var out = [];
4947
- doc.iter(from, to, function(line) { out.push(line.text); });
4948
- return out;
4949
- }
4950
-
4951
- function updateLineHeight(line, height) {
4952
- var diff = height - line.height;
4953
- for (var n = line; n; n = n.parent) n.height += diff;
4954
- }
4955
-
4956
- function lineNo(line) {
4957
- if (line.parent == null) return null;
4958
- var cur = line.parent, no = indexOf(cur.lines, line);
4959
- for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
4960
- for (var i = 0;; ++i) {
4961
- if (chunk.children[i] == cur) break;
4962
- no += chunk.children[i].chunkSize();
4963
- }
4964
- }
4965
- return no + cur.first;
4966
- }
4967
-
4968
- function lineAtHeight(chunk, h) {
4969
- var n = chunk.first;
4970
- outer: do {
4971
- for (var i = 0, e = chunk.children.length; i < e; ++i) {
4972
- var child = chunk.children[i], ch = child.height;
4973
- if (h < ch) { chunk = child; continue outer; }
4974
- h -= ch;
4975
- n += child.chunkSize();
4976
- }
4977
- return n;
4978
- } while (!chunk.lines);
4979
- for (var i = 0, e = chunk.lines.length; i < e; ++i) {
4980
- var line = chunk.lines[i], lh = line.height;
4981
- if (h < lh) break;
4982
- h -= lh;
4983
- }
4984
- return n + i;
4985
- }
4986
-
4987
- function heightAtLine(cm, lineObj) {
4988
- lineObj = visualLine(cm.doc, lineObj);
4989
-
4990
- var h = 0, chunk = lineObj.parent;
4991
- for (var i = 0; i < chunk.lines.length; ++i) {
4992
- var line = chunk.lines[i];
4993
- if (line == lineObj) break;
4994
- else h += line.height;
4995
- }
4996
- for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
4997
- for (var i = 0; i < p.children.length; ++i) {
4998
- var cur = p.children[i];
4999
- if (cur == chunk) break;
5000
- else h += cur.height;
5001
- }
5002
- }
5003
- return h;
5004
- }
5005
-
5006
- function getOrder(line) {
5007
- var order = line.order;
5008
- if (order == null) order = line.order = bidiOrdering(line.text);
5009
- return order;
5010
- }
5011
-
5012
- // HISTORY
5013
-
5014
- function makeHistory(startGen) {
5015
- return {
5016
- // Arrays of history events. Doing something adds an event to
5017
- // done and clears undo. Undoing moves events from done to
5018
- // undone, redoing moves them in the other direction.
5019
- done: [], undone: [], undoDepth: Infinity,
5020
- // Used to track when changes can be merged into a single undo
5021
- // event
5022
- lastTime: 0, lastOp: null, lastOrigin: null,
5023
- // Used by the isClean() method
5024
- generation: startGen || 1, maxGeneration: startGen || 1
5025
- };
5026
- }
5027
-
5028
- function attachLocalSpans(doc, change, from, to) {
5029
- var existing = change["spans_" + doc.id], n = 0;
5030
- doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
5031
- if (line.markedSpans)
5032
- (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
5033
- ++n;
5034
- });
5035
- }
5036
-
5037
- function historyChangeFromChange(doc, change) {
5038
- var from = { line: change.from.line, ch: change.from.ch };
5039
- var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
5040
- attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
5041
- linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
5042
- return histChange;
5043
- }
5044
-
5045
- function addToHistory(doc, change, selAfter, opId) {
5046
- var hist = doc.history;
5047
- hist.undone.length = 0;
5048
- var time = +new Date, cur = lst(hist.done);
5049
-
5050
- if (cur &&
5051
- (hist.lastOp == opId ||
5052
- hist.lastOrigin == change.origin && change.origin &&
5053
- ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||
5054
- change.origin.charAt(0) == "*"))) {
5055
- // Merge this change into the last event
5056
- var last = lst(cur.changes);
5057
- if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
5058
- // Optimized case for simple insertion -- don't want to add
5059
- // new changesets for every character typed
5060
- last.to = changeEnd(change);
5061
- } else {
5062
- // Add new sub-event
5063
- cur.changes.push(historyChangeFromChange(doc, change));
5064
- }
5065
- cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
5066
- } else {
5067
- // Can not be merged, start a new event.
5068
- cur = {changes: [historyChangeFromChange(doc, change)],
5069
- generation: hist.generation,
5070
- anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
5071
- anchorAfter: selAfter.anchor, headAfter: selAfter.head};
5072
- hist.done.push(cur);
5073
- hist.generation = ++hist.maxGeneration;
5074
- while (hist.done.length > hist.undoDepth)
5075
- hist.done.shift();
5076
- }
5077
- hist.lastTime = time;
5078
- hist.lastOp = opId;
5079
- hist.lastOrigin = change.origin;
5080
- }
5081
-
5082
- function removeClearedSpans(spans) {
5083
- if (!spans) return null;
5084
- for (var i = 0, out; i < spans.length; ++i) {
5085
- if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
5086
- else if (out) out.push(spans[i]);
5087
- }
5088
- return !out ? spans : out.length ? out : null;
5089
- }
5090
-
5091
- function getOldSpans(doc, change) {
5092
- var found = change["spans_" + doc.id];
5093
- if (!found) return null;
5094
- for (var i = 0, nw = []; i < change.text.length; ++i)
5095
- nw.push(removeClearedSpans(found[i]));
5096
- return nw;
5097
- }
5098
-
5099
- // Used both to provide a JSON-safe object in .getHistory, and, when
5100
- // detaching a document, to split the history in two
5101
- function copyHistoryArray(events, newGroup) {
5102
- for (var i = 0, copy = []; i < events.length; ++i) {
5103
- var event = events[i], changes = event.changes, newChanges = [];
5104
- copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
5105
- anchorAfter: event.anchorAfter, headAfter: event.headAfter});
5106
- for (var j = 0; j < changes.length; ++j) {
5107
- var change = changes[j], m;
5108
- newChanges.push({from: change.from, to: change.to, text: change.text});
5109
- if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
5110
- if (indexOf(newGroup, Number(m[1])) > -1) {
5111
- lst(newChanges)[prop] = change[prop];
5112
- delete change[prop];
5113
- }
5114
- }
5115
- }
5116
- }
5117
- return copy;
5118
- }
5119
-
5120
- // Rebasing/resetting history to deal with externally-sourced changes
5121
-
5122
- function rebaseHistSel(pos, from, to, diff) {
5123
- if (to < pos.line) {
5124
- pos.line += diff;
5125
- } else if (from < pos.line) {
5126
- pos.line = from;
5127
- pos.ch = 0;
5128
- }
5129
- }
5130
-
5131
- // Tries to rebase an array of history events given a change in the
5132
- // document. If the change touches the same lines as the event, the
5133
- // event, and everything 'behind' it, is discarded. If the change is
5134
- // before the event, the event's positions are updated. Uses a
5135
- // copy-on-write scheme for the positions, to avoid having to
5136
- // reallocate them all on every rebase, but also avoid problems with
5137
- // shared position objects being unsafely updated.
5138
- function rebaseHistArray(array, from, to, diff) {
5139
- for (var i = 0; i < array.length; ++i) {
5140
- var sub = array[i], ok = true;
5141
- for (var j = 0; j < sub.changes.length; ++j) {
5142
- var cur = sub.changes[j];
5143
- if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
5144
- if (to < cur.from.line) {
5145
- cur.from.line += diff;
5146
- cur.to.line += diff;
5147
- } else if (from <= cur.to.line) {
5148
- ok = false;
5149
- break;
5150
- }
5151
- }
5152
- if (!sub.copied) {
5153
- sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
5154
- sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
5155
- sub.copied = true;
5156
- }
5157
- if (!ok) {
5158
- array.splice(0, i + 1);
5159
- i = 0;
5160
- } else {
5161
- rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
5162
- rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
5163
- }
5164
- }
5165
- }
5166
-
5167
- function rebaseHist(hist, change) {
5168
- var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
5169
- rebaseHistArray(hist.done, from, to, diff);
5170
- rebaseHistArray(hist.undone, from, to, diff);
5171
- }
5172
-
5173
- // EVENT OPERATORS
5174
-
5175
- function stopMethod() {e_stop(this);}
5176
- // Ensure an event has a stop method.
5177
- function addStop(event) {
5178
- if (!event.stop) event.stop = stopMethod;
5179
- return event;
5180
- }
5181
-
5182
- function e_preventDefault(e) {
5183
- if (e.preventDefault) e.preventDefault();
5184
- else e.returnValue = false;
5185
- }
5186
- function e_stopPropagation(e) {
5187
- if (e.stopPropagation) e.stopPropagation();
5188
- else e.cancelBubble = true;
5189
- }
5190
- function e_defaultPrevented(e) {
5191
- return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
5192
- }
5193
- function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
5194
- CodeMirror.e_stop = e_stop;
5195
- CodeMirror.e_preventDefault = e_preventDefault;
5196
- CodeMirror.e_stopPropagation = e_stopPropagation;
5197
-
5198
- function e_target(e) {return e.target || e.srcElement;}
5199
- function e_button(e) {
5200
- var b = e.which;
5201
- if (b == null) {
5202
- if (e.button & 1) b = 1;
5203
- else if (e.button & 2) b = 3;
5204
- else if (e.button & 4) b = 2;
5205
- }
5206
- if (mac && e.ctrlKey && b == 1) b = 3;
5207
- return b;
5208
- }
5209
-
5210
- // EVENT HANDLING
5211
-
5212
- function on(emitter, type, f) {
5213
- if (emitter.addEventListener)
5214
- emitter.addEventListener(type, f, false);
5215
- else if (emitter.attachEvent)
5216
- emitter.attachEvent("on" + type, f);
5217
- else {
5218
- var map = emitter._handlers || (emitter._handlers = {});
5219
- var arr = map[type] || (map[type] = []);
5220
- arr.push(f);
5221
- }
5222
- }
5223
-
5224
- function off(emitter, type, f) {
5225
- if (emitter.removeEventListener)
5226
- emitter.removeEventListener(type, f, false);
5227
- else if (emitter.detachEvent)
5228
- emitter.detachEvent("on" + type, f);
5229
- else {
5230
- var arr = emitter._handlers && emitter._handlers[type];
5231
- if (!arr) return;
5232
- for (var i = 0; i < arr.length; ++i)
5233
- if (arr[i] == f) { arr.splice(i, 1); break; }
5234
- }
5235
- }
5236
-
5237
- function signal(emitter, type /*, values...*/) {
5238
- var arr = emitter._handlers && emitter._handlers[type];
5239
- if (!arr) return;
5240
- var args = Array.prototype.slice.call(arguments, 2);
5241
- for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
5242
- }
5243
-
5244
- var delayedCallbacks, delayedCallbackDepth = 0;
5245
- function signalLater(emitter, type /*, values...*/) {
5246
- var arr = emitter._handlers && emitter._handlers[type];
5247
- if (!arr) return;
5248
- var args = Array.prototype.slice.call(arguments, 2);
5249
- if (!delayedCallbacks) {
5250
- ++delayedCallbackDepth;
5251
- delayedCallbacks = [];
5252
- setTimeout(fireDelayed, 0);
5253
- }
5254
- function bnd(f) {return function(){f.apply(null, args);};};
5255
- for (var i = 0; i < arr.length; ++i)
5256
- delayedCallbacks.push(bnd(arr[i]));
5257
- }
5258
-
5259
- function signalDOMEvent(cm, e, override) {
5260
- signal(cm, override || e.type, cm, e);
5261
- return e_defaultPrevented(e) || e.codemirrorIgnore;
5262
- }
5263
-
5264
- function fireDelayed() {
5265
- --delayedCallbackDepth;
5266
- var delayed = delayedCallbacks;
5267
- delayedCallbacks = null;
5268
- for (var i = 0; i < delayed.length; ++i) delayed[i]();
5269
- }
5270
-
5271
- function hasHandler(emitter, type) {
5272
- var arr = emitter._handlers && emitter._handlers[type];
5273
- return arr && arr.length > 0;
5274
- }
5275
-
5276
- CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
5277
-
5278
- function eventMixin(ctor) {
5279
- ctor.prototype.on = function(type, f) {on(this, type, f);};
5280
- ctor.prototype.off = function(type, f) {off(this, type, f);};
5281
- }
5282
-
5283
- // MISC UTILITIES
5284
-
5285
- // Number of pixels added to scroller and sizer to hide scrollbar
5286
- var scrollerCutOff = 30;
5287
-
5288
- // Returned or thrown by various protocols to signal 'I'm not
5289
- // handling this'.
5290
- var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
5291
-
5292
- function Delayed() {this.id = null;}
5293
- Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
5294
-
5295
- // Counts the column offset in a string, taking tabs into account.
5296
- // Used mostly to find indentation.
5297
- function countColumn(string, end, tabSize, startIndex, startValue) {
5298
- if (end == null) {
5299
- end = string.search(/[^\s\u00a0]/);
5300
- if (end == -1) end = string.length;
5301
- }
5302
- for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
5303
- if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
5304
- else ++n;
5305
- }
5306
- return n;
5307
- }
5308
- CodeMirror.countColumn = countColumn;
5309
-
5310
- var spaceStrs = [""];
5311
- function spaceStr(n) {
5312
- while (spaceStrs.length <= n)
5313
- spaceStrs.push(lst(spaceStrs) + " ");
5314
- return spaceStrs[n];
5315
- }
5316
-
5317
- function lst(arr) { return arr[arr.length-1]; }
5318
-
5319
- function selectInput(node) {
5320
- if (ios) { // Mobile Safari apparently has a bug where select() is broken.
5321
- node.selectionStart = 0;
5322
- node.selectionEnd = node.value.length;
5323
- } else {
5324
- // Suppress mysterious IE10 errors
5325
- try { node.select(); }
5326
- catch(_e) {}
5327
- }
5328
- }
5329
-
5330
- function indexOf(collection, elt) {
5331
- if (collection.indexOf) return collection.indexOf(elt);
5332
- for (var i = 0, e = collection.length; i < e; ++i)
5333
- if (collection[i] == elt) return i;
5334
- return -1;
5335
- }
5336
-
5337
- function createObj(base, props) {
5338
- function Obj() {}
5339
- Obj.prototype = base;
5340
- var inst = new Obj();
5341
- if (props) copyObj(props, inst);
5342
- return inst;
5343
- }
5344
-
5345
- function copyObj(obj, target) {
5346
- if (!target) target = {};
5347
- for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
5348
- return target;
5349
- }
5350
-
5351
- function emptyArray(size) {
5352
- for (var a = [], i = 0; i < size; ++i) a.push(undefined);
5353
- return a;
5354
- }
5355
-
5356
- function bind(f) {
5357
- var args = Array.prototype.slice.call(arguments, 1);
5358
- return function(){return f.apply(null, args);};
5359
- }
5360
-
5361
- var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
5362
- function isWordChar(ch) {
5363
- return /\w/.test(ch) || ch > "\x80" &&
5364
- (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
5365
- }
5366
-
5367
- function isEmpty(obj) {
5368
- for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
5369
- return true;
5370
- }
5371
-
5372
- var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
5373
-
5374
- // DOM UTILITIES
5375
-
5376
- function elt(tag, content, className, style) {
5377
- var e = document.createElement(tag);
5378
- if (className) e.className = className;
5379
- if (style) e.style.cssText = style;
5380
- if (typeof content == "string") setTextContent(e, content);
5381
- else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
5382
- return e;
5383
- }
5384
-
5385
- function removeChildren(e) {
5386
- for (var count = e.childNodes.length; count > 0; --count)
5387
- e.removeChild(e.firstChild);
5388
- return e;
5389
- }
5390
-
5391
- function removeChildrenAndAdd(parent, e) {
5392
- return removeChildren(parent).appendChild(e);
5393
- }
5394
-
5395
- function setTextContent(e, str) {
5396
- if (ie_lt9) {
5397
- e.innerHTML = "";
5398
- e.appendChild(document.createTextNode(str));
5399
- } else e.textContent = str;
5400
- }
5401
-
5402
- function getRect(node) {
5403
- return node.getBoundingClientRect();
5404
- }
5405
- CodeMirror.replaceGetRect = function(f) { getRect = f; };
5406
-
5407
- // FEATURE DETECTION
5408
-
5409
- // Detect drag-and-drop
5410
- var dragAndDrop = function() {
5411
- // There is *some* kind of drag-and-drop support in IE6-8, but I
5412
- // couldn't get it to work yet.
5413
- if (ie_lt9) return false;
5414
- var div = elt('div');
5415
- return "draggable" in div || "dragDrop" in div;
5416
- }();
5417
-
5418
- // For a reason I have yet to figure out, some browsers disallow
5419
- // word wrapping between certain characters *only* if a new inline
5420
- // element is started between them. This makes it hard to reliably
5421
- // measure the position of things, since that requires inserting an
5422
- // extra span. This terribly fragile set of tests matches the
5423
- // character combinations that suffer from this phenomenon on the
5424
- // various browsers.
5425
- function spanAffectsWrapping() { return false; }
5426
- if (gecko) // Only for "$'"
5427
- spanAffectsWrapping = function(str, i) {
5428
- return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;
5429
- };
5430
- else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
5431
- spanAffectsWrapping = function(str, i) {
5432
- return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
5433
- };
5434
- else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
5435
- spanAffectsWrapping = function(str, i) {
5436
- if (i > 1 && str.charCodeAt(i - 1) == 45) {
5437
- if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
5438
- if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
5439
- }
5440
- return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
5441
- };
5442
-
5443
- var knownScrollbarWidth;
5444
- function scrollbarWidth(measure) {
5445
- if (knownScrollbarWidth != null) return knownScrollbarWidth;
5446
- var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
5447
- removeChildrenAndAdd(measure, test);
5448
- if (test.offsetWidth)
5449
- knownScrollbarWidth = test.offsetHeight - test.clientHeight;
5450
- return knownScrollbarWidth || 0;
5451
- }
5452
-
5453
- var zwspSupported;
5454
- function zeroWidthElement(measure) {
5455
- if (zwspSupported == null) {
5456
- var test = elt("span", "\u200b");
5457
- removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
5458
- if (measure.firstChild.offsetHeight != 0)
5459
- zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
5460
- }
5461
- if (zwspSupported) return elt("span", "\u200b");
5462
- else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
5463
- }
5464
-
5465
- // See if "".split is the broken IE version, if so, provide an
5466
- // alternative way to split lines.
5467
- var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
5468
- var pos = 0, result = [], l = string.length;
5469
- while (pos <= l) {
5470
- var nl = string.indexOf("\n", pos);
5471
- if (nl == -1) nl = string.length;
5472
- var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
5473
- var rt = line.indexOf("\r");
5474
- if (rt != -1) {
5475
- result.push(line.slice(0, rt));
5476
- pos += rt + 1;
5477
- } else {
5478
- result.push(line);
5479
- pos = nl + 1;
5480
- }
5481
- }
5482
- return result;
5483
- } : function(string){return string.split(/\r\n?|\n/);};
5484
- CodeMirror.splitLines = splitLines;
5485
-
5486
- var hasSelection = window.getSelection ? function(te) {
5487
- try { return te.selectionStart != te.selectionEnd; }
5488
- catch(e) { return false; }
5489
- } : function(te) {
5490
- try {var range = te.ownerDocument.selection.createRange();}
5491
- catch(e) {}
5492
- if (!range || range.parentElement() != te) return false;
5493
- return range.compareEndPoints("StartToEnd", range) != 0;
5494
- };
5495
-
5496
- var hasCopyEvent = (function() {
5497
- var e = elt("div");
5498
- if ("oncopy" in e) return true;
5499
- e.setAttribute("oncopy", "return;");
5500
- return typeof e.oncopy == 'function';
5501
- })();
5502
-
5503
- // KEY NAMING
5504
-
5505
- var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
5506
- 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
5507
- 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
5508
- 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
5509
- 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
5510
- 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
5511
- 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
5512
- CodeMirror.keyNames = keyNames;
5513
- (function() {
5514
- // Number keys
5515
- for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
5516
- // Alphabetic keys
5517
- for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
5518
- // Function keys
5519
- for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
5520
- })();
5521
-
5522
- // BIDI HELPERS
5523
-
5524
- function iterateBidiSections(order, from, to, f) {
5525
- if (!order) return f(from, to, "ltr");
5526
- var found = false;
5527
- for (var i = 0; i < order.length; ++i) {
5528
- var part = order[i];
5529
- if (part.from < to && part.to > from || from == to && part.to == from) {
5530
- f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
5531
- found = true;
5532
- }
5533
- }
5534
- if (!found) f(from, to, "ltr");
5535
- }
5536
-
5537
- function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
5538
- function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
5539
-
5540
- function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
5541
- function lineRight(line) {
5542
- var order = getOrder(line);
5543
- if (!order) return line.text.length;
5544
- return bidiRight(lst(order));
5545
- }
5546
-
5547
- function lineStart(cm, lineN) {
5548
- var line = getLine(cm.doc, lineN);
5549
- var visual = visualLine(cm.doc, line);
5550
- if (visual != line) lineN = lineNo(visual);
5551
- var order = getOrder(visual);
5552
- var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
5553
- return Pos(lineN, ch);
5554
- }
5555
- function lineEnd(cm, lineN) {
5556
- var merged, line;
5557
- while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
5558
- lineN = merged.find().to.line;
5559
- var order = getOrder(line);
5560
- var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
5561
- return Pos(lineN, ch);
5562
- }
5563
-
5564
- function compareBidiLevel(order, a, b) {
5565
- var linedir = order[0].level;
5566
- if (a == linedir) return true;
5567
- if (b == linedir) return false;
5568
- return a < b;
5569
- }
5570
- var bidiOther;
5571
- function getBidiPartAt(order, pos) {
5572
- for (var i = 0, found; i < order.length; ++i) {
5573
- var cur = order[i];
5574
- if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; }
5575
- if (cur.from == pos || cur.to == pos) {
5576
- if (found == null) {
5577
- found = i;
5578
- } else if (compareBidiLevel(order, cur.level, order[found].level)) {
5579
- bidiOther = found;
5580
- return i;
5581
- } else {
5582
- bidiOther = i;
5583
- return found;
5584
- }
5585
- }
5586
- }
5587
- bidiOther = null;
5588
- return found;
5589
- }
5590
-
5591
- function moveInLine(line, pos, dir, byUnit) {
5592
- if (!byUnit) return pos + dir;
5593
- do pos += dir;
5594
- while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
5595
- return pos;
5596
- }
5597
-
5598
- // This is somewhat involved. It is needed in order to move
5599
- // 'visually' through bi-directional text -- i.e., pressing left
5600
- // should make the cursor go left, even when in RTL text. The
5601
- // tricky part is the 'jumps', where RTL and LTR text touch each
5602
- // other. This often requires the cursor offset to move more than
5603
- // one unit, in order to visually move one unit.
5604
- function moveVisually(line, start, dir, byUnit) {
5605
- var bidi = getOrder(line);
5606
- if (!bidi) return moveLogically(line, start, dir, byUnit);
5607
- var pos = getBidiPartAt(bidi, start), part = bidi[pos];
5608
- var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
5609
-
5610
- for (;;) {
5611
- if (target > part.from && target < part.to) return target;
5612
- if (target == part.from || target == part.to) {
5613
- if (getBidiPartAt(bidi, target) == pos) return target;
5614
- part = bidi[pos += dir];
5615
- return (dir > 0) == part.level % 2 ? part.to : part.from;
5616
- } else {
5617
- part = bidi[pos += dir];
5618
- if (!part) return null;
5619
- if ((dir > 0) == part.level % 2)
5620
- target = moveInLine(line, part.to, -1, byUnit);
5621
- else
5622
- target = moveInLine(line, part.from, 1, byUnit);
5623
- }
5624
- }
5625
- }
5626
-
5627
- function moveLogically(line, start, dir, byUnit) {
5628
- var target = start + dir;
5629
- if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
5630
- return target < 0 || target > line.text.length ? null : target;
5631
- }
5632
-
5633
- // Bidirectional ordering algorithm
5634
- // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
5635
- // that this (partially) implements.
5636
-
5637
- // One-char codes used for character types:
5638
- // L (L): Left-to-Right
5639
- // R (R): Right-to-Left
5640
- // r (AL): Right-to-Left Arabic
5641
- // 1 (EN): European Number
5642
- // + (ES): European Number Separator
5643
- // % (ET): European Number Terminator
5644
- // n (AN): Arabic Number
5645
- // , (CS): Common Number Separator
5646
- // m (NSM): Non-Spacing Mark
5647
- // b (BN): Boundary Neutral
5648
- // s (B): Paragraph Separator
5649
- // t (S): Segment Separator
5650
- // w (WS): Whitespace
5651
- // N (ON): Other Neutrals
5652
-
5653
- // Returns null if characters are ordered as they appear
5654
- // (left-to-right), or an array of sections ({from, to, level}
5655
- // objects) in the order in which they occur visually.
5656
- var bidiOrdering = (function() {
5657
- // Character types for codepoints 0 to 0xff
5658
- var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
5659
- // Character types for codepoints 0x600 to 0x6ff
5660
- var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
5661
- function charType(code) {
5662
- if (code <= 0xff) return lowTypes.charAt(code);
5663
- else if (0x590 <= code && code <= 0x5f4) return "R";
5664
- else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
5665
- else if (0x700 <= code && code <= 0x8ac) return "r";
5666
- else return "L";
5667
- }
5668
-
5669
- var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
5670
- var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
5671
- // Browsers seem to always treat the boundaries of block elements as being L.
5672
- var outerType = "L";
5673
-
5674
- return function(str) {
5675
- if (!bidiRE.test(str)) return false;
5676
- var len = str.length, types = [];
5677
- for (var i = 0, type; i < len; ++i)
5678
- types.push(type = charType(str.charCodeAt(i)));
5679
-
5680
- // W1. Examine each non-spacing mark (NSM) in the level run, and
5681
- // change the type of the NSM to the type of the previous
5682
- // character. If the NSM is at the start of the level run, it will
5683
- // get the type of sor.
5684
- for (var i = 0, prev = outerType; i < len; ++i) {
5685
- var type = types[i];
5686
- if (type == "m") types[i] = prev;
5687
- else prev = type;
5688
- }
5689
-
5690
- // W2. Search backwards from each instance of a European number
5691
- // until the first strong type (R, L, AL, or sor) is found. If an
5692
- // AL is found, change the type of the European number to Arabic
5693
- // number.
5694
- // W3. Change all ALs to R.
5695
- for (var i = 0, cur = outerType; i < len; ++i) {
5696
- var type = types[i];
5697
- if (type == "1" && cur == "r") types[i] = "n";
5698
- else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
5699
- }
5700
-
5701
- // W4. A single European separator between two European numbers
5702
- // changes to a European number. A single common separator between
5703
- // two numbers of the same type changes to that type.
5704
- for (var i = 1, prev = types[0]; i < len - 1; ++i) {
5705
- var type = types[i];
5706
- if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
5707
- else if (type == "," && prev == types[i+1] &&
5708
- (prev == "1" || prev == "n")) types[i] = prev;
5709
- prev = type;
5710
- }
5711
-
5712
- // W5. A sequence of European terminators adjacent to European
5713
- // numbers changes to all European numbers.
5714
- // W6. Otherwise, separators and terminators change to Other
5715
- // Neutral.
5716
- for (var i = 0; i < len; ++i) {
5717
- var type = types[i];
5718
- if (type == ",") types[i] = "N";
5719
- else if (type == "%") {
5720
- for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
5721
- var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
5722
- for (var j = i; j < end; ++j) types[j] = replace;
5723
- i = end - 1;
5724
- }
5725
- }
5726
-
5727
- // W7. Search backwards from each instance of a European number
5728
- // until the first strong type (R, L, or sor) is found. If an L is
5729
- // found, then change the type of the European number to L.
5730
- for (var i = 0, cur = outerType; i < len; ++i) {
5731
- var type = types[i];
5732
- if (cur == "L" && type == "1") types[i] = "L";
5733
- else if (isStrong.test(type)) cur = type;
5734
- }
5735
-
5736
- // N1. A sequence of neutrals takes the direction of the
5737
- // surrounding strong text if the text on both sides has the same
5738
- // direction. European and Arabic numbers act as if they were R in
5739
- // terms of their influence on neutrals. Start-of-level-run (sor)
5740
- // and end-of-level-run (eor) are used at level run boundaries.
5741
- // N2. Any remaining neutrals take the embedding direction.
5742
- for (var i = 0; i < len; ++i) {
5743
- if (isNeutral.test(types[i])) {
5744
- for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
5745
- var before = (i ? types[i-1] : outerType) == "L";
5746
- var after = (end < len - 1 ? types[end] : outerType) == "L";
5747
- var replace = before || after ? "L" : "R";
5748
- for (var j = i; j < end; ++j) types[j] = replace;
5749
- i = end - 1;
5750
- }
5751
- }
5752
-
5753
- // Here we depart from the documented algorithm, in order to avoid
5754
- // building up an actual levels array. Since there are only three
5755
- // levels (0, 1, 2) in an implementation that doesn't take
5756
- // explicit embedding into account, we can build up the order on
5757
- // the fly, without following the level-based algorithm.
5758
- var order = [], m;
5759
- for (var i = 0; i < len;) {
5760
- if (countsAsLeft.test(types[i])) {
5761
- var start = i;
5762
- for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
5763
- order.push({from: start, to: i, level: 0});
5764
- } else {
5765
- var pos = i, at = order.length;
5766
- for (++i; i < len && types[i] != "L"; ++i) {}
5767
- for (var j = pos; j < i;) {
5768
- if (countsAsNum.test(types[j])) {
5769
- if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
5770
- var nstart = j;
5771
- for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
5772
- order.splice(at, 0, {from: nstart, to: j, level: 2});
5773
- pos = j;
5774
- } else ++j;
5775
- }
5776
- if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
5777
- }
5778
- }
5779
- if (order[0].level == 1 && (m = str.match(/^\s+/))) {
5780
- order[0].from = m[0].length;
5781
- order.unshift({from: 0, to: m[0].length, level: 0});
5782
- }
5783
- if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
5784
- lst(order).to -= m[0].length;
5785
- order.push({from: len - m[0].length, to: len, level: 0});
5786
- }
5787
- if (order[0].level != lst(order).level)
5788
- order.push({from: len, to: len, level: order[0].level});
5789
-
5790
- return order;
5791
- };
5792
- })();
5793
-
5794
- // THE END
5795
-
5796
- CodeMirror.version = "3.15.0";
5797
-
5798
- return CodeMirror;
5799
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codemirror/mode/clike.js DELETED
@@ -1,362 +0,0 @@
1
- CodeMirror.defineMode("clike", function(config, parserConfig) {
2
- var indentUnit = config.indentUnit,
3
- statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
4
- dontAlignCalls = parserConfig.dontAlignCalls,
5
- keywords = parserConfig.keywords || {},
6
- builtin = parserConfig.builtin || {},
7
- blockKeywords = parserConfig.blockKeywords || {},
8
- atoms = parserConfig.atoms || {},
9
- hooks = parserConfig.hooks || {},
10
- multiLineStrings = parserConfig.multiLineStrings;
11
- var isOperatorChar = /[+\-*&%=<>!?|\/]/;
12
-
13
- var curPunc;
14
-
15
- function tokenBase(stream, state) {
16
- var ch = stream.next();
17
- if (hooks[ch]) {
18
- var result = hooks[ch](stream, state);
19
- if (result !== false) return result;
20
- }
21
- if (ch == '"' || ch == "'") {
22
- state.tokenize = tokenString(ch);
23
- return state.tokenize(stream, state);
24
- }
25
- if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
26
- curPunc = ch;
27
- return null;
28
- }
29
- if (/\d/.test(ch)) {
30
- stream.eatWhile(/[\w\.]/);
31
- return "number";
32
- }
33
- if (ch == "/") {
34
- if (stream.eat("*")) {
35
- state.tokenize = tokenComment;
36
- return tokenComment(stream, state);
37
- }
38
- if (stream.eat("/")) {
39
- stream.skipToEnd();
40
- return "comment";
41
- }
42
- }
43
- if (isOperatorChar.test(ch)) {
44
- stream.eatWhile(isOperatorChar);
45
- return "operator";
46
- }
47
- stream.eatWhile(/[\w\$_]/);
48
- var cur = stream.current();
49
- if (keywords.propertyIsEnumerable(cur)) {
50
- if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
51
- return "keyword";
52
- }
53
- if (builtin.propertyIsEnumerable(cur)) {
54
- if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
55
- return "builtin";
56
- }
57
- if (atoms.propertyIsEnumerable(cur)) return "atom";
58
- return "variable";
59
- }
60
-
61
- function tokenString(quote) {
62
- return function(stream, state) {
63
- var escaped = false, next, end = false;
64
- while ((next = stream.next()) != null) {
65
- if (next == quote && !escaped) {end = true; break;}
66
- escaped = !escaped && next == "\\";
67
- }
68
- if (end || !(escaped || multiLineStrings))
69
- state.tokenize = null;
70
- return "string";
71
- };
72
- }
73
-
74
- function tokenComment(stream, state) {
75
- var maybeEnd = false, ch;
76
- while (ch = stream.next()) {
77
- if (ch == "/" && maybeEnd) {
78
- state.tokenize = null;
79
- break;
80
- }
81
- maybeEnd = (ch == "*");
82
- }
83
- return "comment";
84
- }
85
-
86
- function Context(indented, column, type, align, prev) {
87
- this.indented = indented;
88
- this.column = column;
89
- this.type = type;
90
- this.align = align;
91
- this.prev = prev;
92
- }
93
- function pushContext(state, col, type) {
94
- var indent = state.indented;
95
- if (state.context && state.context.type == "statement")
96
- indent = state.context.indented;
97
- return state.context = new Context(indent, col, type, null, state.context);
98
- }
99
- function popContext(state) {
100
- var t = state.context.type;
101
- if (t == ")" || t == "]" || t == "}")
102
- state.indented = state.context.indented;
103
- return state.context = state.context.prev;
104
- }
105
-
106
- // Interface
107
-
108
- return {
109
- startState: function(basecolumn) {
110
- return {
111
- tokenize: null,
112
- context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
113
- indented: 0,
114
- startOfLine: true
115
- };
116
- },
117
-
118
- token: function(stream, state) {
119
- var ctx = state.context;
120
- if (stream.sol()) {
121
- if (ctx.align == null) ctx.align = false;
122
- state.indented = stream.indentation();
123
- state.startOfLine = true;
124
- }
125
- if (stream.eatSpace()) return null;
126
- curPunc = null;
127
- var style = (state.tokenize || tokenBase)(stream, state);
128
- if (style == "comment" || style == "meta") return style;
129
- if (ctx.align == null) ctx.align = true;
130
-
131
- if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
132
- else if (curPunc == "{") pushContext(state, stream.column(), "}");
133
- else if (curPunc == "[") pushContext(state, stream.column(), "]");
134
- else if (curPunc == "(") pushContext(state, stream.column(), ")");
135
- else if (curPunc == "}") {
136
- while (ctx.type == "statement") ctx = popContext(state);
137
- if (ctx.type == "}") ctx = popContext(state);
138
- while (ctx.type == "statement") ctx = popContext(state);
139
- }
140
- else if (curPunc == ctx.type) popContext(state);
141
- else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
142
- pushContext(state, stream.column(), "statement");
143
- state.startOfLine = false;
144
- return style;
145
- },
146
-
147
- indent: function(state, textAfter) {
148
- if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
149
- var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
150
- if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
151
- var closing = firstChar == ctx.type;
152
- if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
153
- else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
154
- else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
155
- else return ctx.indented + (closing ? 0 : indentUnit);
156
- },
157
-
158
- electricChars: "{}",
159
- blockCommentStart: "/*",
160
- blockCommentEnd: "*/",
161
- lineComment: "//",
162
- fold: "brace"
163
- };
164
- });
165
-
166
- (function() {
167
- function words(str) {
168
- var obj = {}, words = str.split(" ");
169
- for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
170
- return obj;
171
- }
172
- var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
173
- "double static else struct entry switch extern typedef float union for unsigned " +
174
- "goto while enum void const signed volatile";
175
-
176
- function cppHook(stream, state) {
177
- if (!state.startOfLine) return false;
178
- for (;;) {
179
- if (stream.skipTo("\\")) {
180
- stream.next();
181
- if (stream.eol()) {
182
- state.tokenize = cppHook;
183
- break;
184
- }
185
- } else {
186
- stream.skipToEnd();
187
- state.tokenize = null;
188
- break;
189
- }
190
- }
191
- return "meta";
192
- }
193
-
194
- // C#-style strings where "" escapes a quote.
195
- function tokenAtString(stream, state) {
196
- var next;
197
- while ((next = stream.next()) != null) {
198
- if (next == '"' && !stream.eat('"')) {
199
- state.tokenize = null;
200
- break;
201
- }
202
- }
203
- return "string";
204
- }
205
-
206
- function mimes(ms, mode) {
207
- for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode);
208
- }
209
-
210
- mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], {
211
- name: "clike",
212
- keywords: words(cKeywords),
213
- blockKeywords: words("case do else for if switch while struct"),
214
- atoms: words("null"),
215
- hooks: {"#": cppHook}
216
- });
217
- mimes(["text/x-c++src", "text/x-c++hdr"], {
218
- name: "clike",
219
- keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
220
- "static_cast typeid catch operator template typename class friend private " +
221
- "this using const_cast inline public throw virtual delete mutable protected " +
222
- "wchar_t"),
223
- blockKeywords: words("catch class do else finally for if struct switch try while"),
224
- atoms: words("true false null"),
225
- hooks: {"#": cppHook}
226
- });
227
- CodeMirror.defineMIME("text/x-java", {
228
- name: "clike",
229
- keywords: words("abstract assert boolean break byte case catch char class const continue default " +
230
- "do double else enum extends final finally float for goto if implements import " +
231
- "instanceof int interface long native new package private protected public " +
232
- "return short static strictfp super switch synchronized this throw throws transient " +
233
- "try void volatile while"),
234
- blockKeywords: words("catch class do else finally for if switch try while"),
235
- atoms: words("true false null"),
236
- hooks: {
237
- "@": function(stream) {
238
- stream.eatWhile(/[\w\$_]/);
239
- return "meta";
240
- }
241
- }
242
- });
243
- CodeMirror.defineMIME("text/x-csharp", {
244
- name: "clike",
245
- keywords: words("abstract as base break case catch checked class const continue" +
246
- " default delegate do else enum event explicit extern finally fixed for" +
247
- " foreach goto if implicit in interface internal is lock namespace new" +
248
- " operator out override params private protected public readonly ref return sealed" +
249
- " sizeof stackalloc static struct switch this throw try typeof unchecked" +
250
- " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
251
- " global group into join let orderby partial remove select set value var yield"),
252
- blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
253
- builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
254
- " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
255
- " UInt64 bool byte char decimal double short int long object" +
256
- " sbyte float string ushort uint ulong"),
257
- atoms: words("true false null"),
258
- hooks: {
259
- "@": function(stream, state) {
260
- if (stream.eat('"')) {
261
- state.tokenize = tokenAtString;
262
- return tokenAtString(stream, state);
263
- }
264
- stream.eatWhile(/[\w\$_]/);
265
- return "meta";
266
- }
267
- }
268
- });
269
- CodeMirror.defineMIME("text/x-scala", {
270
- name: "clike",
271
- keywords: words(
272
-
273
- /* scala */
274
- "abstract case catch class def do else extends false final finally for forSome if " +
275
- "implicit import lazy match new null object override package private protected return " +
276
- "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
277
- "<% >: # @ " +
278
-
279
- /* package scala */
280
- "assert assume require print println printf readLine readBoolean readByte readShort " +
281
- "readChar readInt readLong readFloat readDouble " +
282
-
283
- "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
284
- "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
285
- "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
286
- "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
287
- "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
288
-
289
- /* package java.lang */
290
- "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
291
- "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
292
- "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
293
- "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
294
-
295
-
296
- ),
297
- blockKeywords: words("catch class do else finally for forSome if match switch try while"),
298
- atoms: words("true false null"),
299
- hooks: {
300
- "@": function(stream) {
301
- stream.eatWhile(/[\w\$_]/);
302
- return "meta";
303
- }
304
- }
305
- });
306
- mimes(["x-shader/x-vertex", "x-shader/x-fragment"], {
307
- name: "clike",
308
- keywords: words("float int bool void " +
309
- "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
310
- "mat2 mat3 mat4 " +
311
- "sampler1D sampler2D sampler3D samplerCube " +
312
- "sampler1DShadow sampler2DShadow" +
313
- "const attribute uniform varying " +
314
- "break continue discard return " +
315
- "for while do if else struct " +
316
- "in out inout"),
317
- blockKeywords: words("for while do if else struct"),
318
- builtin: words("radians degrees sin cos tan asin acos atan " +
319
- "pow exp log exp2 sqrt inversesqrt " +
320
- "abs sign floor ceil fract mod min max clamp mix step smootstep " +
321
- "length distance dot cross normalize ftransform faceforward " +
322
- "reflect refract matrixCompMult " +
323
- "lessThan lessThanEqual greaterThan greaterThanEqual " +
324
- "equal notEqual any all not " +
325
- "texture1D texture1DProj texture1DLod texture1DProjLod " +
326
- "texture2D texture2DProj texture2DLod texture2DProjLod " +
327
- "texture3D texture3DProj texture3DLod texture3DProjLod " +
328
- "textureCube textureCubeLod " +
329
- "shadow1D shadow2D shadow1DProj shadow2DProj " +
330
- "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
331
- "dFdx dFdy fwidth " +
332
- "noise1 noise2 noise3 noise4"),
333
- atoms: words("true false " +
334
- "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
335
- "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
336
- "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
337
- "gl_FogCoord " +
338
- "gl_Position gl_PointSize gl_ClipVertex " +
339
- "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
340
- "gl_TexCoord gl_FogFragCoord " +
341
- "gl_FragCoord gl_FrontFacing " +
342
- "gl_FragColor gl_FragData gl_FragDepth " +
343
- "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
344
- "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
345
- "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
346
- "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
347
- "gl_ProjectionMatrixInverseTranspose " +
348
- "gl_ModelViewProjectionMatrixInverseTranspose " +
349
- "gl_TextureMatrixInverseTranspose " +
350
- "gl_NormalScale gl_DepthRange gl_ClipPlane " +
351
- "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
352
- "gl_FrontLightModelProduct gl_BackLightModelProduct " +
353
- "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
354
- "gl_FogParameters " +
355
- "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
356
- "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
357
- "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
358
- "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
359
- "gl_MaxDrawBuffers"),
360
- hooks: {"#": cppHook}
361
- });
362
- }());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codemirror/mode/php.js DELETED
@@ -1,132 +0,0 @@
1
- (function() {
2
- function keywords(str) {
3
- var obj = {}, words = str.split(" ");
4
- for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5
- return obj;
6
- }
7
- function heredoc(delim) {
8
- return function(stream, state) {
9
- if (stream.match(delim)) state.tokenize = null;
10
- else stream.skipToEnd();
11
- return "string";
12
- };
13
- }
14
- var phpConfig = {
15
- name: "clike",
16
- keywords: keywords("abstract and array as break case catch class clone const continue declare default " +
17
- "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +
18
- "for foreach function global goto if implements interface instanceof namespace " +
19
- "new or private protected public static switch throw trait try use var while xor " +
20
- "die echo empty exit eval include include_once isset list require require_once return " +
21
- "print unset __halt_compiler self static parent"),
22
- blockKeywords: keywords("catch do else elseif for foreach if switch try while"),
23
- atoms: keywords("true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__"),
24
- builtin: keywords("func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport echo print global static exit array empty eval isset unset die include require include_once require_once"),
25
- multiLineStrings: true,
26
- hooks: {
27
- "$": function(stream) {
28
- stream.eatWhile(/[\w\$_]/);
29
- return "variable-2";
30
- },
31
- "<": function(stream, state) {
32
- if (stream.match(/<</)) {
33
- stream.eatWhile(/[\w\.]/);
34
- state.tokenize = heredoc(stream.current().slice(3));
35
- return state.tokenize(stream, state);
36
- }
37
- return false;
38
- },
39
- "#": function(stream) {
40
- while (!stream.eol() && !stream.match("?>", false)) stream.next();
41
- return "comment";
42
- },
43
- "/": function(stream) {
44
- if (stream.eat("/")) {
45
- while (!stream.eol() && !stream.match("?>", false)) stream.next();
46
- return "comment";
47
- }
48
- return false;
49
- }
50
- }
51
- };
52
-
53
- CodeMirror.defineMode("php", function(config, parserConfig) {
54
- var htmlMode = CodeMirror.getMode(config, "text/html");
55
- var phpMode = CodeMirror.getMode(config, phpConfig);
56
-
57
- function dispatch(stream, state) {
58
- var isPHP = state.curMode == phpMode;
59
- if (stream.sol() && state.pending != '"') state.pending = null;
60
- if (!isPHP) {
61
- if (stream.match(/^<\?\w*/)) {
62
- state.curMode = phpMode;
63
- state.curState = state.php;
64
- return "meta";
65
- }
66
- if (state.pending == '"') {
67
- while (!stream.eol() && stream.next() != '"') {}
68
- var style = "string";
69
- } else if (state.pending && stream.pos < state.pending.end) {
70
- stream.pos = state.pending.end;
71
- var style = state.pending.style;
72
- } else {
73
- var style = htmlMode.token(stream, state.curState);
74
- }
75
- state.pending = null;
76
- var cur = stream.current(), openPHP = cur.search(/<\?/);
77
- if (openPHP != -1) {
78
- if (style == "string" && /\"$/.test(cur) && !/\?>/.test(cur)) state.pending = '"';
79
- else state.pending = {end: stream.pos, style: style};
80
- stream.backUp(cur.length - openPHP);
81
- }
82
- return style;
83
- } else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
84
- state.curMode = htmlMode;
85
- state.curState = state.html;
86
- return "meta";
87
- } else {
88
- return phpMode.token(stream, state.curState);
89
- }
90
- }
91
-
92
- return {
93
- startState: function() {
94
- var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
95
- return {html: html,
96
- php: php,
97
- curMode: parserConfig.startOpen ? phpMode : htmlMode,
98
- curState: parserConfig.startOpen ? php : html,
99
- pending: null};
100
- },
101
-
102
- copyState: function(state) {
103
- var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
104
- php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
105
- if (state.curMode == htmlMode) cur = htmlNew;
106
- else cur = phpNew;
107
- return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
108
- pending: state.pending};
109
- },
110
-
111
- token: dispatch,
112
-
113
- indent: function(state, textAfter) {
114
- if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) ||
115
- (state.curMode == phpMode && /^\?>/.test(textAfter)))
116
- return htmlMode.indent(state.html, textAfter);
117
- return state.curMode.indent(state.curState, textAfter);
118
- },
119
-
120
- electricChars: "/{}:",
121
- blockCommentStart: "/*",
122
- blockCommentEnd: "*/",
123
- lineComment: "//",
124
-
125
- innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
126
- };
127
- }, "htmlmixed", "clike");
128
-
129
- CodeMirror.defineMIME("application/x-httpd-php", "php");
130
- CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
131
- CodeMirror.defineMIME("text/x-php", phpConfig);
132
- })();