Unlimited Elements For Elementor (Free Widgets, Addons, Templates) - Version 1.4.67

Version Description

Download this release

Release Info

Developer unitecms
Plugin Icon 128x128 Unlimited Elements For Elementor (Free Widgets, Addons, Templates)
Version 1.4.67
Comparing to
See all releases

Code changes from version 1.4.65 to 1.4.67

css/unitecreator_styles.css CHANGED
@@ -508,6 +508,11 @@
508
  right:46px;
509
  }
510
 
 
 
 
 
 
511
  .uc-attr-list-sections__icon-move{
512
  position:absolute;
513
  left:-16px;
508
  right:46px;
509
  }
510
 
511
+ #cat_general_general .uc-attr-list-sections__icon-copy{
512
+ right:26px;
513
+ }
514
+
515
+
516
  .uc-attr-list-sections__icon-move{
517
  position:absolute;
518
  left:-16px;
images/preview_template_elementor.jpg DELETED
Binary file
inc_php/unitecreator_actions.class.php CHANGED
@@ -113,7 +113,7 @@ class UniteCreatorActions{
113
 
114
  case "remove_category":
115
  $response = $categories->removeFromData($data);
116
-
117
  HelperUC::ajaxResponseSuccess(esc_html__("The category deleted successfully","unlimited-elements-for-elementor"),$response);
118
  break;
119
  case "update_category":
@@ -427,6 +427,13 @@ class UniteCreatorActions{
427
 
428
  HelperUC::ajaxResponseSuccess(esc_html__("Settings Saved", "unlimited-elements-for-elementor"));
429
 
 
 
 
 
 
 
 
430
  break;
431
  case "get_posts_list_forselect":
432
 
@@ -442,6 +449,14 @@ class UniteCreatorActions{
442
  HelperUC::ajaxResponseData(array("select2_data"=>$arrData));
443
 
444
  break;
 
 
 
 
 
 
 
 
445
  case "get_post_child_params":
446
 
447
  $response = $operations->getPostAttributesFromData($data);
113
 
114
  case "remove_category":
115
  $response = $categories->removeFromData($data);
116
+
117
  HelperUC::ajaxResponseSuccess(esc_html__("The category deleted successfully","unlimited-elements-for-elementor"),$response);
118
  break;
119
  case "update_category":
427
 
428
  HelperUC::ajaxResponseSuccess(esc_html__("Settings Saved", "unlimited-elements-for-elementor"));
429
 
430
+ break;
431
+ case "get_terms_list_forselect":
432
+
433
+ $arrTermsList = $operations->getTermsListForSelectFromData($data);
434
+
435
+ HelperUC::ajaxResponseData($arrTermsList);
436
+
437
  break;
438
  case "get_posts_list_forselect":
439
 
449
  HelperUC::ajaxResponseData(array("select2_data"=>$arrData));
450
 
451
  break;
452
+ case "get_select2_terms_titles":
453
+
454
+ $arrData = $operations->getSelect2TermsTitles($data);
455
+
456
+ HelperUC::ajaxResponseData(array("select2_data"=>$arrData));
457
+
458
+ break;
459
+
460
  case "get_post_child_params":
461
 
462
  $response = $operations->getPostAttributesFromData($data);
inc_php/unitecreator_addons.class.php CHANGED
@@ -720,6 +720,8 @@ class UniteCreatorAddons extends UniteElementsBaseUC{
720
  foreach($arrAddons as $key=>$itemID)
721
  $arrAddons[$key] = (int)$itemID;
722
 
 
 
723
  $strAddonIDs = implode(",",$arrAddons);
724
  $this->db->delete(GlobalsUC::$table_addons,"id in($strAddonIDs)");
725
  }
@@ -1007,8 +1009,8 @@ class UniteCreatorAddons extends UniteElementsBaseUC{
1007
  public function deleteAddonFromData($data){
1008
 
1009
  $addonID = UniteFunctionsUC::getVal($data, "addonID");
1010
- UniteFunctionsUC::validateNotEmpty($addonID, "Addon ID");
1011
-
1012
  $this->db->delete(GlobalsUC::$table_addons, "id=$addonID");
1013
 
1014
  }
@@ -1093,6 +1095,7 @@ class UniteCreatorAddons extends UniteElementsBaseUC{
1093
 
1094
  $addonsIDs = UniteFunctionsUC::getVal($data, "arrAddonsIDs");
1095
 
 
1096
  if(HelperUC::isLayoutAddonType($type) == false){ //delete addons
1097
  $this->deleteAddons($addonsIDs);
1098
  }
720
  foreach($arrAddons as $key=>$itemID)
721
  $arrAddons[$key] = (int)$itemID;
722
 
723
+ UniteProviderFunctionsUC::doAction("uc_before_delete_widgets", $arrAddons);
724
+
725
  $strAddonIDs = implode(",",$arrAddons);
726
  $this->db->delete(GlobalsUC::$table_addons,"id in($strAddonIDs)");
727
  }
1009
  public function deleteAddonFromData($data){
1010
 
1011
  $addonID = UniteFunctionsUC::getVal($data, "addonID");
1012
+ UniteFunctionsUC::validateNotEmpty($addonID, "Widget ID");
1013
+
1014
  $this->db->delete(GlobalsUC::$table_addons, "id=$addonID");
1015
 
1016
  }
1095
 
1096
  $addonsIDs = UniteFunctionsUC::getVal($data, "arrAddonsIDs");
1097
 
1098
+
1099
  if(HelperUC::isLayoutAddonType($type) == false){ //delete addons
1100
  $this->deleteAddons($addonsIDs);
1101
  }
inc_php/unitecreator_filters_process.class.php ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Unlimited Elements
4
+ * @author UniteCMS.net
5
+ * @copyright (C) 2017 Unite CMS, All Rights Reserved.
6
+ * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
7
+ * */
8
+ defined('UNLIMITED_ELEMENTS_INC') or die('Restricted access');
9
+
10
+ class UniteCreatorFiltersProcess{
11
+
12
+ private static $filters = null;
13
+
14
+ /**
15
+ * get request array
16
+ */
17
+ private function getArrRequest(){
18
+
19
+ $request = $_GET;
20
+ if(!empty($_POST))
21
+ $request = array_merge($request, $_POST);
22
+
23
+ return($request);
24
+ }
25
+
26
+ /**
27
+ * add single category filter
28
+ */
29
+ private function addSingleCategoryFilter($slug){
30
+
31
+ $slug = trim($slug);
32
+
33
+ $term = get_term_by("slug", $slug, "category");
34
+
35
+ $termID = "0";
36
+ if(!empty($term))
37
+ $termID = $term->term_id;
38
+
39
+ self::$filters["category"] = $termID;
40
+
41
+ }
42
+
43
+
44
+ /**
45
+ * get filters arguments
46
+ */
47
+ public function getRequestFilters(){
48
+
49
+ if(self::$filters !== null)
50
+ return(self::$filters);
51
+
52
+ self::$filters = array();
53
+
54
+ $request = $this->getArrRequest();
55
+
56
+ self::$filters = array();
57
+
58
+ foreach($request as $key=>$value){
59
+
60
+ switch($key){
61
+ case "filter-category":
62
+
63
+ $this->addSingleCategoryFilter($value);
64
+
65
+ break;
66
+ }
67
+
68
+ }
69
+
70
+
71
+ return(self::$filters);
72
+ }
73
+
74
+
75
+ /**
76
+ * get fitler url from the given slugs
77
+ */
78
+ private function getUrlFilter_term($term, $taxonomyName){
79
+
80
+ $key = "filter-term";
81
+
82
+ $taxPrefix = $taxonomyName."--";
83
+
84
+ if($taxonomyName == "category"){
85
+ $taxPrefix = "";
86
+ $key="filter-category";
87
+ }
88
+
89
+ $slug = $term->slug;
90
+
91
+ $value = $taxPrefix.$slug;
92
+
93
+ $urlAddition = "{$key}=".urlencode($value);
94
+
95
+ $urlCurrent = GlobalsUC::$current_page_url;
96
+
97
+ $urlCurrent = UniteFunctionsUC::removePathEndingSlash($urlCurrent);
98
+
99
+ $url = UniteFunctionsUC::addUrlParams($urlCurrent, $urlAddition);
100
+
101
+ return($url);
102
+ }
103
+
104
+ /**
105
+ * check if the term is acrive
106
+ */
107
+ private function isTermActive($term, $arrActiveFilters = null){
108
+
109
+ if(empty($term))
110
+ return(false);
111
+
112
+ if($arrActiveFilters === null)
113
+ $arrActiveFilters = $this->getRequestFilters();
114
+
115
+ if(empty($arrActiveFilters))
116
+ return(false);
117
+
118
+ $taxonomy = $term->taxonomy;
119
+
120
+ $selectedTermID = UniteFunctionsUC::getVal($arrActiveFilters, $taxonomy);
121
+
122
+ if(empty($selectedTermID))
123
+ return(false);
124
+
125
+ if($selectedTermID === $term->term_id)
126
+ return(true);
127
+
128
+ return(false);
129
+ }
130
+
131
+ /**
132
+ * put filters by tabs
133
+ */
134
+ public function putFiltersTabs(){
135
+
136
+ $arrActiveFilters = self::getRequestFilters();
137
+
138
+ $taxonomy = "category";
139
+
140
+ $terms = get_terms($taxonomy);
141
+
142
+ ?>
143
+
144
+ <style>
145
+ .uc-filters{
146
+ list-style:none;
147
+ margin:0px;
148
+ padding:0px;
149
+ display:flex;
150
+ box-sizing:border-box;
151
+ margin-top:20px;
152
+ margin-bottom:20px;
153
+ }
154
+ .uc-filters li{
155
+ margin:0px;
156
+ padding:0px;
157
+ }
158
+ .uc-filters li a{
159
+ padding:10px;
160
+ border:1px solid black;
161
+ }
162
+ .uc-filters li.active a{
163
+ background-color:gold;
164
+ }
165
+ </style>
166
+
167
+ <ul class="uc-filters">
168
+ <?php
169
+ $isFirst = true;
170
+ foreach($terms as $term):
171
+
172
+ $isTermActive = $this->isTermActive($term, $arrActiveFilters);
173
+
174
+ $classActive = "";
175
+
176
+ $termID = $term->term_id;
177
+ $name = $term->name;
178
+ $slug = $term->slug;
179
+
180
+ $urlFilter = $this->getUrlFilter_term($term, $taxonomy);
181
+
182
+ if($isTermActive == true)
183
+ $classActive = " active";
184
+
185
+ $isFirst = false;
186
+ ?>
187
+ <li class="<?php echo $classActive?>">
188
+ <a href="<?php echo $urlFilter?>"><?php echo $name?></a>
189
+ </li>
190
+
191
+
192
+ <?php endforeach?>
193
+ </ul>
194
+
195
+
196
+ <?php
197
+
198
+ }
199
+
200
+
201
+
202
+ }
inc_php/unitecreator_output.class.php CHANGED
@@ -1183,6 +1183,9 @@ class UniteCreatorOutputWork extends HtmlOutputBaseUC{
1183
  */
1184
  private function modifyDataArrayForShow($arrData){
1185
 
 
 
 
1186
  $arrDataNew = array();
1187
  foreach($arrData as $key=>$value){
1188
 
@@ -1212,10 +1215,14 @@ class UniteCreatorOutputWork extends HtmlOutputBaseUC{
1212
  foreach($arrItemData as $item){
1213
 
1214
  $item = UniteFunctionsUC::getVal($item, "item");
1215
- $item = UniteFunctionsUC::getArrFirstValue($item);
1216
 
1217
- $item = $this->modifyDataArrayForShow($item);
1218
-
 
 
 
 
 
1219
  $arrItemsForShow[] = $item;
1220
  }
1221
 
@@ -1354,9 +1361,16 @@ class UniteCreatorOutputWork extends HtmlOutputBaseUC{
1354
  //add html
1355
 
1356
  $output .= "\n\n ".$html;
1357
-
 
 
 
 
 
 
 
1358
  //output js
1359
- if(!empty($js)){
1360
 
1361
  $title = $this->addon->getTitle();
1362
 
@@ -1372,7 +1386,6 @@ class UniteCreatorOutputWork extends HtmlOutputBaseUC{
1372
  $wrapStart = UniteFunctionsUC::getVal($params, "wrap_js_start");
1373
  $wrapEnd = UniteFunctionsUC::getVal($params, "wrap_js_end");
1374
 
1375
-
1376
  $output .= "\n\n <script type=\"text/javascript\">";
1377
 
1378
  if(!empty($wrapStart))
@@ -1422,7 +1435,7 @@ class UniteCreatorOutputWork extends HtmlOutputBaseUC{
1422
  return($this->cacheConstants);
1423
 
1424
  $data = array();
1425
-
1426
  $prefix = "ucid";
1427
  if($this->isInited)
1428
  $prefix = "uc_".$this->addon->getName();
1183
  */
1184
  private function modifyDataArrayForShow($arrData){
1185
 
1186
+ if(is_array($arrData) == false)
1187
+ return($arrData);
1188
+
1189
  $arrDataNew = array();
1190
  foreach($arrData as $key=>$value){
1191
 
1215
  foreach($arrItemData as $item){
1216
 
1217
  $item = UniteFunctionsUC::getVal($item, "item");
 
1218
 
1219
+ $itemFirstValue = UniteFunctionsUC::getArrFirstValue($item);
1220
+
1221
+ if(is_array($itemFirstValue))
1222
+ $item = $this->modifyDataArrayForShow($itemFirstValue);
1223
+ else
1224
+ $item = $this->modifyDataArrayForShow($item);
1225
+
1226
  $arrItemsForShow[] = $item;
1227
  }
1228
 
1361
  //add html
1362
 
1363
  $output .= "\n\n ".$html;
1364
+
1365
+ $isOutputJs = false;
1366
+ if(!empty($js))
1367
+ $isOutputJs = true;
1368
+
1369
+ if(isset($params["wrap_js_start"]) || isset($params["wrap_js_timeout"]))
1370
+ $isOutputJs = true;
1371
+
1372
  //output js
1373
+ if($isOutputJs == true){
1374
 
1375
  $title = $this->addon->getTitle();
1376
 
1386
  $wrapStart = UniteFunctionsUC::getVal($params, "wrap_js_start");
1387
  $wrapEnd = UniteFunctionsUC::getVal($params, "wrap_js_end");
1388
 
 
1389
  $output .= "\n\n <script type=\"text/javascript\">";
1390
 
1391
  if(!empty($wrapStart))
1435
  return($this->cacheConstants);
1436
 
1437
  $data = array();
1438
+
1439
  $prefix = "ucid";
1440
  if($this->isInited)
1441
  $prefix = "uc_".$this->addon->getName();
inc_php/unitecreator_params_editor.class.php CHANGED
@@ -107,7 +107,9 @@ class UniteCreatorParamsEditor{
107
  <span class="uc-attr-list__section-numitems"></span>
108
 
109
  <i class="uc-attr-list-sections__icon-edit fas fa-pen uc-hide-on-movemode" title="<?php _e("Edit Section", "unlimited-elements-for-elementor")?>"></i>
110
-
 
 
111
  <i class="uc-attr-list-sections__icon-move fas fa-bullseye uc-show-on-movemode" title="<?php _e("Move Here", "unlimited-elements-for-elementor")?>"></i>
112
 
113
  </li>
@@ -153,11 +155,11 @@ class UniteCreatorParamsEditor{
153
 
154
  <div class="uc-attr-cats-copied-section__links">
155
 
156
- <a id="uc_attr_cats_copied_section_paste_content" href="javascript:void(0)" class="uc-attr-cats-copied-section__link" title="<?php _e("Paste section in content tab")?>">
157
  <?php _e("to content","unlimited-elements-for-elementor")?>
158
  </a>
159
 
160
- <a id="uc_attr_cats_copied_section_paste_style" href="javascript:void(0)" class="uc-attr-cats-copied-section__link" title="<?php _e("Paste section in style tab")?>">
161
  <?php _e("to style","unlimited-elements-for-elementor")?>
162
  </a>
163
 
107
  <span class="uc-attr-list__section-numitems"></span>
108
 
109
  <i class="uc-attr-list-sections__icon-edit fas fa-pen uc-hide-on-movemode" title="<?php _e("Edit Section", "unlimited-elements-for-elementor")?>"></i>
110
+
111
+ <i class="uc-attr-list-sections__icon-copy fas fa-copy uc-hide-on-movemode" title="<?php _e("Copy Section", "unlimited-elements-for-elementor")?>"></i>
112
+
113
  <i class="uc-attr-list-sections__icon-move fas fa-bullseye uc-show-on-movemode" title="<?php _e("Move Here", "unlimited-elements-for-elementor")?>"></i>
114
 
115
  </li>
155
 
156
  <div class="uc-attr-cats-copied-section__links">
157
 
158
+ <a id="uc_attr_cats_copied_section_paste_content" href="javascript:void(0)" data-tab="content" class="uc-attr-cats-copied-section__link" title="<?php _e("Paste section in content tab")?>">
159
  <?php _e("to content","unlimited-elements-for-elementor")?>
160
  </a>
161
 
162
+ <a id="uc_attr_cats_copied_section_paste_style" href="javascript:void(0)" class="uc-attr-cats-copied-section__link" data-tab="style" title="<?php _e("Paste section in style tab")?>">
163
  <?php _e("to style","unlimited-elements-for-elementor")?>
164
  </a>
165
 
inc_php/unitecreator_params_processor.class.php CHANGED
@@ -1697,5 +1697,4 @@ class UniteCreatorParamsProcessorWork{
1697
 
1698
 
1699
 
1700
-
1701
  }
1697
 
1698
 
1699
 
 
1700
  }
inc_php/unitecreator_settings.class.php CHANGED
@@ -71,6 +71,13 @@ class UniteCreatorSettingsWork extends UniteSettingsAdvancedUC{
71
  if(!empty($elementorCondition))
72
  $param["elementor_condition"] = $elementorCondition;
73
 
 
 
 
 
 
 
 
74
  $labelBlock = UniteFunctionsUC::getVal($setting, "label_block"); //label block
75
  if(!empty($labelBlock))
76
  $param["label_block"] = $labelBlock;
71
  if(!empty($elementorCondition))
72
  $param["elementor_condition"] = $elementorCondition;
73
 
74
+ $addDynamic = UniteFunctionsUC::getVal($setting, "add_dynamic");
75
+ $addDynamic = UniteFunctionsUC::strToBool($addDynamic);
76
+
77
+ if($addDynamic)
78
+ $param["add_dynamic"] = true;
79
+
80
+
81
  $labelBlock = UniteFunctionsUC::getVal($setting, "label_block"); //label block
82
  if(!empty($labelBlock))
83
  $param["label_block"] = $labelBlock;
inc_php/unitecreator_template_engine.class.php CHANGED
@@ -627,9 +627,11 @@ class UniteCreatorTemplateEngineWork{
627
  if(empty($price))
628
  return($price);
629
 
 
 
630
  $price = number_format($price, "2");
631
- $price = rtrim($price,"0");
632
- $price = rtrim($price,".");
633
 
634
  return($price);
635
  }
@@ -637,15 +639,72 @@ class UniteCreatorTemplateEngineWork{
637
  /**
638
  * get listing item data
639
  */
640
- function getListingItemData(){
641
 
642
- $data = get_queried_object();
643
 
644
  $data = UniteFunctionsUC::convertStdClassToArray($data);
645
 
646
  return($data);
647
  }
648
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
649
 
650
  /**
651
  * add extra functions to twig
@@ -680,6 +739,8 @@ class UniteCreatorTemplateEngineWork{
680
  $getPostData = new Twig_SimpleFunction('getPostData', array($this,"getPostData"));
681
  $putPagination = new Twig_SimpleFunction('putPagination', array($this,"putPagination"));
682
 
 
 
683
  $printVar = new Twig_SimpleFunction('printVar', array($this,"printVar"));
684
  $printJsonVar = new Twig_SimpleFunction('printJsonVar', array($this,"printJsonVar"));
685
  $printJsonHtmlData = new Twig_SimpleFunction('printJsonHtmlData', array($this,"printJsonHtmlData"));
@@ -704,9 +765,11 @@ class UniteCreatorTemplateEngineWork{
704
  $filterWPAutop = new Twig_SimpleFilter("wpautop", array($this, "filterWPAutop"));
705
  $filterUCDate = new Twig_SimpleFilter("ucdate", array($this, "filterUCDate"));
706
  $filterPriceNumberFormat = new Twig_SimpleFilter("price_number_format", array($this, "filterPriceNumberFormat"));
 
 
707
 
708
 
709
- //add extra functions
710
  $this->twig->addFunction($putItemsFunction);
711
  $this->twig->addFunction($putItemsFunction2);
712
  $this->twig->addFunction($putCssItemsFunction);
@@ -746,6 +809,11 @@ class UniteCreatorTemplateEngineWork{
746
  $this->twig->addFunction($getTermCustomFields);
747
  $this->twig->addFunction($putItemsJsonFunction);
748
  $this->twig->addFunction($getItems);
 
 
 
 
 
749
 
750
  //add filters
751
  $this->twig->addFilter($filterTruncate);
627
  if(empty($price))
628
  return($price);
629
 
630
+ $type = getType($price);
631
+
632
  $price = number_format($price, "2");
633
+
634
+ $price = str_replace(".00", "", $price);
635
 
636
  return($price);
637
  }
639
  /**
640
  * get listing item data
641
  */
642
+ public function getListingItemData($type = null, $defaultObjectID = null){
643
 
644
+ $data = UniteFunctionsWPUC::getQueriedObject($type, $defaultObjectID);
645
 
646
  $data = UniteFunctionsUC::convertStdClassToArray($data);
647
 
648
  return($data);
649
  }
650
 
651
+ /**
652
+ * put post image attributes
653
+ */
654
+ public function putPostImageAttributes($arrPost, $thumbName, $isPutPlaceholder = false, $urlPlaceholder = ""){
655
+
656
+ if(empty($arrPost))
657
+ UniteFunctionsUC::throwError("No post found :(");
658
+
659
+ $attributes = "";
660
+
661
+ if(isset($arrPost[$thumbName]) == false)
662
+ $thumbName = "image";
663
+
664
+ //dmp("put dummy placeholder");exit();
665
+
666
+ if(!empty($arrPost[$thumbName])){
667
+
668
+ $urlImage = $arrPost[$thumbName];
669
+ $width = UniteFunctionsUC::getVal($arrPost, $thumbName."_width");
670
+ $height = UniteFunctionsUC::getVal($arrPost, $thumbName."_height");
671
+
672
+ $attributes .= "src=\"{$urlImage}\"";
673
+ if(!empty($width) && !empty($height))
674
+ $attributes .= " width=\"{$width}\" height=\"{$height}\"";
675
+
676
+ return($attributes);
677
+ }
678
+
679
+ $isPutPlaceholder = UniteFunctionsUC::strToBool($isPutPlaceholder);
680
+
681
+ if($isPutPlaceholder == false)
682
+ return("");
683
+
684
+ //put placeholder
685
+
686
+ if(!empty($urlPlaceholder)){
687
+
688
+ dmP("put built in placeholder");
689
+ exit();
690
+ }
691
+
692
+
693
+ dmp($arrPost);
694
+ exit();
695
+
696
+ }
697
+
698
+ /**
699
+ * put test html
700
+ */
701
+ public function putTestHTML(){
702
+
703
+ $objFilters = new UniteCreatorFiltersProcess();
704
+
705
+ $objFilters->putFiltersTabs();
706
+ }
707
+
708
 
709
  /**
710
  * add extra functions to twig
739
  $getPostData = new Twig_SimpleFunction('getPostData', array($this,"getPostData"));
740
  $putPagination = new Twig_SimpleFunction('putPagination', array($this,"putPagination"));
741
 
742
+ $putPostImageAttributes = new Twig_SimpleFunction('putPostImageAttributes', array($this,"putPostImageAttributes"));
743
+
744
  $printVar = new Twig_SimpleFunction('printVar', array($this,"printVar"));
745
  $printJsonVar = new Twig_SimpleFunction('printJsonVar', array($this,"printJsonVar"));
746
  $printJsonHtmlData = new Twig_SimpleFunction('printJsonHtmlData', array($this,"printJsonHtmlData"));
765
  $filterWPAutop = new Twig_SimpleFilter("wpautop", array($this, "filterWPAutop"));
766
  $filterUCDate = new Twig_SimpleFilter("ucdate", array($this, "filterUCDate"));
767
  $filterPriceNumberFormat = new Twig_SimpleFilter("price_number_format", array($this, "filterPriceNumberFormat"));
768
+
769
+ $putTestHtml = new Twig_SimpleFunction('putTestHTML', array($this,"putTestHTML"));
770
 
771
 
772
+ //add extra functions
773
  $this->twig->addFunction($putItemsFunction);
774
  $this->twig->addFunction($putItemsFunction2);
775
  $this->twig->addFunction($putCssItemsFunction);
809
  $this->twig->addFunction($getTermCustomFields);
810
  $this->twig->addFunction($putItemsJsonFunction);
811
  $this->twig->addFunction($getItems);
812
+ $this->twig->addFunction($putPostImageAttributes);
813
+
814
+ //test functions
815
+ $this->twig->addFunction($putTestHtml);
816
+
817
 
818
  //add filters
819
  $this->twig->addFilter($filterTruncate);
includes.php CHANGED
@@ -12,7 +12,7 @@ if(!defined('UNLIMITED_ELEMENTS_INC'))
12
  defined('UNLIMITED_ELEMENTS_INC') or die('Restricted access');
13
 
14
  if(!defined("UNLIMITED_ELEMENTS_VERSION"))
15
- define("UNLIMITED_ELEMENTS_VERSION", "1.4.65");
16
 
17
  $currentFile = __FILE__;
18
  $currentFolder = dirname($currentFile);
@@ -84,6 +84,7 @@ require_once $folderIncludesMain . 'unitecreator_dialog_param.class.php';
84
  require_once GlobalsUC::$pathProvider."provider_dialog_param.class.php";
85
  require_once $folderIncludesMain . 'unitecreator_form.class.php';
86
  require_once $folderIncludesMain . 'unitecreator_addon_validator.class.php';
 
87
 
88
  //page builder related
89
 
12
  defined('UNLIMITED_ELEMENTS_INC') or die('Restricted access');
13
 
14
  if(!defined("UNLIMITED_ELEMENTS_VERSION"))
15
+ define("UNLIMITED_ELEMENTS_VERSION", "1.4.67");
16
 
17
  $currentFile = __FILE__;
18
  $currentFolder = dirname($currentFile);
84
  require_once GlobalsUC::$pathProvider."provider_dialog_param.class.php";
85
  require_once $folderIncludesMain . 'unitecreator_form.class.php';
86
  require_once $folderIncludesMain . 'unitecreator_addon_validator.class.php';
87
+ require_once $folderIncludesMain . 'unitecreator_filters_process.class.php';
88
 
89
  //page builder related
90
 
js/admin.js CHANGED
@@ -2211,6 +2211,18 @@ function UniteAdminUC(){
2211
 
2212
  };
2213
 
 
 
 
 
 
 
 
 
 
 
 
 
2214
  this.z_________DATA_FUNCTIONS_______ = function(){};
2215
 
2216
  /**
2211
 
2212
  };
2213
 
2214
+ /**
2215
+ * print time stamp
2216
+ */
2217
+ this.printTimeStamp = function(stamp){
2218
+
2219
+ if(!stamp)
2220
+ var stamp = jQuery.now();
2221
+
2222
+ var date1 = new Date(stamp);
2223
+ trace(date1);
2224
+ }
2225
+
2226
  this.z_________DATA_FUNCTIONS_______ = function(){};
2227
 
2228
  /**
js/codemirror/addon/dialog.css ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .CodeMirror-dialog {
2
+ position: absolute;
3
+ left: 0; right: 0;
4
+ background: inherit;
5
+ z-index: 15;
6
+ padding: .1em .8em;
7
+ overflow: hidden;
8
+ color: inherit;
9
+ }
10
+
11
+ .CodeMirror-dialog-top {
12
+ border-bottom: 1px solid #eee;
13
+ top: 0;
14
+ }
15
+
16
+ .CodeMirror-dialog-bottom {
17
+ border-top: 1px solid #eee;
18
+ bottom: 0;
19
+ }
20
+
21
+ .CodeMirror-dialog input {
22
+ border: none;
23
+ outline: none;
24
+ background: transparent;
25
+ width: 20em;
26
+ color: inherit;
27
+ font-family: monospace;
28
+ }
29
+
30
+ .CodeMirror-dialog button {
31
+ font-size: 70%;
32
+ }
js/codemirror/addon/dialog.js ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: https://codemirror.net/LICENSE
3
+
4
+ // Open simple dialogs on top of an editor. Relies on dialog.css.
5
+
6
+ (function(mod) {
7
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
8
+ mod(require("../../lib/codemirror"));
9
+ else if (typeof define == "function" && define.amd) // AMD
10
+ define(["../../lib/codemirror"], mod);
11
+ else // Plain browser env
12
+ mod(CodeMirror);
13
+ })(function(CodeMirror) {
14
+ function dialogDiv(cm, template, bottom) {
15
+ var wrap = cm.getWrapperElement();
16
+ var dialog;
17
+ dialog = wrap.appendChild(document.createElement("div"));
18
+ if (bottom)
19
+ dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
20
+ else
21
+ dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
22
+
23
+ if (typeof template == "string") {
24
+ dialog.innerHTML = template;
25
+ } else { // Assuming it's a detached DOM element.
26
+ dialog.appendChild(template);
27
+ }
28
+ CodeMirror.addClass(wrap, 'dialog-opened');
29
+ return dialog;
30
+ }
31
+
32
+ function closeNotification(cm, newVal) {
33
+ if (cm.state.currentNotificationClose)
34
+ cm.state.currentNotificationClose();
35
+ cm.state.currentNotificationClose = newVal;
36
+ }
37
+
38
+ CodeMirror.defineExtension("openDialog", function(template, callback, options) {
39
+ if (!options) options = {};
40
+
41
+ closeNotification(this, null);
42
+
43
+ var dialog = dialogDiv(this, template, options.bottom);
44
+ var closed = false, me = this;
45
+ function close(newVal) {
46
+ if (typeof newVal == 'string') {
47
+ inp.value = newVal;
48
+ } else {
49
+ if (closed) return;
50
+ closed = true;
51
+ CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
52
+ dialog.parentNode.removeChild(dialog);
53
+ me.focus();
54
+
55
+ if (options.onClose) options.onClose(dialog);
56
+ }
57
+ }
58
+
59
+ var inp = dialog.getElementsByTagName("input")[0], button;
60
+ if (inp) {
61
+ inp.focus();
62
+
63
+ if (options.value) {
64
+ inp.value = options.value;
65
+ if (options.selectValueOnOpen !== false) {
66
+ inp.select();
67
+ }
68
+ }
69
+
70
+ if (options.onInput)
71
+ CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
72
+ if (options.onKeyUp)
73
+ CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
74
+
75
+ CodeMirror.on(inp, "keydown", function(e) {
76
+ if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
77
+ if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
78
+ inp.blur();
79
+ CodeMirror.e_stop(e);
80
+ close();
81
+ }
82
+ if (e.keyCode == 13) callback(inp.value, e);
83
+ });
84
+
85
+ if (options.closeOnBlur !== false) CodeMirror.on(dialog, "focusout", function (evt) {
86
+ if (evt.relatedTarget !== null) close();
87
+ });
88
+ } else if (button = dialog.getElementsByTagName("button")[0]) {
89
+ CodeMirror.on(button, "click", function() {
90
+ close();
91
+ me.focus();
92
+ });
93
+
94
+ if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
95
+
96
+ button.focus();
97
+ }
98
+ return close;
99
+ });
100
+
101
+ CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
102
+ closeNotification(this, null);
103
+ var dialog = dialogDiv(this, template, options && options.bottom);
104
+ var buttons = dialog.getElementsByTagName("button");
105
+ var closed = false, me = this, blurring = 1;
106
+ function close() {
107
+ if (closed) return;
108
+ closed = true;
109
+ CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
110
+ dialog.parentNode.removeChild(dialog);
111
+ me.focus();
112
+ }
113
+ buttons[0].focus();
114
+ for (var i = 0; i < buttons.length; ++i) {
115
+ var b = buttons[i];
116
+ (function(callback) {
117
+ CodeMirror.on(b, "click", function(e) {
118
+ CodeMirror.e_preventDefault(e);
119
+ close();
120
+ if (callback) callback(me);
121
+ });
122
+ })(callbacks[i]);
123
+ CodeMirror.on(b, "blur", function() {
124
+ --blurring;
125
+ setTimeout(function() { if (blurring <= 0) close(); }, 200);
126
+ });
127
+ CodeMirror.on(b, "focus", function() { ++blurring; });
128
+ }
129
+ });
130
+
131
+ /*
132
+ * openNotification
133
+ * Opens a notification, that can be closed with an optional timer
134
+ * (default 5000ms timer) and always closes on click.
135
+ *
136
+ * If a notification is opened while another is opened, it will close the
137
+ * currently opened one and open the new one immediately.
138
+ */
139
+ CodeMirror.defineExtension("openNotification", function(template, options) {
140
+ closeNotification(this, close);
141
+ var dialog = dialogDiv(this, template, options && options.bottom);
142
+ var closed = false, doneTimer;
143
+ var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
144
+
145
+ function close() {
146
+ if (closed) return;
147
+ closed = true;
148
+ clearTimeout(doneTimer);
149
+ CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
150
+ dialog.parentNode.removeChild(dialog);
151
+ }
152
+
153
+ CodeMirror.on(dialog, 'click', function(e) {
154
+ CodeMirror.e_preventDefault(e);
155
+ close();
156
+ });
157
+
158
+ if (duration)
159
+ doneTimer = setTimeout(close, duration);
160
+
161
+ return close;
162
+ });
163
+ });
js/codemirror/addon/search.js ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: https://codemirror.net/LICENSE
3
+
4
+ // Define search commands. Depends on dialog.js or another
5
+ // implementation of the openDialog method.
6
+
7
+ // Replace works a little oddly -- it will do the replace on the next
8
+ // Ctrl-G (or whatever is bound to findNext) press. You prevent a
9
+ // replace by making sure the match is no longer selected when hitting
10
+ // Ctrl-G.
11
+
12
+ (function(mod) {
13
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
14
+ mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
15
+ else if (typeof define == "function" && define.amd) // AMD
16
+ define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
17
+ else // Plain browser env
18
+ mod(CodeMirror);
19
+ })(function(CodeMirror) {
20
+ "use strict";
21
+
22
+ // default search panel location
23
+ CodeMirror.defineOption("search", {bottom: false});
24
+
25
+ function searchOverlay(query, caseInsensitive) {
26
+ if (typeof query == "string")
27
+ query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
28
+ else if (!query.global)
29
+ query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
30
+
31
+ return {token: function(stream) {
32
+ query.lastIndex = stream.pos;
33
+ var match = query.exec(stream.string);
34
+ if (match && match.index == stream.pos) {
35
+ stream.pos += match[0].length || 1;
36
+ return "searching";
37
+ } else if (match) {
38
+ stream.pos = match.index;
39
+ } else {
40
+ stream.skipToEnd();
41
+ }
42
+ }};
43
+ }
44
+
45
+ function SearchState() {
46
+ this.posFrom = this.posTo = this.lastQuery = this.query = null;
47
+ this.overlay = null;
48
+ }
49
+
50
+ function getSearchState(cm) {
51
+ return cm.state.search || (cm.state.search = new SearchState());
52
+ }
53
+
54
+ function queryCaseInsensitive(query) {
55
+ return typeof query == "string" && query == query.toLowerCase();
56
+ }
57
+
58
+ function getSearchCursor(cm, query, pos) {
59
+ // Heuristic: if the query string is all lowercase, do a case insensitive search.
60
+ return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true});
61
+ }
62
+
63
+ function persistentDialog(cm, text, deflt, onEnter, onKeyDown) {
64
+ cm.openDialog(text, onEnter, {
65
+ value: deflt,
66
+ selectValueOnOpen: true,
67
+ closeOnEnter: false,
68
+ onClose: function() { clearSearch(cm); },
69
+ onKeyDown: onKeyDown,
70
+ bottom: cm.options.search.bottom
71
+ });
72
+ }
73
+
74
+ function dialog(cm, text, shortText, deflt, f) {
75
+ if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom});
76
+ else f(prompt(shortText, deflt));
77
+ }
78
+
79
+ function confirmDialog(cm, text, shortText, fs) {
80
+ if (cm.openConfirm) cm.openConfirm(text, fs);
81
+ else if (confirm(shortText)) fs[0]();
82
+ }
83
+
84
+ function parseString(string) {
85
+ return string.replace(/\\([nrt\\])/g, function(match, ch) {
86
+ if (ch == "n") return "\n"
87
+ if (ch == "r") return "\r"
88
+ if (ch == "t") return "\t"
89
+ if (ch == "\\") return "\\"
90
+ return match
91
+ })
92
+ }
93
+
94
+ function parseQuery(query) {
95
+ var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
96
+ if (isRE) {
97
+ try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
98
+ catch(e) {} // Not a regular expression after all, do a string search
99
+ } else {
100
+ query = parseString(query)
101
+ }
102
+ if (typeof query == "string" ? query == "" : query.test(""))
103
+ query = /x^/;
104
+ return query;
105
+ }
106
+
107
+ function startSearch(cm, state, query) {
108
+ state.queryText = query;
109
+ state.query = parseQuery(query);
110
+ cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
111
+ state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
112
+ cm.addOverlay(state.overlay);
113
+ if (cm.showMatchesOnScrollbar) {
114
+ if (state.annotate) { state.annotate.clear(); state.annotate = null; }
115
+ state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
116
+ }
117
+ }
118
+
119
+ function doSearch(cm, rev, persistent, immediate) {
120
+ var state = getSearchState(cm);
121
+ if (state.query) return findNext(cm, rev);
122
+ var q = cm.getSelection() || state.lastQuery;
123
+ if (q instanceof RegExp && q.source == "x^") q = null
124
+ if (persistent && cm.openDialog) {
125
+ var hiding = null
126
+ var searchNext = function(query, event) {
127
+ CodeMirror.e_stop(event);
128
+ if (!query) return;
129
+ if (query != state.queryText) {
130
+ startSearch(cm, state, query);
131
+ state.posFrom = state.posTo = cm.getCursor();
132
+ }
133
+ if (hiding) hiding.style.opacity = 1
134
+ findNext(cm, event.shiftKey, function(_, to) {
135
+ var dialog
136
+ if (to.line < 3 && document.querySelector &&
137
+ (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
138
+ dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
139
+ (hiding = dialog).style.opacity = .4
140
+ })
141
+ };
142
+ persistentDialog(cm, getQueryDialog(cm), q, searchNext, function(event, query) {
143
+ var keyName = CodeMirror.keyName(event)
144
+ var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName]
145
+ if (cmd == "findNext" || cmd == "findPrev" ||
146
+ cmd == "findPersistentNext" || cmd == "findPersistentPrev") {
147
+ CodeMirror.e_stop(event);
148
+ startSearch(cm, getSearchState(cm), query);
149
+ cm.execCommand(cmd);
150
+ } else if (cmd == "find" || cmd == "findPersistent") {
151
+ CodeMirror.e_stop(event);
152
+ searchNext(query, event);
153
+ }
154
+ });
155
+ if (immediate && q) {
156
+ startSearch(cm, state, q);
157
+ findNext(cm, rev);
158
+ }
159
+ } else {
160
+ dialog(cm, getQueryDialog(cm), "Search for:", q, function(query) {
161
+ if (query && !state.query) cm.operation(function() {
162
+ startSearch(cm, state, query);
163
+ state.posFrom = state.posTo = cm.getCursor();
164
+ findNext(cm, rev);
165
+ });
166
+ });
167
+ }
168
+ }
169
+
170
+ function findNext(cm, rev, callback) {cm.operation(function() {
171
+ var state = getSearchState(cm);
172
+ var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
173
+ if (!cursor.find(rev)) {
174
+ cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
175
+ if (!cursor.find(rev)) return;
176
+ }
177
+ cm.setSelection(cursor.from(), cursor.to());
178
+ cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
179
+ state.posFrom = cursor.from(); state.posTo = cursor.to();
180
+ if (callback) callback(cursor.from(), cursor.to())
181
+ });}
182
+
183
+ function clearSearch(cm) {cm.operation(function() {
184
+ var state = getSearchState(cm);
185
+ state.lastQuery = state.query;
186
+ if (!state.query) return;
187
+ state.query = state.queryText = null;
188
+ cm.removeOverlay(state.overlay);
189
+ if (state.annotate) { state.annotate.clear(); state.annotate = null; }
190
+ });}
191
+
192
+
193
+ function getQueryDialog(cm) {
194
+ return '<span class="CodeMirror-search-label">' + cm.phrase("Search:") + '</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">' + cm.phrase("(Use /re/ syntax for regexp search)") + '</span>';
195
+ }
196
+ function getReplaceQueryDialog(cm) {
197
+ return ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">' + cm.phrase("(Use /re/ syntax for regexp search)") + '</span>';
198
+ }
199
+ function getReplacementQueryDialog(cm) {
200
+ return '<span class="CodeMirror-search-label">' + cm.phrase("With:") + '</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
201
+ }
202
+ function getDoReplaceConfirm(cm) {
203
+ return '<span class="CodeMirror-search-label">' + cm.phrase("Replace?") + '</span> <button>' + cm.phrase("Yes") + '</button> <button>' + cm.phrase("No") + '</button> <button>' + cm.phrase("All") + '</button> <button>' + cm.phrase("Stop") + '</button> ';
204
+ }
205
+
206
+ function replaceAll(cm, query, text) {
207
+ cm.operation(function() {
208
+ for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
209
+ if (typeof query != "string") {
210
+ var match = cm.getRange(cursor.from(), cursor.to()).match(query);
211
+ cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
212
+ } else cursor.replace(text);
213
+ }
214
+ });
215
+ }
216
+
217
+ function replace(cm, all) {
218
+ if (cm.getOption("readOnly")) return;
219
+ var query = cm.getSelection() || getSearchState(cm).lastQuery;
220
+ var dialogText = '<span class="CodeMirror-search-label">' + (all ? cm.phrase("Replace all:") : cm.phrase("Replace:")) + '</span>';
221
+ dialog(cm, dialogText + getReplaceQueryDialog(cm), dialogText, query, function(query) {
222
+ if (!query) return;
223
+ query = parseQuery(query);
224
+ dialog(cm, getReplacementQueryDialog(cm), cm.phrase("Replace with:"), "", function(text) {
225
+ text = parseString(text)
226
+ if (all) {
227
+ replaceAll(cm, query, text)
228
+ } else {
229
+ clearSearch(cm);
230
+ var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
231
+ var advance = function() {
232
+ var start = cursor.from(), match;
233
+ if (!(match = cursor.findNext())) {
234
+ cursor = getSearchCursor(cm, query);
235
+ if (!(match = cursor.findNext()) ||
236
+ (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
237
+ }
238
+ cm.setSelection(cursor.from(), cursor.to());
239
+ cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
240
+ confirmDialog(cm, getDoReplaceConfirm(cm), cm.phrase("Replace?"),
241
+ [function() {doReplace(match);}, advance,
242
+ function() {replaceAll(cm, query, text)}]);
243
+ };
244
+ var doReplace = function(match) {
245
+ cursor.replace(typeof query == "string" ? text :
246
+ text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
247
+ advance();
248
+ };
249
+ advance();
250
+ }
251
+ });
252
+ });
253
+ }
254
+
255
+ CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
256
+ CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
257
+ CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);};
258
+ CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);};
259
+ CodeMirror.commands.findNext = doSearch;
260
+ CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
261
+ CodeMirror.commands.clearSearch = clearSearch;
262
+ CodeMirror.commands.replace = replace;
263
+ CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
264
+ });
js/codemirror/addon/searchcursor.js ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: https://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"))
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod)
9
+ else // Plain browser env
10
+ mod(CodeMirror)
11
+ })(function(CodeMirror) {
12
+ "use strict"
13
+ var Pos = CodeMirror.Pos
14
+
15
+ function regexpFlags(regexp) {
16
+ var flags = regexp.flags
17
+ return flags != null ? flags : (regexp.ignoreCase ? "i" : "")
18
+ + (regexp.global ? "g" : "")
19
+ + (regexp.multiline ? "m" : "")
20
+ }
21
+
22
+ function ensureFlags(regexp, flags) {
23
+ var current = regexpFlags(regexp), target = current
24
+ for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1)
25
+ target += flags.charAt(i)
26
+ return current == target ? regexp : new RegExp(regexp.source, target)
27
+ }
28
+
29
+ function maybeMultiline(regexp) {
30
+ return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source)
31
+ }
32
+
33
+ function searchRegexpForward(doc, regexp, start) {
34
+ regexp = ensureFlags(regexp, "g")
35
+ for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {
36
+ regexp.lastIndex = ch
37
+ var string = doc.getLine(line), match = regexp.exec(string)
38
+ if (match)
39
+ return {from: Pos(line, match.index),
40
+ to: Pos(line, match.index + match[0].length),
41
+ match: match}
42
+ }
43
+ }
44
+
45
+ function searchRegexpForwardMultiline(doc, regexp, start) {
46
+ if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)
47
+
48
+ regexp = ensureFlags(regexp, "gm")
49
+ var string, chunk = 1
50
+ for (var line = start.line, last = doc.lastLine(); line <= last;) {
51
+ // This grows the search buffer in exponentially-sized chunks
52
+ // between matches, so that nearby matches are fast and don't
53
+ // require concatenating the whole document (in case we're
54
+ // searching for something that has tons of matches), but at the
55
+ // same time, the amount of retries is limited.
56
+ for (var i = 0; i < chunk; i++) {
57
+ if (line > last) break
58
+ var curLine = doc.getLine(line++)
59
+ string = string == null ? curLine : string + "\n" + curLine
60
+ }
61
+ chunk = chunk * 2
62
+ regexp.lastIndex = start.ch
63
+ var match = regexp.exec(string)
64
+ if (match) {
65
+ var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
66
+ var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length
67
+ return {from: Pos(startLine, startCh),
68
+ to: Pos(startLine + inside.length - 1,
69
+ inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
70
+ match: match}
71
+ }
72
+ }
73
+ }
74
+
75
+ function lastMatchIn(string, regexp, endMargin) {
76
+ var match, from = 0
77
+ while (from <= string.length) {
78
+ regexp.lastIndex = from
79
+ var newMatch = regexp.exec(string)
80
+ if (!newMatch) break
81
+ var end = newMatch.index + newMatch[0].length
82
+ if (end > string.length - endMargin) break
83
+ if (!match || end > match.index + match[0].length)
84
+ match = newMatch
85
+ from = newMatch.index + 1
86
+ }
87
+ return match
88
+ }
89
+
90
+ function searchRegexpBackward(doc, regexp, start) {
91
+ regexp = ensureFlags(regexp, "g")
92
+ for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
93
+ var string = doc.getLine(line)
94
+ var match = lastMatchIn(string, regexp, ch < 0 ? 0 : string.length - ch)
95
+ if (match)
96
+ return {from: Pos(line, match.index),
97
+ to: Pos(line, match.index + match[0].length),
98
+ match: match}
99
+ }
100
+ }
101
+
102
+ function searchRegexpBackwardMultiline(doc, regexp, start) {
103
+ if (!maybeMultiline(regexp)) return searchRegexpBackward(doc, regexp, start)
104
+ regexp = ensureFlags(regexp, "gm")
105
+ var string, chunkSize = 1, endMargin = doc.getLine(start.line).length - start.ch
106
+ for (var line = start.line, first = doc.firstLine(); line >= first;) {
107
+ for (var i = 0; i < chunkSize && line >= first; i++) {
108
+ var curLine = doc.getLine(line--)
109
+ string = string == null ? curLine : curLine + "\n" + string
110
+ }
111
+ chunkSize *= 2
112
+
113
+ var match = lastMatchIn(string, regexp, endMargin)
114
+ if (match) {
115
+ var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
116
+ var startLine = line + before.length, startCh = before[before.length - 1].length
117
+ return {from: Pos(startLine, startCh),
118
+ to: Pos(startLine + inside.length - 1,
119
+ inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
120
+ match: match}
121
+ }
122
+ }
123
+ }
124
+
125
+ var doFold, noFold
126
+ if (String.prototype.normalize) {
127
+ doFold = function(str) { return str.normalize("NFD").toLowerCase() }
128
+ noFold = function(str) { return str.normalize("NFD") }
129
+ } else {
130
+ doFold = function(str) { return str.toLowerCase() }
131
+ noFold = function(str) { return str }
132
+ }
133
+
134
+ // Maps a position in a case-folded line back to a position in the original line
135
+ // (compensating for codepoints increasing in number during folding)
136
+ function adjustPos(orig, folded, pos, foldFunc) {
137
+ if (orig.length == folded.length) return pos
138
+ for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) {
139
+ if (min == max) return min
140
+ var mid = (min + max) >> 1
141
+ var len = foldFunc(orig.slice(0, mid)).length
142
+ if (len == pos) return mid
143
+ else if (len > pos) max = mid
144
+ else min = mid + 1
145
+ }
146
+ }
147
+
148
+ function searchStringForward(doc, query, start, caseFold) {
149
+ // Empty string would match anything and never progress, so we
150
+ // define it to match nothing instead.
151
+ if (!query.length) return null
152
+ var fold = caseFold ? doFold : noFold
153
+ var lines = fold(query).split(/\r|\n\r?/)
154
+
155
+ search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) {
156
+ var orig = doc.getLine(line).slice(ch), string = fold(orig)
157
+ if (lines.length == 1) {
158
+ var found = string.indexOf(lines[0])
159
+ if (found == -1) continue search
160
+ var start = adjustPos(orig, string, found, fold) + ch
161
+ return {from: Pos(line, adjustPos(orig, string, found, fold) + ch),
162
+ to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)}
163
+ } else {
164
+ var cutFrom = string.length - lines[0].length
165
+ if (string.slice(cutFrom) != lines[0]) continue search
166
+ for (var i = 1; i < lines.length - 1; i++)
167
+ if (fold(doc.getLine(line + i)) != lines[i]) continue search
168
+ var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1]
169
+ if (endString.slice(0, lastLine.length) != lastLine) continue search
170
+ return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch),
171
+ to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))}
172
+ }
173
+ }
174
+ }
175
+
176
+ function searchStringBackward(doc, query, start, caseFold) {
177
+ if (!query.length) return null
178
+ var fold = caseFold ? doFold : noFold
179
+ var lines = fold(query).split(/\r|\n\r?/)
180
+
181
+ search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) {
182
+ var orig = doc.getLine(line)
183
+ if (ch > -1) orig = orig.slice(0, ch)
184
+ var string = fold(orig)
185
+ if (lines.length == 1) {
186
+ var found = string.lastIndexOf(lines[0])
187
+ if (found == -1) continue search
188
+ return {from: Pos(line, adjustPos(orig, string, found, fold)),
189
+ to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))}
190
+ } else {
191
+ var lastLine = lines[lines.length - 1]
192
+ if (string.slice(0, lastLine.length) != lastLine) continue search
193
+ for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++)
194
+ if (fold(doc.getLine(start + i)) != lines[i]) continue search
195
+ var top = doc.getLine(line + 1 - lines.length), topString = fold(top)
196
+ if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search
197
+ return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)),
198
+ to: Pos(line, adjustPos(orig, string, lastLine.length, fold))}
199
+ }
200
+ }
201
+ }
202
+
203
+ function SearchCursor(doc, query, pos, options) {
204
+ this.atOccurrence = false
205
+ this.doc = doc
206
+ pos = pos ? doc.clipPos(pos) : Pos(0, 0)
207
+ this.pos = {from: pos, to: pos}
208
+
209
+ var caseFold
210
+ if (typeof options == "object") {
211
+ caseFold = options.caseFold
212
+ } else { // Backwards compat for when caseFold was the 4th argument
213
+ caseFold = options
214
+ options = null
215
+ }
216
+
217
+ if (typeof query == "string") {
218
+ if (caseFold == null) caseFold = false
219
+ this.matches = function(reverse, pos) {
220
+ return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)
221
+ }
222
+ } else {
223
+ query = ensureFlags(query, "gm")
224
+ if (!options || options.multiline !== false)
225
+ this.matches = function(reverse, pos) {
226
+ return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)
227
+ }
228
+ else
229
+ this.matches = function(reverse, pos) {
230
+ return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos)
231
+ }
232
+ }
233
+ }
234
+
235
+ SearchCursor.prototype = {
236
+ findNext: function() {return this.find(false)},
237
+ findPrevious: function() {return this.find(true)},
238
+
239
+ find: function(reverse) {
240
+ var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to))
241
+
242
+ // Implements weird auto-growing behavior on null-matches for
243
+ // backwards-compatibility with the vim code (unfortunately)
244
+ while (result && CodeMirror.cmpPos(result.from, result.to) == 0) {
245
+ if (reverse) {
246
+ if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1)
247
+ else if (result.from.line == this.doc.firstLine()) result = null
248
+ else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1)))
249
+ } else {
250
+ if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1)
251
+ else if (result.to.line == this.doc.lastLine()) result = null
252
+ else result = this.matches(reverse, Pos(result.to.line + 1, 0))
253
+ }
254
+ }
255
+
256
+ if (result) {
257
+ this.pos = result
258
+ this.atOccurrence = true
259
+ return this.pos.match || true
260
+ } else {
261
+ var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0)
262
+ this.pos = {from: end, to: end}
263
+ return this.atOccurrence = false
264
+ }
265
+ },
266
+
267
+ from: function() {if (this.atOccurrence) return this.pos.from},
268
+ to: function() {if (this.atOccurrence) return this.pos.to},
269
+
270
+ replace: function(newText, origin) {
271
+ if (!this.atOccurrence) return
272
+ var lines = CodeMirror.splitLines(newText)
273
+ this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin)
274
+ this.pos.to = Pos(this.pos.from.line + lines.length - 1,
275
+ lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0))
276
+ }
277
+ }
278
+
279
+ CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
280
+ return new SearchCursor(this.doc, query, pos, caseFold)
281
+ })
282
+ CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
283
+ return new SearchCursor(this, query, pos, caseFold)
284
+ })
285
+
286
+ CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
287
+ var ranges = []
288
+ var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold)
289
+ while (cur.findNext()) {
290
+ if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break
291
+ ranges.push({anchor: cur.from(), head: cur.to()})
292
+ }
293
+ if (ranges.length)
294
+ this.setSelections(ranges, 0)
295
+ })
296
+ });
js/codemirror/codemirror.css CHANGED
@@ -5,6 +5,7 @@
5
  font-family: monospace;
6
  height: 300px;
7
  color: black;
 
8
  }
9
 
10
  /* PADDING */
@@ -12,12 +13,13 @@
12
  .CodeMirror-lines {
13
  padding: 4px 0; /* Vertical padding around content */
14
  }
15
- .CodeMirror pre {
 
16
  padding: 0 4px; /* Horizontal padding of content */
17
  }
18
 
19
  .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
20
- background-color: white; /* The little square between H and V scrollbars */
21
  }
22
 
23
  /* GUTTER */
@@ -41,57 +43,80 @@
41
 
42
  /* CURSOR */
43
 
44
- .CodeMirror div.CodeMirror-cursor {
45
  border-left: 1px solid black;
 
 
46
  }
47
  /* Shown when moving in bi-directional text */
48
  .CodeMirror div.CodeMirror-secondarycursor {
49
  border-left: 1px solid silver;
50
  }
51
- .CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
52
  width: auto;
53
- border: 0;
54
  background: #7e7;
55
  }
56
- .CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
57
  z-index: 1;
58
  }
59
-
 
 
 
 
 
60
  .cm-animate-fat-cursor {
61
  width: auto;
62
  border: 0;
63
  -webkit-animation: blink 1.06s steps(1) infinite;
64
  -moz-animation: blink 1.06s steps(1) infinite;
65
  animation: blink 1.06s steps(1) infinite;
 
66
  }
67
  @-moz-keyframes blink {
68
- 0% { background: #7e7; }
69
- 50% { background: none; }
70
- 100% { background: #7e7; }
71
  }
72
  @-webkit-keyframes blink {
73
- 0% { background: #7e7; }
74
- 50% { background: none; }
75
- 100% { background: #7e7; }
76
  }
77
  @keyframes blink {
78
- 0% { background: #7e7; }
79
- 50% { background: none; }
80
- 100% { background: #7e7; }
81
  }
82
 
83
  /* Can style cursor different in overwrite (non-insert) mode */
84
- div.CodeMirror-overwrite div.CodeMirror-cursor {}
85
 
86
  .cm-tab { display: inline-block; text-decoration: inherit; }
87
 
 
 
 
 
 
88
  .CodeMirror-ruler {
89
  border-left: 1px solid #ccc;
 
90
  position: absolute;
91
  }
92
 
93
  /* DEFAULT THEME */
94
 
 
 
 
 
 
 
 
 
 
95
  .cm-s-default .cm-keyword {color: #708;}
96
  .cm-s-default .cm-atom {color: #219;}
97
  .cm-s-default .cm-number {color: #164;}
@@ -101,7 +126,7 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
101
  .cm-s-default .cm-property,
102
  .cm-s-default .cm-operator {}
103
  .cm-s-default .cm-variable-2 {color: #05a;}
104
- .cm-s-default .cm-variable-3 {color: #085;}
105
  .cm-s-default .cm-comment {color: #a50;}
106
  .cm-s-default .cm-string {color: #a11;}
107
  .cm-s-default .cm-string-2 {color: #f50;}
@@ -111,25 +136,18 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
111
  .cm-s-default .cm-bracket {color: #997;}
112
  .cm-s-default .cm-tag {color: #170;}
113
  .cm-s-default .cm-attribute {color: #00c;}
114
- .cm-s-default .cm-header {color: blue;}
115
- .cm-s-default .cm-quote {color: #090;}
116
  .cm-s-default .cm-hr {color: #999;}
117
  .cm-s-default .cm-link {color: #00c;}
118
 
119
- .cm-negative {color: #d44;}
120
- .cm-positive {color: #292;}
121
- .cm-header, .cm-strong {font-weight: bold;}
122
- .cm-em {font-style: italic;}
123
- .cm-link {text-decoration: underline;}
124
- .cm-strikethrough {text-decoration: line-through;}
125
-
126
  .cm-s-default .cm-error {color: #f00;}
127
  .cm-invalidchar {color: #f00;}
128
 
 
 
129
  /* Default styles for common addons */
130
 
131
- div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
132
- div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
133
  .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
134
  .CodeMirror-activeline-background {background: #e8f2ff;}
135
 
@@ -146,26 +164,27 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
146
 
147
  .CodeMirror-scroll {
148
  overflow: scroll !important; /* Things will break if this is overridden */
149
- /* 30px is the magic margin used to hide the element's real scrollbars */
150
  /* See overflow: hidden in .CodeMirror */
151
- margin-bottom: -30px; margin-right: -30px;
152
- padding-bottom: 30px;
153
  height: 100%;
154
  outline: none; /* Prevent dragging from highlighting the element */
155
  position: relative;
156
  }
157
  .CodeMirror-sizer {
158
  position: relative;
159
- border-right: 30px solid transparent;
160
  }
161
 
162
  /* The fake, visible scrollbars. Used to force redraw during scrolling
163
- before actuall scrolling happens, thus preventing shaking and
164
  flickering artifacts. */
165
  .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
166
  position: absolute;
167
  z-index: 6;
168
  display: none;
 
169
  }
170
  .CodeMirror-vscrollbar {
171
  right: 0; top: 0;
@@ -186,38 +205,41 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
186
 
187
  .CodeMirror-gutters {
188
  position: absolute; left: 0; top: 0;
 
189
  z-index: 3;
190
  }
191
  .CodeMirror-gutter {
192
  white-space: normal;
193
  height: 100%;
194
  display: inline-block;
195
- margin-bottom: -30px;
196
- /* Hack to make IE7 behave */
197
- *zoom:1;
198
- *display:inline;
199
  }
200
  .CodeMirror-gutter-wrapper {
201
  position: absolute;
202
  z-index: 4;
203
- height: 100%;
 
 
 
 
 
 
204
  }
205
  .CodeMirror-gutter-elt {
206
  position: absolute;
207
  cursor: default;
208
  z-index: 4;
209
  }
210
- .CodeMirror-gutter-wrapper {
211
- -webkit-user-select: none;
212
- -moz-user-select: none;
213
- user-select: none;
214
- }
215
 
216
  .CodeMirror-lines {
217
  cursor: text;
218
  min-height: 1px; /* prevents collapsing before first draw */
219
  }
220
- .CodeMirror pre {
 
221
  /* Reset some styles that the rest of the page might have set */
222
  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
223
  border-width: 0;
@@ -233,8 +255,11 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
233
  position: relative;
234
  overflow: visible;
235
  -webkit-tap-highlight-color: transparent;
 
 
236
  }
237
- .CodeMirror-wrap pre {
 
238
  word-wrap: break-word;
239
  white-space: pre-wrap;
240
  word-break: normal;
@@ -249,11 +274,13 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
249
  .CodeMirror-linewidget {
250
  position: relative;
251
  z-index: 2;
252
- overflow: auto;
253
  }
254
 
255
  .CodeMirror-widget {}
256
 
 
 
257
  .CodeMirror-code {
258
  outline: none;
259
  }
@@ -275,19 +302,22 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
275
  overflow: hidden;
276
  visibility: hidden;
277
  }
278
- .CodeMirror-measure pre { position: static; }
279
 
280
- .CodeMirror div.CodeMirror-cursor {
281
  position: absolute;
282
- border-right: none;
283
- width: 0;
284
  }
 
285
 
286
  div.CodeMirror-cursors {
287
  visibility: hidden;
288
  position: relative;
289
  z-index: 3;
290
  }
 
 
 
 
291
  .CodeMirror-focused div.CodeMirror-cursors {
292
  visibility: visible;
293
  }
@@ -295,17 +325,14 @@ div.CodeMirror-cursors {
295
  .CodeMirror-selected { background: #d9d9d9; }
296
  .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
297
  .CodeMirror-crosshair { cursor: crosshair; }
298
- .CodeMirror ::selection { background: #d7d4f0; }
299
- .CodeMirror ::-moz-selection { background: #d7d4f0; }
300
 
301
  .cm-searching {
302
- background: #ffa;
303
- background: rgba(255, 255, 0, .4);
304
  }
305
 
306
- /* IE7 hack to prevent it from returning funny offsetTops on the spans */
307
- .CodeMirror span { *vertical-align: text-bottom; }
308
-
309
  /* Used to force a border model for a node */
310
  .cm-force-border { padding-right: .1px; }
311
 
5
  font-family: monospace;
6
  height: 300px;
7
  color: black;
8
+ direction: ltr;
9
  }
10
 
11
  /* PADDING */
13
  .CodeMirror-lines {
14
  padding: 4px 0; /* Vertical padding around content */
15
  }
16
+ .CodeMirror pre.CodeMirror-line,
17
+ .CodeMirror pre.CodeMirror-line-like {
18
  padding: 0 4px; /* Horizontal padding of content */
19
  }
20
 
21
  .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
22
+ background-color: transparent; /* The little square between H and V scrollbars */
23
  }
24
 
25
  /* GUTTER */
43
 
44
  /* CURSOR */
45
 
46
+ .CodeMirror-cursor {
47
  border-left: 1px solid black;
48
+ border-right: none;
49
+ width: 0;
50
  }
51
  /* Shown when moving in bi-directional text */
52
  .CodeMirror div.CodeMirror-secondarycursor {
53
  border-left: 1px solid silver;
54
  }
55
+ .cm-fat-cursor .CodeMirror-cursor {
56
  width: auto;
57
+ border: 0 !important;
58
  background: #7e7;
59
  }
60
+ .cm-fat-cursor div.CodeMirror-cursors {
61
  z-index: 1;
62
  }
63
+ .cm-fat-cursor-mark {
64
+ background-color: rgba(20, 255, 20, 0.5);
65
+ -webkit-animation: blink 1.06s steps(1) infinite;
66
+ -moz-animation: blink 1.06s steps(1) infinite;
67
+ animation: blink 1.06s steps(1) infinite;
68
+ }
69
  .cm-animate-fat-cursor {
70
  width: auto;
71
  border: 0;
72
  -webkit-animation: blink 1.06s steps(1) infinite;
73
  -moz-animation: blink 1.06s steps(1) infinite;
74
  animation: blink 1.06s steps(1) infinite;
75
+ background-color: #7e7;
76
  }
77
  @-moz-keyframes blink {
78
+ 0% {}
79
+ 50% { background-color: transparent; }
80
+ 100% {}
81
  }
82
  @-webkit-keyframes blink {
83
+ 0% {}
84
+ 50% { background-color: transparent; }
85
+ 100% {}
86
  }
87
  @keyframes blink {
88
+ 0% {}
89
+ 50% { background-color: transparent; }
90
+ 100% {}
91
  }
92
 
93
  /* Can style cursor different in overwrite (non-insert) mode */
94
+ .CodeMirror-overwrite .CodeMirror-cursor {}
95
 
96
  .cm-tab { display: inline-block; text-decoration: inherit; }
97
 
98
+ .CodeMirror-rulers {
99
+ position: absolute;
100
+ left: 0; right: 0; top: -50px; bottom: 0;
101
+ overflow: hidden;
102
+ }
103
  .CodeMirror-ruler {
104
  border-left: 1px solid #ccc;
105
+ top: 0; bottom: 0;
106
  position: absolute;
107
  }
108
 
109
  /* DEFAULT THEME */
110
 
111
+ .cm-s-default .cm-header {color: blue;}
112
+ .cm-s-default .cm-quote {color: #090;}
113
+ .cm-negative {color: #d44;}
114
+ .cm-positive {color: #292;}
115
+ .cm-header, .cm-strong {font-weight: bold;}
116
+ .cm-em {font-style: italic;}
117
+ .cm-link {text-decoration: underline;}
118
+ .cm-strikethrough {text-decoration: line-through;}
119
+
120
  .cm-s-default .cm-keyword {color: #708;}
121
  .cm-s-default .cm-atom {color: #219;}
122
  .cm-s-default .cm-number {color: #164;}
126
  .cm-s-default .cm-property,
127
  .cm-s-default .cm-operator {}
128
  .cm-s-default .cm-variable-2 {color: #05a;}
129
+ .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
130
  .cm-s-default .cm-comment {color: #a50;}
131
  .cm-s-default .cm-string {color: #a11;}
132
  .cm-s-default .cm-string-2 {color: #f50;}
136
  .cm-s-default .cm-bracket {color: #997;}
137
  .cm-s-default .cm-tag {color: #170;}
138
  .cm-s-default .cm-attribute {color: #00c;}
 
 
139
  .cm-s-default .cm-hr {color: #999;}
140
  .cm-s-default .cm-link {color: #00c;}
141
 
 
 
 
 
 
 
 
142
  .cm-s-default .cm-error {color: #f00;}
143
  .cm-invalidchar {color: #f00;}
144
 
145
+ .CodeMirror-composing { border-bottom: 2px solid; }
146
+
147
  /* Default styles for common addons */
148
 
149
+ div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
150
+ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
151
  .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
152
  .CodeMirror-activeline-background {background: #e8f2ff;}
153
 
164
 
165
  .CodeMirror-scroll {
166
  overflow: scroll !important; /* Things will break if this is overridden */
167
+ /* 50px is the magic margin used to hide the element's real scrollbars */
168
  /* See overflow: hidden in .CodeMirror */
169
+ margin-bottom: -50px; margin-right: -50px;
170
+ padding-bottom: 50px;
171
  height: 100%;
172
  outline: none; /* Prevent dragging from highlighting the element */
173
  position: relative;
174
  }
175
  .CodeMirror-sizer {
176
  position: relative;
177
+ border-right: 50px solid transparent;
178
  }
179
 
180
  /* The fake, visible scrollbars. Used to force redraw during scrolling
181
+ before actual scrolling happens, thus preventing shaking and
182
  flickering artifacts. */
183
  .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
184
  position: absolute;
185
  z-index: 6;
186
  display: none;
187
+ outline: none;
188
  }
189
  .CodeMirror-vscrollbar {
190
  right: 0; top: 0;
205
 
206
  .CodeMirror-gutters {
207
  position: absolute; left: 0; top: 0;
208
+ min-height: 100%;
209
  z-index: 3;
210
  }
211
  .CodeMirror-gutter {
212
  white-space: normal;
213
  height: 100%;
214
  display: inline-block;
215
+ vertical-align: top;
216
+ margin-bottom: -50px;
 
 
217
  }
218
  .CodeMirror-gutter-wrapper {
219
  position: absolute;
220
  z-index: 4;
221
+ background: none !important;
222
+ border: none !important;
223
+ }
224
+ .CodeMirror-gutter-background {
225
+ position: absolute;
226
+ top: 0; bottom: 0;
227
+ z-index: 4;
228
  }
229
  .CodeMirror-gutter-elt {
230
  position: absolute;
231
  cursor: default;
232
  z-index: 4;
233
  }
234
+ .CodeMirror-gutter-wrapper ::selection { background-color: transparent }
235
+ .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
 
 
 
236
 
237
  .CodeMirror-lines {
238
  cursor: text;
239
  min-height: 1px; /* prevents collapsing before first draw */
240
  }
241
+ .CodeMirror pre.CodeMirror-line,
242
+ .CodeMirror pre.CodeMirror-line-like {
243
  /* Reset some styles that the rest of the page might have set */
244
  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
245
  border-width: 0;
255
  position: relative;
256
  overflow: visible;
257
  -webkit-tap-highlight-color: transparent;
258
+ -webkit-font-variant-ligatures: contextual;
259
+ font-variant-ligatures: contextual;
260
  }
261
+ .CodeMirror-wrap pre.CodeMirror-line,
262
+ .CodeMirror-wrap pre.CodeMirror-line-like {
263
  word-wrap: break-word;
264
  white-space: pre-wrap;
265
  word-break: normal;
274
  .CodeMirror-linewidget {
275
  position: relative;
276
  z-index: 2;
277
+ padding: 0.1px; /* Force widget margins to stay inside of the container */
278
  }
279
 
280
  .CodeMirror-widget {}
281
 
282
+ .CodeMirror-rtl pre { direction: rtl; }
283
+
284
  .CodeMirror-code {
285
  outline: none;
286
  }
302
  overflow: hidden;
303
  visibility: hidden;
304
  }
 
305
 
306
+ .CodeMirror-cursor {
307
  position: absolute;
308
+ pointer-events: none;
 
309
  }
310
+ .CodeMirror-measure pre { position: static; }
311
 
312
  div.CodeMirror-cursors {
313
  visibility: hidden;
314
  position: relative;
315
  z-index: 3;
316
  }
317
+ div.CodeMirror-dragcursors {
318
+ visibility: visible;
319
+ }
320
+
321
  .CodeMirror-focused div.CodeMirror-cursors {
322
  visibility: visible;
323
  }
325
  .CodeMirror-selected { background: #d9d9d9; }
326
  .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
327
  .CodeMirror-crosshair { cursor: crosshair; }
328
+ .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
329
+ .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
330
 
331
  .cm-searching {
332
+ background-color: #ffa;
333
+ background-color: rgba(255, 255, 0, .4);
334
  }
335
 
 
 
 
336
  /* Used to force a border model for a node */
337
  .cm-force-border { padding-right: .1px; }
338
 
js/codemirror/codemirror.js CHANGED
@@ -1,2445 +1,2317 @@
1
  // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
- // Distributed under an MIT license: http://codemirror.net/LICENSE
3
 
4
- // This is CodeMirror (http://codemirror.net), a code editor
5
  // implemented in JavaScript on top of the browser's DOM.
6
  //
7
  // You can find some technical background for some of the code below
8
  // at http://marijnhaverbeke.nl/blog/#cm-internals .
9
 
10
- (function(mod) {
11
- if (typeof exports == "object" && typeof module == "object") // CommonJS
12
- module.exports = mod();
13
- else if (typeof define == "function" && define.amd) // AMD
14
- return define([], mod);
15
- else // Plain browser env
16
- this.CodeMirror = mod();
17
- })(function() {
18
- "use strict";
19
-
20
- // BROWSER SNIFFING
21
 
22
  // Kludges for bugs and behavior differences that can't be feature
23
  // detected are enabled based on userAgent etc sniffing.
24
-
25
- var gecko = /gecko\/\d/i.test(navigator.userAgent);
26
- var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
27
- var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
28
- var ie = ie_upto10 || ie_11up;
29
- var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
30
- var webkit = /WebKit\//.test(navigator.userAgent);
31
- var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
32
- var chrome = /Chrome\//.test(navigator.userAgent);
33
- var presto = /Opera\//.test(navigator.userAgent);
 
 
 
34
  var safari = /Apple Computer/.test(navigator.vendor);
35
- var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
36
- var phantom = /PhantomJS/.test(navigator.userAgent);
37
 
38
- var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
 
39
  // This is woefully incomplete. Suggestions for alternative methods welcome.
40
- var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
41
- var mac = ios || /Mac/.test(navigator.platform);
42
- var windows = /win/i.test(navigator.platform);
 
43
 
44
- var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
45
- if (presto_version) presto_version = Number(presto_version[1]);
46
  if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
47
  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
48
  var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
49
  var captureRightClick = gecko || (ie && ie_version >= 9);
50
 
51
- // Optimize some code when these features are not used.
52
- var sawReadOnlySpans = false, sawCollapsedSpans = false;
53
-
54
- // EDITOR CONSTRUCTOR
55
 
56
- // A CodeMirror instance represents an editor. This is the object
57
- // that user code is usually dealing with.
 
 
 
 
 
 
58
 
59
- function CodeMirror(place, options) {
60
- if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
 
 
 
61
 
62
- this.options = options = options ? copyObj(options) : {};
63
- // Determine effective options based on given values and defaults.
64
- copyObj(defaults, options, false);
65
- setGuttersForLineNumbers(options);
66
 
67
- var doc = options.value;
68
- if (typeof doc == "string") doc = new Doc(doc, options.mode);
69
- this.doc = doc;
 
 
 
 
 
 
 
 
 
 
 
70
 
71
- var input = new CodeMirror.inputStyles[options.inputStyle](this);
72
- var display = this.display = new Display(place, doc, input);
73
- display.wrapper.CodeMirror = this;
74
- updateGutters(this);
75
- themeChanged(this);
76
- if (options.lineWrapping)
77
- this.display.wrapper.className += " CodeMirror-wrap";
78
- if (options.autofocus && !mobile) display.input.focus();
79
- initScrollbars(this);
 
 
 
 
 
 
 
80
 
81
- this.state = {
82
- keyMaps: [], // stores maps added by addKeyMap
83
- overlays: [], // highlighting overlays, as added by addOverlay
84
- modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
85
- overwrite: false, focused: false,
86
- suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
87
- pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
88
- draggingText: false,
89
- highlight: new Delayed(), // stores highlight worker timeout
90
- keySeq: null, // Unfinished key sequence
91
- specialChars: null
92
- };
93
 
94
- var cm = this;
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- // Override magic textarea content restore that IE sometimes does
97
- // on our hidden textarea on reload
98
- if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);
 
 
 
 
 
 
 
99
 
100
- registerEventHandlers(this);
101
- ensureGlobalHandlers();
 
 
 
102
 
103
- startOperation(this);
104
- this.curOp.forceUpdate = true;
105
- attachDoc(this, doc);
 
106
 
107
- if ((options.autofocus && !mobile) || cm.hasFocus())
108
- setTimeout(bind(onFocus, this), 20);
109
- else
110
- onBlur(this);
 
 
 
111
 
112
- for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
113
- optionHandlers[opt](this, options[opt], Init);
114
- maybeUpdateLineNumberWidth(this);
115
- if (options.finishInit) options.finishInit(this);
116
- for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
117
- endOperation(this);
118
- // Suppress optimizelegibility in Webkit, since it breaks text
119
- // measuring on line wrapping boundaries.
120
- if (webkit && options.lineWrapping &&
121
- getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
122
- display.lineDiv.style.textRendering = "auto";
 
 
 
 
123
  }
124
 
125
- // DISPLAY CONSTRUCTOR
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
- // The display handles the DOM integration, both for input reading
128
- // and content drawing. It holds references to DOM nodes and
129
- // display-related state.
 
 
130
 
131
- function Display(place, doc, input) {
132
- var d = this;
133
- this.input = input;
134
 
135
- // Covers bottom-right square when both scrollbars are present.
136
- d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
137
- d.scrollbarFiller.setAttribute("cm-not-content", "true");
138
- // Covers bottom of gutter when coverGutterNextToScrollbar is on
139
- // and h scrollbar is present.
140
- d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
141
- d.gutterFiller.setAttribute("cm-not-content", "true");
142
- // Will contain the actual code, positioned to cover the viewport.
143
- d.lineDiv = elt("div", null, "CodeMirror-code");
144
- // Elements are added to these to represent selection and cursors.
145
- d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
146
- d.cursorDiv = elt("div", null, "CodeMirror-cursors");
147
- // A visibility: hidden element used to find the size of things.
148
- d.measure = elt("div", null, "CodeMirror-measure");
149
- // When lines outside of the viewport are measured, they are drawn in this.
150
- d.lineMeasure = elt("div", null, "CodeMirror-measure");
151
- // Wraps everything that needs to exist inside the vertically-padded coordinate system
152
- d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
153
- null, "position: relative; outline: none");
154
- // Moved around its parent to cover visible view.
155
- d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
156
- // Set to the height of the document, allowing scrolling.
157
- d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
158
- d.sizerWidth = null;
159
- // Behavior of elts with overflow: auto and padding is
160
- // inconsistent across browsers. This is used to ensure the
161
- // scrollable area is big enough.
162
- d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
163
- // Will contain the gutters, if any.
164
- d.gutters = elt("div", null, "CodeMirror-gutters");
165
- d.lineGutter = null;
166
- // Actual scrollable element.
167
- d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
168
- d.scroller.setAttribute("tabIndex", "-1");
169
- // The element in which the editor lives.
170
- d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
171
 
172
- // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
173
- if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
174
- if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;
175
 
176
- if (place) {
177
- if (place.appendChild) place.appendChild(d.wrapper);
178
- else place(d.wrapper);
 
 
 
 
 
 
 
 
 
 
179
  }
 
180
 
181
- // Current rendered range (may be bigger than the view window).
182
- d.viewFrom = d.viewTo = doc.first;
183
- d.reportedViewFrom = d.reportedViewTo = doc.first;
184
- // Information about the rendered lines.
185
- d.view = [];
186
- d.renderedView = null;
187
- // Holds info about a single rendered line when it was rendered
188
- // for measurement, while not in view.
189
- d.externalMeasured = null;
190
- // Empty space (in pixels) above the view
191
- d.viewOffset = 0;
192
- d.lastWrapHeight = d.lastWrapWidth = 0;
193
- d.updateLineNumbers = null;
194
 
195
- d.nativeBarWidth = d.barHeight = d.barWidth = 0;
196
- d.scrollbarsClipped = false;
197
 
198
- // Used to only resize the line number gutter when necessary (when
199
- // the amount of lines crosses a boundary that makes its width change)
200
- d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
201
- // Set to true when a non-horizontal-scrolling line widget is
202
- // added. As an optimization, line widget aligning is skipped when
203
- // this is false.
204
- d.alignWidgets = false;
205
 
206
- d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
 
 
 
 
207
 
208
- // Tracks the maximum line length so that the horizontal scrollbar
209
- // can be kept static when scrolling.
210
- d.maxLine = null;
211
- d.maxLineLength = 0;
212
- d.maxLineChanged = false;
213
 
214
- // Used for measuring wheel scrolling granularity
215
- d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
 
 
 
 
 
 
 
 
 
216
 
217
- // True when shift is held down.
218
- d.shift = false;
 
 
 
 
 
 
 
 
219
 
220
- // Used to track whether anything happened since the context menu
221
- // was opened.
222
- d.selForContextMenu = null;
 
223
 
224
- d.activeTouch = null;
 
 
 
 
 
 
225
 
226
- input.init(d);
 
 
 
227
  }
228
 
229
- // STATE UPDATES
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
 
231
- // Used to get the editor into a consistent state again when options change.
232
 
233
- function loadMode(cm) {
234
- cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
235
- resetModeState(cm);
 
 
 
 
 
 
 
 
236
  }
237
 
238
- function resetModeState(cm) {
239
- cm.doc.iter(function(line) {
240
- if (line.stateAfter) line.stateAfter = null;
241
- if (line.styles) line.styles = null;
242
- });
243
- cm.doc.frontier = cm.doc.first;
244
- startWorker(cm, 100);
245
- cm.state.modeGen++;
246
- if (cm.curOp) regChange(cm);
247
- }
248
-
249
- function wrappingChanged(cm) {
250
- if (cm.options.lineWrapping) {
251
- addClass(cm.display.wrapper, "CodeMirror-wrap");
252
- cm.display.sizer.style.minWidth = "";
253
- cm.display.sizerWidth = null;
254
- } else {
255
- rmClass(cm.display.wrapper, "CodeMirror-wrap");
256
- findMaxLine(cm);
257
- }
258
- estimateLineHeights(cm);
259
- regChange(cm);
260
- clearCaches(cm);
261
- setTimeout(function(){updateScrollbars(cm);}, 100);
262
- }
263
-
264
- // Returns a function that estimates the height of a line, to use as
265
- // first approximation until the line becomes visible (and is thus
266
- // properly measurable).
267
- function estimateHeight(cm) {
268
- var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
269
- var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
270
- return function(line) {
271
- if (lineIsHidden(cm.doc, line)) return 0;
272
-
273
- var widgetsHeight = 0;
274
- if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {
275
- if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;
276
  }
277
-
278
- if (wrapping)
279
- return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
280
- else
281
- return widgetsHeight + th;
282
- };
283
- }
284
-
285
- function estimateLineHeights(cm) {
286
- var doc = cm.doc, est = estimateHeight(cm);
287
- doc.iter(function(line) {
288
- var estHeight = est(line);
289
- if (estHeight != line.height) updateLineHeight(line, estHeight);
290
- });
291
  }
292
 
293
- function themeChanged(cm) {
294
- cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
295
- cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
296
- clearCaches(cm);
297
- }
298
 
299
- function guttersChanged(cm) {
300
- updateGutters(cm);
301
- regChange(cm);
302
- setTimeout(function(){alignHorizontally(cm);}, 20);
303
- }
 
 
 
 
 
 
 
 
 
 
304
 
305
- // Rebuild the gutter elements, ensure the margin to the left of the
306
- // code matches their width.
307
- function updateGutters(cm) {
308
- var gutters = cm.display.gutters, specs = cm.options.gutters;
309
- removeChildren(gutters);
310
- for (var i = 0; i < specs.length; ++i) {
311
- var gutterClass = specs[i];
312
- var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
313
- if (gutterClass == "CodeMirror-linenumbers") {
314
- cm.display.lineGutter = gElt;
315
- gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
316
- }
 
 
 
 
317
  }
318
- gutters.style.display = i ? "" : "none";
319
- updateGutterSpace(cm);
320
- }
321
 
322
- function updateGutterSpace(cm) {
323
- var width = cm.display.gutters.offsetWidth;
324
- cm.display.sizer.style.marginLeft = width + "px";
325
- }
326
 
327
- // Compute the character length of a line, taking into account
328
- // collapsed ranges (see markText) that might hide parts, and join
329
- // other lines onto it.
330
- function lineLength(line) {
331
- if (line.height == 0) return 0;
332
- var len = line.text.length, merged, cur = line;
333
- while (merged = collapsedSpanAtStart(cur)) {
334
- var found = merged.find(0, true);
335
- cur = found.from.line;
336
- len += found.from.ch - found.to.ch;
337
- }
338
- cur = line;
339
- while (merged = collapsedSpanAtEnd(cur)) {
340
- var found = merged.find(0, true);
341
- len -= cur.text.length - found.from.ch;
342
- cur = found.to.line;
343
- len += cur.text.length - found.to.ch;
344
  }
345
- return len;
346
- }
347
 
348
- // Find the longest line in the document.
349
- function findMaxLine(cm) {
350
- var d = cm.display, doc = cm.doc;
351
- d.maxLine = getLine(doc, doc.first);
352
- d.maxLineLength = lineLength(d.maxLine);
353
- d.maxLineChanged = true;
354
- doc.iter(function(line) {
355
- var len = lineLength(line);
356
- if (len > d.maxLineLength) {
357
- d.maxLineLength = len;
358
- d.maxLine = line;
359
- }
360
- });
361
- }
362
 
363
- // Make sure the gutters options contains the element
364
- // "CodeMirror-linenumbers" when the lineNumbers option is true.
365
- function setGuttersForLineNumbers(options) {
366
- var found = indexOf(options.gutters, "CodeMirror-linenumbers");
367
- if (found == -1 && options.lineNumbers) {
368
- options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
369
- } else if (found > -1 && !options.lineNumbers) {
370
- options.gutters = options.gutters.slice(0);
371
- options.gutters.splice(found, 1);
372
- }
373
- }
374
 
375
- // SCROLLBARS
 
 
 
 
 
 
 
 
376
 
377
- // Prepare DOM reads needed to update the scrollbars. Done in one
378
- // shot to minimize update/measure roundtrips.
379
- function measureForScrollbars(cm) {
380
- var d = cm.display, gutterW = d.gutters.offsetWidth;
381
- var docH = Math.round(cm.doc.height + paddingVert(cm.display));
382
- return {
383
- clientHeight: d.scroller.clientHeight,
384
- viewHeight: d.wrapper.clientHeight,
385
- scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
386
- viewWidth: d.wrapper.clientWidth,
387
- barLeft: cm.options.fixedGutter ? gutterW : 0,
388
- docHeight: docH,
389
- scrollHeight: docH + scrollGap(cm) + d.barHeight,
390
- nativeBarWidth: d.nativeBarWidth,
391
- gutterWidth: gutterW
392
- };
393
- }
394
 
395
- function NativeScrollbars(place, scroll, cm) {
396
- this.cm = cm;
397
- var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
398
- var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
399
- place(vert); place(horiz);
 
 
 
 
 
400
 
401
- on(vert, "scroll", function() {
402
- if (vert.clientHeight) scroll(vert.scrollTop, "vertical");
403
- });
404
- on(horiz, "scroll", function() {
405
- if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
406
- });
 
 
 
 
 
 
 
 
 
407
 
408
- this.checkedOverlay = false;
409
- // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
410
- if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
411
- }
412
-
413
- NativeScrollbars.prototype = copyObj({
414
- update: function(measure) {
415
- var needsH = measure.scrollWidth > measure.clientWidth + 1;
416
- var needsV = measure.scrollHeight > measure.clientHeight + 1;
417
- var sWidth = measure.nativeBarWidth;
418
-
419
- if (needsV) {
420
- this.vert.style.display = "block";
421
- this.vert.style.bottom = needsH ? sWidth + "px" : "0";
422
- var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
423
- // A bug in IE8 can cause this value to be negative, so guard it.
424
- this.vert.firstChild.style.height =
425
- Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
426
- } else {
427
- this.vert.style.display = "";
428
- this.vert.firstChild.style.height = "0";
429
  }
430
 
431
- if (needsH) {
432
- this.horiz.style.display = "block";
433
- this.horiz.style.right = needsV ? sWidth + "px" : "0";
434
- this.horiz.style.left = measure.barLeft + "px";
435
- var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
436
- this.horiz.firstChild.style.width =
437
- (measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
438
- } else {
439
- this.horiz.style.display = "";
440
- this.horiz.firstChild.style.width = "0";
 
 
 
 
 
 
441
  }
442
 
443
- if (!this.checkedOverlay && measure.clientHeight > 0) {
444
- if (sWidth == 0) this.overlayHack();
445
- this.checkedOverlay = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
  }
447
 
448
- return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
449
- },
450
- setScrollLeft: function(pos) {
451
- if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
452
- },
453
- setScrollTop: function(pos) {
454
- if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
455
- },
456
- overlayHack: function() {
457
- var w = mac && !mac_geMountainLion ? "12px" : "18px";
458
- this.horiz.style.minHeight = this.vert.style.minWidth = w;
459
- var self = this;
460
- var barMouseDown = function(e) {
461
- if (e_target(e) != self.vert && e_target(e) != self.horiz)
462
- operation(self.cm, onMouseDown)(e);
463
- };
464
- on(this.vert, "mousedown", barMouseDown);
465
- on(this.horiz, "mousedown", barMouseDown);
466
- },
467
- clear: function() {
468
- var parent = this.horiz.parentNode;
469
- parent.removeChild(this.horiz);
470
- parent.removeChild(this.vert);
471
  }
472
- }, NativeScrollbars.prototype);
 
 
 
 
 
 
 
 
 
473
 
474
- function NullScrollbars() {}
475
 
476
- NullScrollbars.prototype = copyObj({
477
- update: function() { return {bottom: 0, right: 0}; },
478
- setScrollLeft: function() {},
479
- setScrollTop: function() {},
480
- clear: function() {}
481
- }, NullScrollbars.prototype);
482
 
483
- CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
484
 
485
- function initScrollbars(cm) {
486
- if (cm.display.scrollbars) {
487
- cm.display.scrollbars.clear();
488
- if (cm.display.scrollbars.addClass)
489
- rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);
 
 
 
490
  }
 
491
 
492
- cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
493
- cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
494
- // Prevent clicks in the scrollbars from killing focus
495
- on(node, "mousedown", function() {
496
- if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);
497
- });
498
- node.setAttribute("cm-not-content", "true");
499
- }, function(pos, axis) {
500
- if (axis == "horizontal") setScrollLeft(cm, pos);
501
- else setScrollTop(cm, pos);
502
- }, cm);
503
- if (cm.display.scrollbars.addClass)
504
- addClass(cm.display.wrapper, cm.display.scrollbars.addClass);
505
  }
506
 
507
- function updateScrollbars(cm, measure) {
508
- if (!measure) measure = measureForScrollbars(cm);
509
- var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
510
- updateScrollbarsInner(cm, measure);
511
- for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
512
- if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
513
- updateHeightsInViewport(cm);
514
- updateScrollbarsInner(cm, measureForScrollbars(cm));
515
- startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
 
 
 
516
  }
517
  }
518
 
519
- // Re-synchronize the fake scrollbars with the actual size of the
520
- // content.
521
- function updateScrollbarsInner(cm, measure) {
522
- var d = cm.display;
523
- var sizes = d.scrollbars.update(measure);
 
524
 
525
- d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
526
- d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
 
 
 
 
 
 
 
527
 
528
- if (sizes.right && sizes.bottom) {
529
- d.scrollbarFiller.style.display = "block";
530
- d.scrollbarFiller.style.height = sizes.bottom + "px";
531
- d.scrollbarFiller.style.width = sizes.right + "px";
532
- } else d.scrollbarFiller.style.display = "";
533
- if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
534
- d.gutterFiller.style.display = "block";
535
- d.gutterFiller.style.height = sizes.bottom + "px";
536
- d.gutterFiller.style.width = measure.gutterWidth + "px";
537
- } else d.gutterFiller.style.display = "";
538
  }
539
 
540
- // Compute the lines that are visible in a given viewport (defaults
541
- // the the current scroll position). viewport may contain top,
542
- // height, and ensure (see op.scrollToPos) properties.
543
- function visibleLines(display, doc, viewport) {
544
- var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
545
- top = Math.floor(top - paddingTop(display));
546
- var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
547
-
548
- var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
549
- // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
550
- // forces those lines into the viewport (if possible).
551
- if (viewport && viewport.ensure) {
552
- var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
553
- if (ensureFrom < from) {
554
- from = ensureFrom;
555
- to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
556
- } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
557
- from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
558
- to = ensureTo;
559
- }
560
- }
561
- return {from: from, to: Math.max(to, from + 1)};
562
  }
563
 
564
- // LINE NUMBERS
565
-
566
- // Re-align line numbers and gutter marks to compensate for
567
- // horizontal scrolling.
568
- function alignHorizontally(cm) {
569
- var display = cm.display, view = display.view;
570
- if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
571
- var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
572
- var gutterW = display.gutters.offsetWidth, left = comp + "px";
573
- for (var i = 0; i < view.length; i++) if (!view[i].hidden) {
574
- if (cm.options.fixedGutter && view[i].gutter)
575
- view[i].gutter.style.left = left;
576
- var align = view[i].alignable;
577
- if (align) for (var j = 0; j < align.length; j++)
578
- align[j].style.left = left;
579
- }
580
- if (cm.options.fixedGutter)
581
- display.gutters.style.left = (comp + gutterW) + "px";
582
  }
583
 
584
- // Used to ensure that the line number gutter is still the right
585
- // size for the current document size. Returns true when an update
586
- // is needed.
587
- function maybeUpdateLineNumberWidth(cm) {
588
- if (!cm.options.lineNumbers) return false;
589
- var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
590
- if (last.length != display.lineNumChars) {
591
- var test = display.measure.appendChild(elt("div", [elt("div", last)],
592
- "CodeMirror-linenumber CodeMirror-gutter-elt"));
593
- var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
594
- display.lineGutter.style.width = "";
595
- display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
596
- display.lineNumWidth = display.lineNumInnerWidth + padding;
597
- display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
598
- display.lineGutter.style.width = display.lineNumWidth + "px";
599
- updateGutterSpace(cm);
600
- return true;
601
- }
602
- return false;
603
- }
604
 
605
- function lineNumberFor(options, i) {
606
- return String(options.lineNumberFormatter(i + options.firstLineNumber));
 
607
  }
608
-
609
- // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
610
- // but using getBoundingClientRect to get a sub-pixel-accurate
611
- // result.
612
- function compensateForHScroll(display) {
613
- return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
614
  }
615
-
616
- // DISPLAY DRAWING
617
-
618
- function DisplayUpdate(cm, viewport, force) {
619
- var display = cm.display;
620
-
621
- this.viewport = viewport;
622
- // Store some values that we'll need later (but don't want to force a relayout for)
623
- this.visible = visibleLines(display, cm.doc, viewport);
624
- this.editorIsHidden = !display.wrapper.offsetWidth;
625
- this.wrapperHeight = display.wrapper.clientHeight;
626
- this.wrapperWidth = display.wrapper.clientWidth;
627
- this.oldDisplayWidth = displayWidth(cm);
628
- this.force = force;
629
- this.dims = getDimensions(cm);
630
- this.events = [];
631
  }
 
632
 
633
- DisplayUpdate.prototype.signal = function(emitter, type) {
634
- if (hasHandler(emitter, type))
635
- this.events.push(arguments);
636
- };
637
- DisplayUpdate.prototype.finish = function() {
638
- for (var i = 0; i < this.events.length; i++)
639
- signal.apply(null, this.events[i]);
640
- };
641
-
642
- function maybeClipScrollbars(cm) {
643
- var display = cm.display;
644
- if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
645
- display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
646
- display.heightForcer.style.height = scrollGap(cm) + "px";
647
- display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
648
- display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
649
- display.scrollbarsClipped = true;
650
  }
 
 
651
  }
652
 
653
- // Does the actual updating of the line display. Bails out
654
- // (returning false) when there is nothing to be done and forced is
655
- // false.
656
- function updateDisplayIfNeeded(cm, update) {
657
- var display = cm.display, doc = cm.doc;
 
 
 
658
 
659
- if (update.editorIsHidden) {
660
- resetView(cm);
661
- return false;
 
 
 
 
662
  }
 
 
 
 
 
663
 
664
- // Bail out if the visible area is already rendered and nothing changed.
665
- if (!update.force &&
666
- update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
667
- (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
668
- display.renderedView == display.view && countDirtyView(cm) == 0)
669
- return false;
 
 
 
 
 
670
 
671
- if (maybeUpdateLineNumberWidth(cm)) {
672
- resetView(cm);
673
- update.dims = getDimensions(cm);
 
 
 
 
 
 
 
 
 
 
 
 
 
674
  }
 
 
675
 
676
- // Compute a suitable new viewport (from & to)
677
- var end = doc.first + doc.size;
678
- var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
679
- var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
680
- if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
681
- if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
682
- if (sawCollapsedSpans) {
683
- from = visualLineNo(cm.doc, from);
684
- to = visualLineEndNo(cm.doc, to);
685
- }
686
 
687
- var different = from != display.viewFrom || to != display.viewTo ||
688
- display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
689
- adjustView(cm, from, to);
 
 
 
690
 
691
- display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
692
- // Position the mover div to align with the current scroll position
693
- cm.display.mover.style.top = display.viewOffset + "px";
 
 
 
 
 
694
 
695
- var toUpdate = countDirtyView(cm);
696
- if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
697
- (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
698
- return false;
699
 
700
- // For big changes, we hide the enclosing element during the
701
- // update, since that speeds up the operations on most browsers.
702
- var focused = activeElt();
703
- if (toUpdate > 4) display.lineDiv.style.display = "none";
704
- patchDisplay(cm, display.updateLineNumbers, update.dims);
705
- if (toUpdate > 4) display.lineDiv.style.display = "";
706
- display.renderedView = display.view;
707
- // There might have been a widget with a focused element that got
708
- // hidden or updated, if so re-focus it.
709
- if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();
710
 
711
- // Prevent selection and cursors from interfering with the scroll
712
- // width and height.
713
- removeChildren(display.cursorDiv);
714
- removeChildren(display.selectionDiv);
715
- display.gutters.style.height = 0;
716
 
717
- if (different) {
718
- display.lastWrapHeight = update.wrapperHeight;
719
- display.lastWrapWidth = update.wrapperWidth;
720
- startWorker(cm, 400);
 
 
 
 
 
 
 
 
 
 
721
  }
722
-
723
- display.updateLineNumbers = null;
724
-
725
- return true;
726
  }
727
 
728
- function postUpdateDisplay(cm, update) {
729
- var force = update.force, viewport = update.viewport;
730
- for (var first = true;; first = false) {
731
- if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {
732
- force = true;
733
- } else {
734
- force = false;
735
- // Clip forced viewport to actual scrollable area.
736
- if (viewport && viewport.top != null)
737
- viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
738
- // Updated line heights might result in the drawn area not
739
- // actually covering the viewport. Keep looping until it does.
740
- update.visible = visibleLines(cm.display, cm.doc, viewport);
741
- if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
742
- break;
743
  }
744
- if (!updateDisplayIfNeeded(cm, update)) break;
745
- updateHeightsInViewport(cm);
746
- var barMeasure = measureForScrollbars(cm);
747
- updateSelection(cm);
748
- setDocumentHeight(cm, barMeasure);
749
- updateScrollbars(cm, barMeasure);
750
  }
 
 
 
 
751
 
752
- update.signal(cm, "update", cm);
753
- if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
754
- update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
755
- cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
756
- }
757
  }
758
 
759
- function updateDisplaySimple(cm, viewport) {
760
- var update = new DisplayUpdate(cm, viewport);
761
- if (updateDisplayIfNeeded(cm, update)) {
762
- updateHeightsInViewport(cm);
763
- postUpdateDisplay(cm, update);
764
- var barMeasure = measureForScrollbars(cm);
765
- updateSelection(cm);
766
- setDocumentHeight(cm, barMeasure);
767
- updateScrollbars(cm, barMeasure);
768
- update.finish();
769
- }
770
  }
771
 
772
- function setDocumentHeight(cm, measure) {
773
- cm.display.sizer.style.minHeight = measure.docHeight + "px";
774
- var total = measure.docHeight + cm.display.barHeight;
775
- cm.display.heightForcer.style.top = total + "px";
776
- cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";
 
 
 
 
 
777
  }
778
 
779
- // Read the actual heights of the rendered lines, and update their
780
- // stored heights to match.
781
- function updateHeightsInViewport(cm) {
782
- var display = cm.display;
783
- var prevBottom = display.lineDiv.offsetTop;
784
- for (var i = 0; i < display.view.length; i++) {
785
- var cur = display.view[i], height;
786
- if (cur.hidden) continue;
787
- if (ie && ie_version < 8) {
788
- var bot = cur.node.offsetTop + cur.node.offsetHeight;
789
- height = bot - prevBottom;
790
- prevBottom = bot;
791
- } else {
792
- var box = cur.node.getBoundingClientRect();
793
- height = box.bottom - box.top;
794
- }
795
- var diff = cur.line.height - height;
796
- if (height < 2) height = textHeight(display);
797
- if (diff > .001 || diff < -.001) {
798
- updateLineHeight(cur.line, height);
799
- updateWidgetHeight(cur.line);
800
- if (cur.rest) for (var j = 0; j < cur.rest.length; j++)
801
- updateWidgetHeight(cur.rest[j]);
802
- }
803
  }
 
804
  }
805
 
806
- // Read and store the height of line widgets associated with the
807
- // given line.
808
- function updateWidgetHeight(line) {
809
- if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
810
- line.widgets[i].height = line.widgets[i].node.offsetHeight;
811
- }
812
-
813
- // Do a bulk-read of the DOM positions and sizes needed to draw the
814
- // view, so that we don't interleave reading and writing to the DOM.
815
- function getDimensions(cm) {
816
- var d = cm.display, left = {}, width = {};
817
- var gutterLeft = d.gutters.clientLeft;
818
- for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
819
- left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
820
- width[cm.options.gutters[i]] = n.clientWidth;
821
- }
822
- return {fixedPos: compensateForHScroll(d),
823
- gutterTotalWidth: d.gutters.offsetWidth,
824
- gutterLeft: left,
825
- gutterWidth: width,
826
- wrapperWidth: d.wrapper.clientWidth};
827
  }
828
 
829
- // Sync the actual display DOM structure with display.view, removing
830
- // nodes for lines that are no longer in view, and creating the ones
831
- // that are not there yet, and updating the ones that are out of
832
- // date.
833
- function patchDisplay(cm, updateNumbersFrom, dims) {
834
- var display = cm.display, lineNumbers = cm.options.lineNumbers;
835
- var container = display.lineDiv, cur = container.firstChild;
836
 
837
- function rm(node) {
838
- var next = node.nextSibling;
839
- // Works around a throw-scroll bug in OS X Webkit
840
- if (webkit && mac && cm.display.currentWheelTarget == node)
841
- node.style.display = "none";
842
- else
843
- node.parentNode.removeChild(node);
844
- return next;
845
- }
846
 
847
- var view = display.view, lineN = display.viewFrom;
848
- // Loop over the elements in the view, syncing cur (the DOM nodes
849
- // in display.lineDiv) with the view as we go.
850
- for (var i = 0; i < view.length; i++) {
851
- var lineView = view[i];
852
- if (lineView.hidden) {
853
- } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
854
- var node = buildLineElement(cm, lineView, lineN, dims);
855
- container.insertBefore(node, cur);
856
- } else { // Already drawn
857
- while (cur != lineView.node) cur = rm(cur);
858
- var updateNumber = lineNumbers && updateNumbersFrom != null &&
859
- updateNumbersFrom <= lineN && lineView.lineNumber;
860
- if (lineView.changes) {
861
- if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;
862
- updateLineForChanges(cm, lineView, lineN, dims);
863
- }
864
- if (updateNumber) {
865
- removeChildren(lineView.lineNumber);
866
- lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
867
- }
868
- cur = lineView.node.nextSibling;
869
- }
870
- lineN += lineView.size;
871
- }
872
- while (cur) cur = rm(cur);
873
- }
874
 
875
- // When an aspect of a line changes, a string is added to
876
- // lineView.changes. This updates the relevant part of the line's
877
- // DOM structure.
878
- function updateLineForChanges(cm, lineView, lineN, dims) {
879
- for (var j = 0; j < lineView.changes.length; j++) {
880
- var type = lineView.changes[j];
881
- if (type == "text") updateLineText(cm, lineView);
882
- else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
883
- else if (type == "class") updateLineClasses(lineView);
884
- else if (type == "widget") updateLineWidgets(cm, lineView, dims);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
885
  }
886
- lineView.changes = null;
887
- }
888
-
889
- // Lines with gutter elements, widgets or a background class need to
890
- // be wrapped, and have the extra elements added to the wrapper div
891
- function ensureLineWrapped(lineView) {
892
- if (lineView.node == lineView.text) {
893
- lineView.node = elt("div", null, null, "position: relative");
894
- if (lineView.text.parentNode)
895
- lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
896
- lineView.node.appendChild(lineView.text);
897
- if (ie && ie_version < 8) lineView.node.style.zIndex = 2;
 
 
 
 
 
 
 
898
  }
899
- return lineView.node;
900
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
901
 
902
- function updateLineBackground(lineView) {
903
- var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
904
- if (cls) cls += " CodeMirror-linebackground";
905
- if (lineView.background) {
906
- if (cls) lineView.background.className = cls;
907
- else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
908
- } else if (cls) {
909
- var wrap = ensureLineWrapped(lineView);
910
- lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
 
 
911
  }
 
912
  }
913
 
914
- // Wrapper around buildLineContent which will reuse the structure
915
- // in display.externalMeasured when possible.
916
- function getLineContent(cm, lineView) {
917
- var ext = cm.display.externalMeasured;
918
- if (ext && ext.line == lineView.line) {
919
- cm.display.externalMeasured = null;
920
- lineView.measure = ext.measure;
921
- return ext.built;
922
- }
923
- return buildLineContent(cm, lineView);
 
 
924
  }
925
-
926
- // Redraw the line's text. Interacts with the background and text
927
- // classes because the mode may output tokens that influence these
928
- // classes.
929
- function updateLineText(cm, lineView) {
930
- var cls = lineView.text.className;
931
- var built = getLineContent(cm, lineView);
932
- if (lineView.text == lineView.node) lineView.node = built.pre;
933
- lineView.text.parentNode.replaceChild(built.pre, lineView.text);
934
- lineView.text = built.pre;
935
- if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
936
- lineView.bgClass = built.bgClass;
937
- lineView.textClass = built.textClass;
938
- updateLineClasses(lineView);
939
- } else if (cls) {
940
- lineView.text.className = cls;
941
- }
942
  }
943
 
944
- function updateLineClasses(lineView) {
945
- updateLineBackground(lineView);
946
- if (lineView.line.wrapClass)
947
- ensureLineWrapped(lineView).className = lineView.line.wrapClass;
948
- else if (lineView.node != lineView.text)
949
- lineView.node.className = "";
950
- var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
951
- lineView.text.className = textClass || "";
952
  }
953
 
954
- function updateLineGutter(cm, lineView, lineN, dims) {
955
- if (lineView.gutter) {
956
- lineView.node.removeChild(lineView.gutter);
957
- lineView.gutter = null;
958
- }
959
- var markers = lineView.line.gutterMarkers;
960
- if (cm.options.lineNumbers || markers) {
961
- var wrap = ensureLineWrapped(lineView);
962
- var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
963
- (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
964
- "px; width: " + dims.gutterTotalWidth + "px");
965
- cm.display.input.setUneditable(gutterWrap);
966
- wrap.insertBefore(gutterWrap, lineView.text);
967
- if (lineView.line.gutterClass)
968
- gutterWrap.className += " " + lineView.line.gutterClass;
969
- if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
970
- lineView.lineNumber = gutterWrap.appendChild(
971
- elt("div", lineNumberFor(cm.options, lineN),
972
- "CodeMirror-linenumber CodeMirror-gutter-elt",
973
- "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
974
- + cm.display.lineNumInnerWidth + "px"));
975
- if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {
976
- var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
977
- if (found)
978
- gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
979
- dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
980
  }
981
  }
 
982
  }
983
 
984
- function updateLineWidgets(cm, lineView, dims) {
985
- if (lineView.alignable) lineView.alignable = null;
986
- for (var node = lineView.node.firstChild, next; node; node = next) {
987
- var next = node.nextSibling;
988
- if (node.className == "CodeMirror-linewidget")
989
- lineView.node.removeChild(node);
 
 
 
 
 
 
 
 
 
 
 
 
990
  }
991
- insertLineWidgets(cm, lineView, dims);
992
  }
993
 
994
- // Build a line's DOM representation from scratch
995
- function buildLineElement(cm, lineView, lineN, dims) {
996
- var built = getLineContent(cm, lineView);
997
- lineView.text = lineView.node = built.pre;
998
- if (built.bgClass) lineView.bgClass = built.bgClass;
999
- if (built.textClass) lineView.textClass = built.textClass;
1000
-
1001
- updateLineClasses(lineView);
1002
- updateLineGutter(cm, lineView, lineN, dims);
1003
- insertLineWidgets(cm, lineView, dims);
1004
- return lineView.node;
1005
- }
1006
 
1007
- // A lineView may contain multiple logical lines (when merged by
1008
- // collapsed spans). The widgets for all of them need to be drawn.
1009
- function insertLineWidgets(cm, lineView, dims) {
1010
- insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
1011
- if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
1012
- insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);
1013
  }
1014
 
1015
- function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
1016
- if (!line.widgets) return;
1017
- var wrap = ensureLineWrapped(lineView);
1018
- for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
1019
- var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
1020
- if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");
1021
- positionLineWidget(widget, node, lineView, dims);
1022
- cm.display.input.setUneditable(node);
1023
- if (allowAbove && widget.above)
1024
- wrap.insertBefore(node, lineView.gutter || lineView.text);
1025
- else
1026
- wrap.appendChild(node);
1027
- signalLater(widget, "redraw");
1028
- }
1029
- }
1030
 
1031
- function positionLineWidget(widget, node, lineView, dims) {
1032
- if (widget.noHScroll) {
1033
- (lineView.alignable || (lineView.alignable = [])).push(node);
1034
- var width = dims.wrapperWidth;
1035
- node.style.left = dims.fixedPos + "px";
1036
- if (!widget.coverGutter) {
1037
- width -= dims.gutterTotalWidth;
1038
- node.style.paddingLeft = dims.gutterTotalWidth + "px";
1039
- }
1040
- node.style.width = width + "px";
1041
- }
1042
- if (widget.coverGutter) {
1043
- node.style.zIndex = 5;
1044
- node.style.position = "relative";
1045
- if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
1046
- }
1047
  }
1048
 
1049
- // POSITION OBJECT
1050
-
1051
- // A Pos instance represents a position within the text.
1052
- var Pos = CodeMirror.Pos = function(line, ch) {
1053
- if (!(this instanceof Pos)) return new Pos(line, ch);
1054
- this.line = line; this.ch = ch;
1055
- };
1056
-
1057
  // Compare two positions, return 0 if they are the same, a negative
1058
  // number when a is less, and a positive number otherwise.
1059
- var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };
1060
 
1061
- function copyPos(x) {return Pos(x.line, x.ch);}
1062
- function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
1063
- function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
1064
 
1065
- // INPUT HANDLING
 
 
1066
 
1067
- function ensureFocus(cm) {
1068
- if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
 
 
 
 
 
 
1069
  }
1070
-
1071
- function isReadOnly(cm) {
1072
- return cm.options.readOnly || cm.doc.cantEdit;
 
 
 
 
 
 
 
1073
  }
1074
 
1075
- // This will be set to an array of strings when copying, so that,
1076
- // when pasting, we know what kind of selections the copied text
1077
- // was made out of.
1078
- var lastCopied = null;
1079
 
1080
- function applyTextInput(cm, inserted, deleted, sel) {
1081
- var doc = cm.doc;
1082
- cm.display.shift = false;
1083
- if (!sel) sel = doc.sel;
1084
-
1085
- var textLines = splitLines(inserted), multiPaste = null;
1086
- // When pasing N lines into N selections, insert one line per selection
1087
- if (cm.state.pasteIncoming && sel.ranges.length > 1) {
1088
- if (lastCopied && lastCopied.join("\n") == inserted)
1089
- multiPaste = sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
1090
- else if (textLines.length == sel.ranges.length)
1091
- multiPaste = map(textLines, function(l) { return [l]; });
1092
- }
1093
-
1094
- // Normal behavior is to insert the new text into every selection
1095
- for (var i = sel.ranges.length - 1; i >= 0; i--) {
1096
- var range = sel.ranges[i];
1097
- var from = range.from(), to = range.to();
1098
- if (range.empty()) {
1099
- if (deleted && deleted > 0) // Handle deletion
1100
- from = Pos(from.line, from.ch - deleted);
1101
- else if (cm.state.overwrite && !cm.state.pasteIncoming) // Handle overwrite
1102
- to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
1103
- }
1104
- var updateInput = cm.curOp.updateInput;
1105
- var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
1106
- origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
1107
- makeChange(cm.doc, changeEvent);
1108
- signalLater(cm, "inputRead", cm, changeEvent);
1109
- // When an 'electric' character is inserted, immediately trigger a reindent
1110
- if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
1111
- cm.options.smartIndent && range.head.ch < 100 &&
1112
- (!i || sel.ranges[i - 1].head.line != range.head.line)) {
1113
- var mode = cm.getModeAt(range.head);
1114
- var end = changeEnd(changeEvent);
1115
- if (mode.electricChars) {
1116
- for (var j = 0; j < mode.electricChars.length; j++)
1117
- if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
1118
- indentLine(cm, end.line, "smart");
1119
- break;
1120
- }
1121
- } else if (mode.electricInput) {
1122
- if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
1123
- indentLine(cm, end.line, "smart");
1124
- }
1125
- }
1126
- }
1127
- ensureCursorVisible(cm);
1128
- cm.curOp.updateInput = updateInput;
1129
- cm.curOp.typing = true;
1130
- cm.state.pasteIncoming = cm.state.cutIncoming = false;
1131
- }
1132
-
1133
- function copyableRanges(cm) {
1134
- var text = [], ranges = [];
1135
- for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
1136
- var line = cm.doc.sel.ranges[i].head.line;
1137
- var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
1138
- ranges.push(lineRange);
1139
- text.push(cm.getRange(lineRange.anchor, lineRange.head));
1140
- }
1141
- return {text: text, ranges: ranges};
1142
- }
1143
-
1144
- function disableBrowserMagic(field) {
1145
- field.setAttribute("autocorrect", "off");
1146
- field.setAttribute("autocapitalize", "off");
1147
- field.setAttribute("spellcheck", "false");
1148
- }
1149
-
1150
- // TEXTAREA INPUT STYLE
1151
 
1152
- function TextareaInput(cm) {
1153
- this.cm = cm;
1154
- // See input.poll and input.reset
1155
- this.prevInput = "";
 
1156
 
1157
- // Flag that indicates whether we expect input to appear real soon
1158
- // now (after some event like 'keypress' or 'input') and are
1159
- // polling intensively.
1160
- this.pollingFast = false;
1161
- // Self-resetting timeout for the poller
1162
- this.polling = new Delayed();
1163
- // Tracks when input.reset has punted to just putting a short
1164
- // string into the textarea instead of the full selection.
1165
- this.inaccurateSelection = false;
1166
- // Used to work around IE issue with selection being forgotten when focus moves away from textarea
1167
- this.hasSelection = false;
1168
  };
1169
 
1170
- function hiddenTextarea() {
1171
- var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
1172
- var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
1173
- // The textarea is kept positioned near the cursor to prevent the
1174
- // fact that it'll be scrolled into view on input from scrolling
1175
- // our fake cursor out of view. On webkit, when wrap=off, paste is
1176
- // very slow. So make the area wide instead.
1177
- if (webkit) te.style.width = "1000px";
1178
- else te.setAttribute("wrap", "off");
1179
- // If border: 0; -- iOS fails to open keyboard (issue #1287)
1180
- if (ios) te.style.border = "1px solid black";
1181
- disableBrowserMagic(te);
1182
- return div;
1183
- }
1184
 
1185
- TextareaInput.prototype = copyObj({
1186
- init: function(display) {
1187
- var input = this, cm = this.cm;
 
 
 
1188
 
1189
- // Wraps and hides input textarea
1190
- var div = this.wrapper = hiddenTextarea();
1191
- // The semihidden textarea that is focused when the editor is
1192
- // focused, and receives input.
1193
- var te = this.textarea = div.firstChild;
1194
- display.wrapper.insertBefore(div, display.wrapper.firstChild);
1195
 
1196
- // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
1197
- if (ios) te.style.width = "0px";
1198
 
1199
- on(te, "input", function() {
1200
- if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;
1201
- input.poll();
1202
- });
 
 
 
 
 
 
 
 
1203
 
1204
- on(te, "paste", function() {
1205
- // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
1206
- // Add a char to the end of textarea before paste occur so that
1207
- // selection doesn't span to the end of textarea.
1208
- if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
1209
- var start = te.selectionStart, end = te.selectionEnd;
1210
- te.value += "$";
1211
- // The selection end needs to be set before the start, otherwise there
1212
- // can be an intermediate non-empty selection between the two, which
1213
- // can override the middle-click paste buffer on linux and cause the
1214
- // wrong thing to get pasted.
1215
- te.selectionEnd = end;
1216
- te.selectionStart = start;
1217
- cm.state.fakedLastChar = true;
1218
  }
1219
- cm.state.pasteIncoming = true;
1220
- input.fastPoll();
1221
- });
1222
-
1223
- function prepareCopyCut(e) {
1224
- if (cm.somethingSelected()) {
1225
- lastCopied = cm.getSelections();
1226
- if (input.inaccurateSelection) {
1227
- input.prevInput = "";
1228
- input.inaccurateSelection = false;
1229
- te.value = lastCopied.join("\n");
1230
- selectInput(te);
1231
- }
1232
  } else {
1233
- var ranges = copyableRanges(cm);
1234
- lastCopied = ranges.text;
1235
- if (e.type == "cut") {
1236
- cm.setSelections(ranges.ranges, null, sel_dontScroll);
1237
- } else {
1238
- input.prevInput = "";
1239
- te.value = ranges.text.join("\n");
1240
- selectInput(te);
1241
  }
1242
  }
1243
- if (e.type == "cut") cm.state.cutIncoming = true;
1244
- }
1245
- on(te, "cut", prepareCopyCut);
1246
- on(te, "copy", prepareCopyCut);
1247
-
1248
- on(display.scroller, "paste", function(e) {
1249
- if (eventInWidget(display, e)) return;
1250
- cm.state.pasteIncoming = true;
1251
- input.focus();
1252
- });
1253
-
1254
- // Prevent normal selection in the editor (we handle our own)
1255
- on(display.lineSpace, "selectstart", function(e) {
1256
- if (!eventInWidget(display, e)) e_preventDefault(e);
1257
- });
1258
- },
1259
-
1260
- prepareSelection: function() {
1261
- // Redraw the selection and/or cursor
1262
- var cm = this.cm, display = cm.display, doc = cm.doc;
1263
- var result = prepareSelection(cm);
1264
-
1265
- // Move the hidden textarea near the cursor to prevent scrolling artifacts
1266
- if (cm.options.moveInputWithCursor) {
1267
- var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
1268
- var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
1269
- result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
1270
- headPos.top + lineOff.top - wrapOff.top));
1271
- result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
1272
- headPos.left + lineOff.left - wrapOff.left));
1273
- }
1274
-
1275
- return result;
1276
- },
1277
 
1278
- showSelection: function(drawn) {
1279
- var cm = this.cm, display = cm.display;
1280
- removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
1281
- removeChildrenAndAdd(display.selectionDiv, drawn.selection);
1282
- if (drawn.teTop != null) {
1283
- this.wrapper.style.top = drawn.teTop + "px";
1284
- this.wrapper.style.left = drawn.teLeft + "px";
1285
- }
1286
- },
1287
 
1288
- // Reset the input to correspond to the selection (or to be empty,
1289
- // when not typing and nothing is selected)
1290
- reset: function(typing) {
1291
- if (this.contextMenuPending) return;
1292
- var minimal, selected, cm = this.cm, doc = cm.doc;
1293
- if (cm.somethingSelected()) {
1294
- this.prevInput = "";
1295
- var range = doc.sel.primary();
1296
- minimal = hasCopyEvent &&
1297
- (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
1298
- var content = minimal ? "-" : selected || cm.getSelection();
1299
- this.textarea.value = content;
1300
- if (cm.state.focused) selectInput(this.textarea);
1301
- if (ie && ie_version >= 9) this.hasSelection = content;
1302
- } else if (!typing) {
1303
- this.prevInput = this.textarea.value = "";
1304
- if (ie && ie_version >= 9) this.hasSelection = null;
1305
- }
1306
- this.inaccurateSelection = minimal;
1307
- },
1308
 
1309
- getField: function() { return this.textarea; },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1310
 
1311
- supportsTouch: function() { return false; },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1312
 
1313
- focus: function() {
1314
- if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
1315
- try { this.textarea.focus(); }
1316
- catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
1317
- }
1318
- },
 
 
 
 
 
 
 
1319
 
1320
- blur: function() { this.textarea.blur(); },
 
 
 
 
 
1321
 
1322
- resetPosition: function() {
1323
- this.wrapper.style.top = this.wrapper.style.left = 0;
1324
- },
 
 
 
 
 
1325
 
1326
- receivedFocus: function() { this.slowPoll(); },
 
 
 
 
 
1327
 
1328
- // Poll for input changes, using the normal rate of polling. This
1329
- // runs as long as the editor is focused.
1330
- slowPoll: function() {
1331
- var input = this;
1332
- if (input.pollingFast) return;
1333
- input.polling.set(this.cm.options.pollInterval, function() {
1334
- input.poll();
1335
- if (input.cm.state.focused) input.slowPoll();
1336
- });
1337
- },
 
 
 
 
1338
 
1339
- // When an event has just come in that is likely to add or change
1340
- // something in the input textarea, we poll faster, to ensure that
1341
- // the change appears on the screen quickly.
1342
- fastPoll: function() {
1343
- var missed = false, input = this;
1344
- input.pollingFast = true;
1345
- function p() {
1346
- var changed = input.poll();
1347
- if (!changed && !missed) {missed = true; input.polling.set(60, p);}
1348
- else {input.pollingFast = false; input.slowPoll();}
1349
- }
1350
- input.polling.set(20, p);
1351
- },
1352
 
1353
- // Read input from the textarea, and update the document to match.
1354
- // When something is selected, it is present in the textarea, and
1355
- // selected (unless it is huge, in which case a placeholder is
1356
- // used). When nothing is selected, the cursor sits after previously
1357
- // seen text (can be empty), which is stored in prevInput (we must
1358
- // not reset the textarea when typing, because that breaks IME).
1359
- poll: function() {
1360
- var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
1361
- // Since this is called a *lot*, try to bail out as cheaply as
1362
- // possible when it is clear that nothing happened. hasSelection
1363
- // will be the case when there is a lot of text in the textarea,
1364
- // in which case reading its value would be expensive.
1365
- if (!cm.state.focused || (hasSelection(input) && !prevInput) ||
1366
- isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
1367
- return false;
1368
- // See paste handler for more on the fakedLastChar kludge
1369
- if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
1370
- input.value = input.value.substring(0, input.value.length - 1);
1371
- cm.state.fakedLastChar = false;
1372
- }
1373
- var text = input.value;
1374
- // If nothing changed, bail.
1375
- if (text == prevInput && !cm.somethingSelected()) return false;
1376
- // Work around nonsensical selection resetting in IE9/10, and
1377
- // inexplicable appearance of private area unicode characters on
1378
- // some key combos in Mac (#2689).
1379
- if (ie && ie_version >= 9 && this.hasSelection === text ||
1380
- mac && /[\uf700-\uf7ff]/.test(text)) {
1381
- cm.display.input.reset();
1382
- return false;
1383
  }
1384
-
1385
- if (text.charCodeAt(0) == 0x200b && cm.doc.sel == cm.display.selForContextMenu && !prevInput)
1386
- prevInput = "\u200b";
1387
- // Find the part of the input that is actually new
1388
- var same = 0, l = Math.min(prevInput.length, text.length);
1389
- while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
1390
-
1391
- var self = this;
1392
- runInOp(cm, function() {
1393
- applyTextInput(cm, text.slice(same), prevInput.length - same);
1394
-
1395
- // Don't leave long text in the textarea, since it makes further polling slow
1396
- if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
1397
- else self.prevInput = text;
1398
- });
1399
- return true;
1400
- },
1401
-
1402
- ensurePolled: function() {
1403
- if (this.pollingFast && this.poll()) this.pollingFast = false;
1404
- },
1405
-
1406
- onKeyPress: function() {
1407
- if (ie && ie_version >= 9) this.hasSelection = null;
1408
- this.fastPoll();
1409
- },
1410
-
1411
- onContextMenu: function(e) {
1412
- var input = this, cm = input.cm, display = cm.display, te = input.textarea;
1413
- var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
1414
- if (!pos || presto) return; // Opera is difficult.
1415
-
1416
- // Reset the current text selection only if the click is done outside of the selection
1417
- // and 'resetSelectionOnContextMenu' option is true.
1418
- var reset = cm.options.resetSelectionOnContextMenu;
1419
- if (reset && cm.doc.sel.contains(pos) == -1)
1420
- operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
1421
-
1422
- var oldCSS = te.style.cssText;
1423
- input.wrapper.style.position = "absolute";
1424
- te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
1425
- "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
1426
- (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
1427
- "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
1428
- if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
1429
- display.input.focus();
1430
- if (webkit) window.scrollTo(null, oldScrollY);
1431
- display.input.reset();
1432
- // Adds "Select all" to context menu in FF
1433
- if (!cm.somethingSelected()) te.value = input.prevInput = " ";
1434
- input.contextMenuPending = true;
1435
- display.selForContextMenu = cm.doc.sel;
1436
- clearTimeout(display.detectingSelectAll);
1437
-
1438
- // Select-all will be greyed out if there's nothing to select, so
1439
- // this adds a zero-width space so that we can later check whether
1440
- // it got selected.
1441
- function prepareSelectAllHack() {
1442
- if (te.selectionStart != null) {
1443
- var selected = cm.somethingSelected();
1444
- var extval = te.value = "\u200b" + (selected ? te.value : "");
1445
- input.prevInput = selected ? "" : "\u200b";
1446
- te.selectionStart = 1; te.selectionEnd = extval.length;
1447
- // Re-set this, in case some other handler touched the
1448
- // selection in the meantime.
1449
- display.selForContextMenu = cm.doc.sel;
1450
- }
1451
  }
1452
- function rehide() {
1453
- input.contextMenuPending = false;
1454
- input.wrapper.style.position = "relative";
1455
- te.style.cssText = oldCSS;
1456
- if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
1457
-
1458
- // Try to detect the user choosing select-all
1459
- if (te.selectionStart != null) {
1460
- if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
1461
- var i = 0, poll = function() {
1462
- if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0)
1463
- operation(cm, commands.selectAll)(cm);
1464
- else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
1465
- else display.input.reset();
1466
- };
1467
- display.detectingSelectAll = setTimeout(poll, 200);
1468
  }
 
1469
  }
 
 
 
 
 
 
 
 
 
 
 
1470
 
1471
- if (ie && ie_version >= 9) prepareSelectAllHack();
1472
- if (captureRightClick) {
1473
- e_stop(e);
1474
- var mouseup = function() {
1475
- off(window, "mouseup", mouseup);
1476
- setTimeout(rehide, 20);
1477
- };
1478
- on(window, "mouseup", mouseup);
1479
- } else {
1480
- setTimeout(rehide, 50);
 
 
 
 
 
 
 
1481
  }
1482
- },
1483
-
1484
- setUneditable: nothing,
1485
 
1486
- needsContentAttribute: false
1487
- }, TextareaInput.prototype);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1488
 
1489
- // CONTENTEDITABLE INPUT STYLE
 
1490
 
1491
- function ContentEditableInput(cm) {
1492
- this.cm = cm;
1493
- this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
1494
- this.polling = new Delayed();
1495
- this.gracePeriod = false;
1496
  }
1497
 
1498
- ContentEditableInput.prototype = copyObj({
1499
- init: function(display) {
1500
- var input = this, cm = input.cm;
1501
- var div = input.div = display.lineDiv;
1502
- div.contentEditable = "true";
1503
- disableBrowserMagic(div);
1504
-
1505
- on(div, "paste", function(e) {
1506
- var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
1507
- if (pasted) {
1508
- e.preventDefault();
1509
- cm.replaceSelection(pasted, null, "paste");
1510
- }
1511
- });
1512
 
1513
- on(div, "compositionstart", function(e) {
1514
- var data = e.data;
1515
- input.composing = {sel: cm.doc.sel, data: data, startData: data};
1516
- if (!data) return;
1517
- var prim = cm.doc.sel.primary();
1518
- var line = cm.getLine(prim.head.line);
1519
- var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));
1520
- if (found > -1 && found <= prim.head.ch)
1521
- input.composing.sel = simpleSelection(Pos(prim.head.line, found),
1522
- Pos(prim.head.line, found + data.length));
1523
- });
1524
- on(div, "compositionupdate", function(e) {
1525
- input.composing.data = e.data;
1526
- });
1527
- on(div, "compositionend", function(e) {
1528
- var ours = input.composing;
1529
- if (!ours) return;
1530
- if (e.data != ours.startData && !/\u200b/.test(e.data))
1531
- ours.data = e.data;
1532
- // Need a small delay to prevent other code (input event,
1533
- // selection polling) from doing damage when fired right after
1534
- // compositionend.
1535
- setTimeout(function() {
1536
- if (!ours.handled)
1537
- input.applyComposition(ours);
1538
- if (input.composing == ours)
1539
- input.composing = null;
1540
- }, 50);
1541
- });
1542
 
1543
- on(div, "touchstart", function() {
1544
- input.forceCompositionEnd();
1545
- });
 
1546
 
1547
- on(div, "input", function() {
1548
- if (input.composing) return;
1549
- if (!input.pollContent())
1550
- runInOp(input.cm, function() {regChange(cm);});
1551
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1552
 
1553
- function onCopyCut(e) {
1554
- if (cm.somethingSelected()) {
1555
- lastCopied = cm.getSelections();
1556
- if (e.type == "cut") cm.replaceSelection("", null, "cut");
1557
- } else {
1558
- var ranges = copyableRanges(cm);
1559
- lastCopied = ranges.text;
1560
- if (e.type == "cut") {
1561
- cm.operation(function() {
1562
- cm.setSelections(ranges.ranges, 0, sel_dontScroll);
1563
- cm.replaceSelection("", null, "cut");
1564
- });
1565
- }
1566
- }
1567
- // iOS exposes the clipboard API, but seems to discard content inserted into it
1568
- if (e.clipboardData && !ios) {
1569
- e.preventDefault();
1570
- e.clipboardData.clearData();
1571
- e.clipboardData.setData("text/plain", lastCopied.join("\n"));
1572
- } else {
1573
- // Old-fashioned briefly-focus-a-textarea hack
1574
- var kludge = hiddenTextarea(), te = kludge.firstChild;
1575
- cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
1576
- te.value = lastCopied.join("\n");
1577
- var hadFocus = document.activeElement;
1578
- selectInput(te);
1579
- setTimeout(function() {
1580
- cm.display.lineSpace.removeChild(kludge);
1581
- hadFocus.focus();
1582
- }, 50);
1583
- }
1584
  }
1585
- on(div, "copy", onCopyCut);
1586
- on(div, "cut", onCopyCut);
1587
- },
1588
-
1589
- prepareSelection: function() {
1590
- var result = prepareSelection(this.cm, false);
1591
- result.focus = this.cm.state.focused;
1592
- return result;
1593
- },
1594
-
1595
- showSelection: function(info) {
1596
- if (!info || !this.cm.display.view.length) return;
1597
- if (info.focus) this.showPrimarySelection();
1598
- this.showMultipleSelections(info);
1599
- },
1600
-
1601
- showPrimarySelection: function() {
1602
- var sel = window.getSelection(), prim = this.cm.doc.sel.primary();
1603
- var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);
1604
- var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);
1605
- if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
1606
- cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
1607
- cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
1608
- return;
1609
-
1610
- var start = posToDOM(this.cm, prim.from());
1611
- var end = posToDOM(this.cm, prim.to());
1612
- if (!start && !end) return;
1613
-
1614
- var view = this.cm.display.view;
1615
- var old = sel.rangeCount && sel.getRangeAt(0);
1616
- if (!start) {
1617
- start = {node: view[0].measure.map[2], offset: 0};
1618
- } else if (!end) { // FIXME dangerously hacky
1619
- var measure = view[view.length - 1].measure;
1620
- var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
1621
- end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
1622
- }
1623
-
1624
- try { var rng = range(start.node, start.offset, end.offset, end.node); }
1625
- catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
1626
- if (rng) {
1627
- sel.removeAllRanges();
1628
- sel.addRange(rng);
1629
- if (old && sel.anchorNode == null) sel.addRange(old);
1630
- else if (gecko) this.startGracePeriod();
1631
  }
1632
- this.rememberSelection();
1633
- },
1634
-
1635
- startGracePeriod: function() {
1636
- var input = this;
1637
- clearTimeout(this.gracePeriod);
1638
- this.gracePeriod = setTimeout(function() {
1639
- input.gracePeriod = false;
1640
- if (input.selectionChanged())
1641
- input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
1642
- }, 20);
1643
- },
1644
-
1645
- showMultipleSelections: function(info) {
1646
- removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
1647
- removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
1648
- },
1649
-
1650
- rememberSelection: function() {
1651
- var sel = window.getSelection();
1652
- this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
1653
- this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
1654
- },
1655
-
1656
- selectionInEditor: function() {
1657
- var sel = window.getSelection();
1658
- if (!sel.rangeCount) return false;
1659
- var node = sel.getRangeAt(0).commonAncestorContainer;
1660
- return contains(this.div, node);
1661
- },
1662
-
1663
- focus: function() {
1664
- if (this.cm.options.readOnly != "nocursor") this.div.focus();
1665
- },
1666
- blur: function() { this.div.blur(); },
1667
- getField: function() { return this.div; },
1668
 
1669
- supportsTouch: function() { return true; },
 
 
 
 
 
 
 
 
 
 
1670
 
1671
- receivedFocus: function() {
1672
- var input = this;
1673
- if (this.selectionInEditor())
1674
- this.pollSelection();
1675
- else
1676
- runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });
1677
 
1678
- function poll() {
1679
- if (input.cm.state.focused) {
1680
- input.pollSelection();
1681
- input.polling.set(input.cm.options.pollInterval, poll);
 
 
 
 
 
 
1682
  }
1683
  }
1684
- this.polling.set(this.cm.options.pollInterval, poll);
1685
- },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1686
 
1687
- selectionChanged: function() {
1688
- var sel = window.getSelection();
1689
- return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
1690
- sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
1691
- },
 
 
 
 
 
 
 
 
 
1692
 
1693
- pollSelection: function() {
1694
- if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
1695
- var sel = window.getSelection(), cm = this.cm;
1696
- this.rememberSelection();
1697
- var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
1698
- var head = domToPos(cm, sel.focusNode, sel.focusOffset);
1699
- if (anchor && head) runInOp(cm, function() {
1700
- setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
1701
- if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;
1702
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1703
  }
1704
- },
 
 
1705
 
1706
- pollContent: function() {
1707
- var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
1708
- var from = sel.from(), to = sel.to();
1709
- if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;
 
 
 
 
 
 
 
 
 
 
1710
 
1711
- var fromIndex;
1712
- if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
1713
- var fromLine = lineNo(display.view[0].line);
1714
- var fromNode = display.view[0].node;
1715
- } else {
1716
- var fromLine = lineNo(display.view[fromIndex].line);
1717
- var fromNode = display.view[fromIndex - 1].node.nextSibling;
1718
- }
1719
- var toIndex = findViewIndex(cm, to.line);
1720
- if (toIndex == display.view.length - 1) {
1721
- var toLine = display.viewTo - 1;
1722
- var toNode = display.view[toIndex].node;
1723
- } else {
1724
- var toLine = lineNo(display.view[toIndex + 1].line) - 1;
1725
- var toNode = display.view[toIndex + 1].node.previousSibling;
1726
- }
1727
-
1728
- var newText = splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
1729
- var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
1730
- while (newText.length > 1 && oldText.length > 1) {
1731
- if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
1732
- else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
1733
- else break;
1734
- }
1735
-
1736
- var cutFront = 0, cutEnd = 0;
1737
- var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
1738
- while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
1739
- ++cutFront;
1740
- var newBot = lst(newText), oldBot = lst(oldText);
1741
- var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
1742
- oldBot.length - (oldText.length == 1 ? cutFront : 0));
1743
- while (cutEnd < maxCutEnd &&
1744
- newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
1745
- ++cutEnd;
1746
-
1747
- newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);
1748
- newText[0] = newText[0].slice(cutFront);
1749
-
1750
- var chFrom = Pos(fromLine, cutFront);
1751
- var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
1752
- if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
1753
- replaceRange(cm.doc, newText, chFrom, chTo, "+input");
1754
- return true;
1755
- }
1756
- },
1757
 
1758
- ensurePolled: function() {
1759
- this.forceCompositionEnd();
1760
- },
1761
- reset: function() {
1762
- this.forceCompositionEnd();
1763
- },
1764
- forceCompositionEnd: function() {
1765
- if (!this.composing || this.composing.handled) return;
1766
- this.applyComposition(this.composing);
1767
- this.composing.handled = true;
1768
- this.div.blur();
1769
- this.div.focus();
1770
- },
1771
- applyComposition: function(composing) {
1772
- if (composing.data && composing.data != composing.startData)
1773
- operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
1774
- },
1775
 
1776
- setUneditable: function(node) {
1777
- node.setAttribute("contenteditable", "false");
1778
- },
 
 
 
 
 
 
 
 
 
 
 
1779
 
1780
- onKeyPress: function(e) {
1781
- e.preventDefault();
1782
- operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
1783
- },
 
 
 
 
 
1784
 
1785
- onContextMenu: nothing,
1786
- resetPosition: nothing,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1787
 
1788
- needsContentAttribute: true
1789
- }, ContentEditableInput.prototype);
 
 
 
 
 
 
 
 
1790
 
1791
- function posToDOM(cm, pos) {
1792
- var view = findViewForLine(cm, pos.line);
1793
- if (!view || view.hidden) return null;
1794
- var line = getLine(cm.doc, pos.line);
1795
- var info = mapFromLineView(view, line, pos.line);
 
1796
 
1797
- var order = getOrder(line), side = "left";
1798
- if (order) {
1799
- var partPos = getBidiPartAt(order, pos.ch);
1800
- side = partPos % 2 ? "right" : "left";
 
 
 
1801
  }
1802
- var result = nodeAndOffsetInLineMap(info.map, pos.ch, "left");
1803
- result.offset = result.collapse == "right" ? result.end : result.start;
1804
- return result;
1805
  }
1806
 
1807
- function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }
 
 
 
 
 
 
1808
 
1809
- function domToPos(cm, node, offset) {
1810
- var lineNode;
1811
- if (node == cm.display.lineDiv) {
1812
- lineNode = cm.display.lineDiv.childNodes[offset];
1813
- if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);
1814
- node = null; offset = 0;
1815
- } else {
1816
- for (lineNode = node;; lineNode = lineNode.parentNode) {
1817
- if (!lineNode || lineNode == cm.display.lineDiv) return null;
1818
- if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;
1819
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1820
  }
1821
- for (var i = 0; i < cm.display.view.length; i++) {
1822
- var lineView = cm.display.view[i];
1823
- if (lineView.node == lineNode)
1824
- return locateNodeInLineView(lineView, node, offset);
 
 
 
 
1825
  }
1826
  }
1827
 
1828
- function locateNodeInLineView(lineView, node, offset) {
1829
- var wrapper = lineView.text.firstChild, bad = false;
1830
- if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);
1831
- if (node == wrapper) {
1832
- bad = true;
1833
- node = wrapper.childNodes[offset];
1834
- offset = 0;
1835
- if (!node) {
1836
- var line = lineView.rest ? lst(lineView.rest) : lineView.line;
1837
- return badPos(Pos(lineNo(line), line.text.length), bad);
 
 
 
 
 
1838
  }
1839
  }
 
 
1840
 
1841
- var textNode = node.nodeType == 3 ? node : null, topNode = node;
1842
- if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
1843
- textNode = node.firstChild;
1844
- if (offset) offset = textNode.nodeValue.length;
 
 
 
 
 
 
1845
  }
1846
- while (topNode.parentNode != wrapper) topNode = topNode.parentNode;
1847
- var measure = lineView.measure, maps = measure.maps;
1848
-
1849
- function find(textNode, topNode, offset) {
1850
- for (var i = -1; i < (maps ? maps.length : 0); i++) {
1851
- var map = i < 0 ? measure.map : maps[i];
1852
- for (var j = 0; j < map.length; j += 3) {
1853
- var curNode = map[j + 2];
1854
- if (curNode == textNode || curNode == topNode) {
1855
- var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
1856
- var ch = map[j] + offset;
1857
- if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];
1858
- return Pos(line, ch);
1859
- }
1860
- }
1861
- }
1862
- }
1863
- var found = find(textNode, topNode, offset);
1864
- if (found) return badPos(found, bad);
1865
-
1866
- // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
1867
- for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
1868
- found = find(after, after.firstChild, 0);
1869
- if (found)
1870
- return badPos(Pos(found.line, found.ch - dist), bad);
1871
- else
1872
- dist += after.textContent.length;
1873
- }
1874
- for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {
1875
- found = find(before, before.firstChild, -1);
1876
- if (found)
1877
- return badPos(Pos(found.line, found.ch + dist), bad);
1878
- else
1879
- dist += after.textContent.length;
1880
  }
 
1881
  }
1882
 
1883
- function domTextBetween(cm, from, to, fromLine, toLine) {
1884
- var text = "", closing = false;
1885
- function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
1886
- function walk(node) {
1887
- if (node.nodeType == 1) {
1888
- var cmText = node.getAttribute("cm-text");
1889
- if (cmText != null) {
1890
- if (cmText == "") cmText = node.textContent.replace(/\u200b/g, "");
1891
- text += cmText;
1892
- return;
1893
- }
1894
- var markerID = node.getAttribute("cm-marker"), range;
1895
- if (markerID) {
1896
- var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
1897
- if (found.length && (range = found[0].find()))
1898
- text += getBetween(cm.doc, range.from, range.to).join("\n");
1899
- return;
1900
- }
1901
- if (node.getAttribute("contenteditable") == "false") return;
1902
- for (var i = 0; i < node.childNodes.length; i++)
1903
- walk(node.childNodes[i]);
1904
- if (/^(pre|div|p)$/i.test(node.nodeName))
1905
- closing = true;
1906
- } else if (node.nodeType == 3) {
1907
- var val = node.nodeValue;
1908
- if (!val) return;
1909
- if (closing) {
1910
- text += "\n";
1911
- closing = false;
1912
- }
1913
- text += val;
1914
  }
1915
- }
1916
- for (;;) {
1917
- walk(from);
1918
- if (from == to) break;
1919
- from = from.nextSibling;
1920
- }
1921
- return text;
1922
  }
1923
 
1924
- CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
1925
-
1926
- // SELECTION / CURSOR
1927
-
1928
- // Selection objects are immutable. A new one is created every time
1929
- // the selection changes. A selection is one or more non-overlapping
1930
- // (and non-touching) ranges, sorted, and an integer that indicates
1931
- // which one is the primary selection (the one that's scrolled into
1932
- // view, that getCursor returns, etc).
1933
- function Selection(ranges, primIndex) {
1934
- this.ranges = ranges;
1935
- this.primIndex = primIndex;
1936
- }
1937
 
1938
- Selection.prototype = {
1939
- primary: function() { return this.ranges[this.primIndex]; },
1940
- equals: function(other) {
1941
- if (other == this) return true;
1942
- if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;
1943
- for (var i = 0; i < this.ranges.length; i++) {
1944
- var here = this.ranges[i], there = other.ranges[i];
1945
- if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;
1946
- }
1947
- return true;
1948
- },
1949
- deepCopy: function() {
1950
- for (var out = [], i = 0; i < this.ranges.length; i++)
1951
- out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
1952
- return new Selection(out, this.primIndex);
1953
- },
1954
- somethingSelected: function() {
1955
- for (var i = 0; i < this.ranges.length; i++)
1956
- if (!this.ranges[i].empty()) return true;
1957
- return false;
1958
- },
1959
- contains: function(pos, end) {
1960
- if (!end) end = pos;
1961
- for (var i = 0; i < this.ranges.length; i++) {
1962
- var range = this.ranges[i];
1963
- if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
1964
- return i;
1965
- }
1966
- return -1;
1967
- }
1968
  };
1969
 
1970
- function Range(anchor, head) {
1971
- this.anchor = anchor; this.head = head;
1972
- }
1973
-
1974
- Range.prototype = {
1975
- from: function() { return minPos(this.anchor, this.head); },
1976
- to: function() { return maxPos(this.anchor, this.head); },
1977
- empty: function() {
1978
- return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
1979
- }
1980
- };
1981
 
1982
- // Take an unsorted, potentially overlapping set of ranges, and
1983
- // build a selection out of it. 'Consumes' ranges array (modifying
1984
- // it).
1985
- function normalizeSelection(ranges, primIndex) {
1986
- var prim = ranges[primIndex];
1987
- ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });
1988
- primIndex = indexOf(ranges, prim);
1989
- for (var i = 1; i < ranges.length; i++) {
1990
- var cur = ranges[i], prev = ranges[i - 1];
1991
- if (cmp(prev.to(), cur.from()) >= 0) {
1992
- var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
1993
- var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
1994
- if (i <= primIndex) --primIndex;
1995
- ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
1996
- }
1997
- }
1998
- return new Selection(ranges, primIndex);
1999
  }
2000
 
2001
- function simpleSelection(anchor, head) {
2002
- return new Selection([new Range(anchor, head || anchor)], 0);
 
 
2003
  }
2004
 
2005
- // Most of the external API clips given positions to make sure they
2006
- // actually exist within the document.
2007
- function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
2008
- function clipPos(doc, pos) {
2009
- if (pos.line < doc.first) return Pos(doc.first, 0);
2010
- var last = doc.first + doc.size - 1;
2011
- if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
2012
- return clipToLen(pos, getLine(doc, pos.line).text.length);
2013
- }
2014
- function clipToLen(pos, linelen) {
2015
- var ch = pos.ch;
2016
- if (ch == null || ch > linelen) return Pos(pos.line, linelen);
2017
- else if (ch < 0) return Pos(pos.line, 0);
2018
- else return pos;
2019
- }
2020
- function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
2021
- function clipPosArray(doc, array) {
2022
- for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);
2023
- return out;
2024
  }
2025
 
2026
- // SELECTION UPDATES
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2027
 
2028
- // The 'scroll' parameter given to many of these indicated whether
2029
- // the new cursor position should be scrolled into view after
2030
- // modifying the selection.
2031
 
2032
- // If shift is held or the extend flag is set, extends a range to
2033
- // include a given position (and optionally a second position).
2034
- // Otherwise, simply returns the range between the given positions.
2035
- // Used for cursor motion and such.
2036
- function extendRange(doc, range, head, other) {
2037
- if (doc.cm && doc.cm.display.shift || doc.extend) {
2038
- var anchor = range.anchor;
2039
- if (other) {
2040
- var posBefore = cmp(head, anchor) < 0;
2041
- if (posBefore != (cmp(other, anchor) < 0)) {
2042
- anchor = head;
2043
- head = other;
2044
- } else if (posBefore != (cmp(head, other) < 0)) {
2045
- head = other;
2046
- }
2047
  }
2048
- return new Range(anchor, head);
2049
- } else {
2050
- return new Range(other || head, head);
2051
  }
2052
- }
2053
-
2054
- // Extend the primary selection range, discard the rest.
2055
- function extendSelection(doc, head, other, options) {
2056
- setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
2057
- }
2058
 
2059
- // Extend all selections (pos is an array of selections with length
2060
- // equal the number of selections)
2061
- function extendSelections(doc, heads, options) {
2062
- for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
2063
- out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
2064
- var newSel = normalizeSelection(out, doc.sel.primIndex);
2065
- setSelection(doc, newSel, options);
2066
- }
2067
 
2068
- // Updates a single range in the selection.
2069
- function replaceOneSelection(doc, i, range, options) {
2070
- var ranges = doc.sel.ranges.slice(0);
2071
- ranges[i] = range;
2072
- setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
2073
- }
2074
 
2075
- // Reset the selection to a single range.
2076
- function setSimpleSelection(doc, anchor, head, options) {
2077
- setSelection(doc, simpleSelection(anchor, head), options);
2078
  }
2079
 
2080
- // Give beforeSelectionChange handlers a change to influence a
2081
- // selection update.
2082
- function filterSelectionChange(doc, sel) {
2083
- var obj = {
2084
- ranges: sel.ranges,
2085
- update: function(ranges) {
2086
- this.ranges = [];
2087
- for (var i = 0; i < ranges.length; i++)
2088
- this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
2089
- clipPos(doc, ranges[i].head));
2090
- }
2091
- };
2092
- signal(doc, "beforeSelectionChange", doc, obj);
2093
- if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
2094
- if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);
2095
- else return sel;
2096
  }
2097
 
2098
- function setSelectionReplaceHistory(doc, sel, options) {
2099
- var done = doc.history.done, last = lst(done);
2100
- if (last && last.ranges) {
2101
- done[done.length - 1] = sel;
2102
- setSelectionNoUndo(doc, sel, options);
 
 
 
 
 
 
 
 
2103
  } else {
2104
- setSelection(doc, sel, options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2105
  }
 
2106
  }
2107
 
2108
- // Set a new selection.
2109
- function setSelection(doc, sel, options) {
2110
- setSelectionNoUndo(doc, sel, options);
2111
- addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
 
 
 
 
 
 
 
 
 
2112
  }
2113
 
2114
- function setSelectionNoUndo(doc, sel, options) {
2115
- if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
2116
- sel = filterSelectionChange(doc, sel);
2117
-
2118
- var bias = options && options.bias ||
2119
- (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
2120
- setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
2121
-
2122
- if (!(options && options.scroll === false) && doc.cm)
2123
- ensureCursorVisible(doc.cm);
2124
- }
2125
-
2126
- function setSelectionInner(doc, sel) {
2127
- if (sel.equals(doc.sel)) return;
2128
-
2129
- doc.sel = sel;
2130
-
2131
- if (doc.cm) {
2132
- doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
2133
- signalCursorActivity(doc.cm);
2134
  }
2135
- signalLater(doc, "cursorActivity", doc);
2136
  }
2137
 
2138
- // Verify that the selection does not partially select any atomic
2139
- // marked ranges.
2140
- function reCheckSelection(doc) {
2141
- setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
 
 
 
 
 
 
 
 
 
 
2142
  }
2143
 
2144
- // Return a selection that does not partially select any atomic
2145
- // ranges.
2146
- function skipAtomicInSelection(doc, sel, bias, mayClear) {
2147
- var out;
2148
- for (var i = 0; i < sel.ranges.length; i++) {
2149
- var range = sel.ranges[i];
2150
- var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
2151
- var newHead = skipAtomic(doc, range.head, bias, mayClear);
2152
- if (out || newAnchor != range.anchor || newHead != range.head) {
2153
- if (!out) out = sel.ranges.slice(0, i);
2154
- out[i] = new Range(newAnchor, newHead);
2155
- }
2156
  }
2157
- return out ? normalizeSelection(out, sel.primIndex) : sel;
2158
- }
2159
 
2160
- // Ensure a given position is not inside an atomic range.
2161
- function skipAtomic(doc, pos, bias, mayClear) {
2162
- var flipped = false, curPos = pos;
2163
- var dir = bias || 1;
2164
- doc.cantEdit = false;
2165
- search: for (;;) {
2166
- var line = getLine(doc, curPos.line);
2167
- if (line.markedSpans) {
2168
- for (var i = 0; i < line.markedSpans.length; ++i) {
2169
- var sp = line.markedSpans[i], m = sp.marker;
2170
- if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
2171
- (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
2172
- if (mayClear) {
2173
- signal(m, "beforeCursorEnter");
2174
- if (m.explicitlyCleared) {
2175
- if (!line.markedSpans) break;
2176
- else {--i; continue;}
2177
- }
2178
  }
2179
- if (!m.atomic) continue;
2180
- var newPos = m.find(dir < 0 ? -1 : 1);
2181
- if (cmp(newPos, curPos) == 0) {
2182
- newPos.ch += dir;
2183
- if (newPos.ch < 0) {
2184
- if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
2185
- else newPos = null;
2186
- } else if (newPos.ch > line.text.length) {
2187
- if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
2188
- else newPos = null;
2189
- }
2190
- if (!newPos) {
2191
- if (flipped) {
2192
- // Driven in a corner -- no valid cursor position found at all
2193
- // -- try again *with* clearing, if we didn't already
2194
- if (!mayClear) return skipAtomic(doc, pos, bias, true);
2195
- // Otherwise, turn off editing until further notice, and return the start of the doc
2196
- doc.cantEdit = true;
2197
- return Pos(doc.first, 0);
2198
- }
2199
- flipped = true; newPos = pos; dir = -dir;
2200
- }
2201
  }
2202
- curPos = newPos;
2203
- continue search;
 
 
2204
  }
2205
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2206
  }
2207
- return curPos;
2208
  }
2209
  }
2210
 
2211
- // SELECTION DRAWING
2212
 
2213
- function updateSelection(cm) {
2214
- cm.display.input.showSelection(cm.display.input.prepareSelection());
 
 
 
 
 
 
 
 
 
 
2215
  }
2216
 
2217
- function prepareSelection(cm, primary) {
2218
- var doc = cm.doc, result = {};
2219
- var curFragment = result.cursors = document.createDocumentFragment();
2220
- var selFragment = result.selection = document.createDocumentFragment();
2221
-
2222
- for (var i = 0; i < doc.sel.ranges.length; i++) {
2223
- if (primary === false && i == doc.sel.primIndex) continue;
2224
- var range = doc.sel.ranges[i];
2225
- var collapsed = range.empty();
2226
- if (collapsed || cm.options.showCursorWhenSelecting)
2227
- drawSelectionCursor(cm, range, curFragment);
2228
- if (!collapsed)
2229
- drawSelectionRange(cm, range, selFragment);
2230
  }
2231
- return result;
2232
  }
2233
 
2234
- // Draws a cursor for the given range
2235
- function drawSelectionCursor(cm, range, output) {
2236
- var pos = cursorCoords(cm, range.head, "div", null, null, !cm.options.singleCursorHeightPerLine);
2237
-
2238
- var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
2239
- cursor.style.left = pos.left + "px";
2240
- cursor.style.top = pos.top + "px";
2241
- cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
2242
 
2243
- if (pos.other) {
2244
- // Secondary cursor, shown when on a 'jump' in bi-directional text
2245
- var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
2246
- otherCursor.style.display = "";
2247
- otherCursor.style.left = pos.other.left + "px";
2248
- otherCursor.style.top = pos.other.top + "px";
2249
- otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
 
2250
  }
2251
  }
2252
 
2253
- // Draws the given range as a highlighted selection
2254
- function drawSelectionRange(cm, range, output) {
2255
- var display = cm.display, doc = cm.doc;
2256
- var fragment = document.createDocumentFragment();
2257
- var padding = paddingH(cm.display), leftSide = padding.left;
2258
- var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
2259
-
2260
- function add(left, top, width, bottom) {
2261
- if (top < 0) top = 0;
2262
- top = Math.round(top);
2263
- bottom = Math.round(bottom);
2264
- fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
2265
- "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
2266
- "px; height: " + (bottom - top) + "px"));
2267
- }
2268
-
2269
- function drawForLine(line, fromArg, toArg) {
2270
- var lineObj = getLine(doc, line);
2271
- var lineLen = lineObj.text.length;
2272
- var start, end;
2273
- function coords(ch, bias) {
2274
- return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
2275
  }
 
 
2276
 
2277
- iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
2278
- var leftPos = coords(from, "left"), rightPos, left, right;
2279
- if (from == to) {
2280
- rightPos = leftPos;
2281
- left = right = leftPos.left;
2282
- } else {
2283
- rightPos = coords(to - 1, "right");
2284
- if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
2285
- left = leftPos.left;
2286
- right = rightPos.right;
2287
- }
2288
- if (fromArg == null && from == 0) left = leftSide;
2289
- if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
2290
- add(left, leftPos.top, null, leftPos.bottom);
2291
- left = leftSide;
2292
- if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
2293
- }
2294
- if (toArg == null && to == lineLen) right = rightSide;
2295
- if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
2296
- start = leftPos;
2297
- if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
2298
- end = rightPos;
2299
- if (left < leftSide + 1) left = leftSide;
2300
- add(left, rightPos.top, right - left, rightPos.bottom);
2301
- });
2302
- return {start: start, end: end};
2303
  }
 
2304
 
2305
- var sFrom = range.from(), sTo = range.to();
2306
- if (sFrom.line == sTo.line) {
2307
- drawForLine(sFrom.line, sFrom.ch, sTo.ch);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2308
  } else {
2309
- var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
2310
- var singleVLine = visualLine(fromLine) == visualLine(toLine);
2311
- var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
2312
- var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
2313
- if (singleVLine) {
2314
- if (leftEnd.top < rightStart.top - 2) {
2315
- add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
2316
- add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
2317
- } else {
2318
- add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
2319
- }
2320
- }
2321
- if (leftEnd.bottom < rightStart.top)
2322
- add(leftSide, leftEnd.bottom, null, rightStart.top);
2323
  }
 
 
 
2324
 
2325
- output.appendChild(fragment);
 
2326
  }
2327
 
2328
- // Cursor-blinking
2329
- function restartBlink(cm) {
2330
- if (!cm.state.focused) return;
2331
- var display = cm.display;
2332
- clearInterval(display.blinker);
2333
- var on = true;
2334
- display.cursorDiv.style.visibility = "";
2335
- if (cm.options.cursorBlinkRate > 0)
2336
- display.blinker = setInterval(function() {
2337
- display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
2338
- }, cm.options.cursorBlinkRate);
2339
- else if (cm.options.cursorBlinkRate < 0)
2340
- display.cursorDiv.style.visibility = "hidden";
2341
  }
2342
 
2343
- // HIGHLIGHT WORKER
2344
-
2345
- function startWorker(cm, time) {
2346
- if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
2347
- cm.state.highlight.set(time, bind(highlightWorker, cm));
 
 
 
 
 
 
 
2348
  }
2349
 
2350
- function highlightWorker(cm) {
2351
- var doc = cm.doc;
2352
- if (doc.frontier < doc.first) doc.frontier = doc.first;
2353
- if (doc.frontier >= cm.display.viewTo) return;
2354
- var end = +new Date + cm.options.workTime;
2355
- var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
2356
- var changedLines = [];
2357
-
2358
- doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
2359
- if (doc.frontier >= cm.display.viewFrom) { // Visible
2360
- var oldStyles = line.styles;
2361
- var highlighted = highlightLine(cm, line, state, true);
2362
- line.styles = highlighted.styles;
2363
- var oldCls = line.styleClasses, newCls = highlighted.classes;
2364
- if (newCls) line.styleClasses = newCls;
2365
- else if (oldCls) line.styleClasses = null;
2366
- var ischange = !oldStyles || oldStyles.length != line.styles.length ||
2367
- oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
2368
- for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
2369
- if (ischange) changedLines.push(doc.frontier);
2370
- line.stateAfter = copyState(doc.mode, state);
2371
- } else {
2372
- processLine(cm, line.text, state);
2373
- line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
2374
- }
2375
- ++doc.frontier;
2376
- if (+new Date > end) {
2377
- startWorker(cm, cm.options.workDelay);
2378
- return true;
2379
- }
2380
- });
2381
- if (changedLines.length) runInOp(cm, function() {
2382
- for (var i = 0; i < changedLines.length; i++)
2383
- regLineChange(cm, changedLines[i], "text");
2384
- });
2385
  }
2386
 
2387
- // Finds the line to start with when starting a parse. Tries to
2388
- // find a line with a stateAfter, so that it can start with a
2389
- // valid state. If that fails, it returns the line with the
2390
- // smallest indentation, which tends to need the least context to
2391
- // parse correctly.
2392
- function findStartLine(cm, n, precise) {
2393
- var minindent, minline, doc = cm.doc;
2394
- var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
2395
- for (var search = n; search > lim; --search) {
2396
- if (search <= doc.first) return doc.first;
2397
- var line = getLine(doc, search - 1);
2398
- if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
2399
- var indented = countColumn(line.text, null, cm.options.tabSize);
2400
- if (minline == null || minindent > indented) {
2401
- minline = search - 1;
2402
- minindent = indented;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2403
  }
 
 
 
 
 
 
2404
  }
2405
- return minline;
2406
  }
2407
 
2408
- function getStateBefore(cm, n, precise) {
2409
- var doc = cm.doc, display = cm.display;
2410
- if (!doc.mode.startState) return true;
2411
- var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
2412
- if (!state) state = startState(doc.mode);
2413
- else state = copyState(doc.mode, state);
2414
- doc.iter(pos, n, function(line) {
2415
- processLine(cm, line.text, state);
2416
- var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
2417
- line.stateAfter = save ? copyState(doc.mode, state) : null;
2418
- ++pos;
2419
- });
2420
- if (precise) doc.frontier = pos;
2421
- return state;
 
 
 
 
 
 
 
 
2422
  }
2423
 
2424
  // POSITION MEASUREMENT
2425
 
2426
- function paddingTop(display) {return display.lineSpace.offsetTop;}
2427
- function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
2428
  function paddingH(display) {
2429
- if (display.cachedPaddingH) return display.cachedPaddingH;
2430
- var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
2431
  var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
2432
  var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
2433
- if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
2434
- return data;
2435
  }
2436
 
2437
- function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }
2438
  function displayWidth(cm) {
2439
- return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;
2440
  }
2441
  function displayHeight(cm) {
2442
- return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;
2443
  }
2444
 
2445
  // Ensure the lineView.wrapping.heights array is populated. This is
@@ -2457,7 +2329,7 @@
2457
  for (var i = 0; i < rects.length - 1; i++) {
2458
  var cur = rects[i], next = rects[i + 1];
2459
  if (Math.abs(cur.bottom - next.bottom) > 2)
2460
- heights.push((cur.bottom + next.top) / 2 - rect.top);
2461
  }
2462
  }
2463
  heights.push(rect.bottom - rect.top);
@@ -2469,13 +2341,13 @@
2469
  // contain multiple lines when collapsed ranges are present.)
2470
  function mapFromLineView(lineView, line, lineN) {
2471
  if (lineView.line == line)
2472
- return {map: lineView.measure.map, cache: lineView.measure.cache};
2473
  for (var i = 0; i < lineView.rest.length; i++)
2474
- if (lineView.rest[i] == line)
2475
- return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
2476
- for (var i = 0; i < lineView.rest.length; i++)
2477
- if (lineNo(lineView.rest[i]) > lineN)
2478
- return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
2479
  }
2480
 
2481
  // Render a line into the hidden node display.externalMeasured. Used
@@ -2488,22 +2360,22 @@
2488
  var built = view.built = buildLineContent(cm, view);
2489
  view.text = built.pre;
2490
  removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
2491
- return view;
2492
  }
2493
 
2494
  // Get a {top, bottom, left, right} box (in line-local coordinates)
2495
  // for a given character.
2496
  function measureChar(cm, line, ch, bias) {
2497
- return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
2498
  }
2499
 
2500
  // Find a line view that corresponds to the given line number.
2501
  function findViewForLine(cm, lineN) {
2502
  if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
2503
- return cm.display.view[findViewIndex(cm, lineN)];
2504
  var ext = cm.display.externalMeasured;
2505
  if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
2506
- return ext;
2507
  }
2508
 
2509
  // Measurement can be split in two steps, the set-up work that
@@ -2514,51 +2386,54 @@
2514
  function prepareMeasureForLine(cm, line) {
2515
  var lineN = lineNo(line);
2516
  var view = findViewForLine(cm, lineN);
2517
- if (view && !view.text)
2518
  view = null;
2519
- else if (view && view.changes)
2520
  updateLineForChanges(cm, view, lineN, getDimensions(cm));
 
 
2521
  if (!view)
2522
- view = updateExternalMeasurement(cm, line);
2523
 
2524
  var info = mapFromLineView(view, line, lineN);
2525
  return {
2526
  line: line, view: view, rect: null,
2527
  map: info.map, cache: info.cache, before: info.before,
2528
  hasHeights: false
2529
- };
2530
  }
2531
 
2532
  // Given a prepared measurement object, measures the position of an
2533
  // actual character (or fetches it from the cache).
2534
  function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
2535
- if (prepared.before) ch = -1;
2536
  var key = ch + (bias || ""), found;
2537
  if (prepared.cache.hasOwnProperty(key)) {
2538
  found = prepared.cache[key];
2539
  } else {
2540
  if (!prepared.rect)
2541
- prepared.rect = prepared.view.text.getBoundingClientRect();
2542
  if (!prepared.hasHeights) {
2543
  ensureLineHeights(cm, prepared.view, prepared.rect);
2544
  prepared.hasHeights = true;
2545
  }
2546
  found = measureCharInner(cm, prepared, ch, bias);
2547
- if (!found.bogus) prepared.cache[key] = found;
2548
  }
2549
  return {left: found.left, right: found.right,
2550
  top: varHeight ? found.rtop : found.top,
2551
- bottom: varHeight ? found.rbottom : found.bottom};
2552
  }
2553
 
2554
  var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
2555
 
2556
  function nodeAndOffsetInLineMap(map, ch, bias) {
2557
- var node, start, end, collapse;
2558
  // First, search the line map for the text node corresponding to,
2559
  // or closest to, the target character.
2560
  for (var i = 0; i < map.length; i += 3) {
2561
- var mStart = map[i], mEnd = map[i + 1];
 
2562
  if (ch < mStart) {
2563
  start = 0; end = 1;
2564
  collapse = "left";
@@ -2568,26 +2443,36 @@
2568
  } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
2569
  end = mEnd - mStart;
2570
  start = end - 1;
2571
- if (ch >= mEnd) collapse = "right";
2572
  }
2573
  if (start != null) {
2574
  node = map[i + 2];
2575
  if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
2576
- collapse = bias;
2577
  if (bias == "left" && start == 0)
2578
- while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
2579
  node = map[(i -= 3) + 2];
2580
  collapse = "left";
2581
- }
2582
  if (bias == "right" && start == mEnd - mStart)
2583
- while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
2584
  node = map[(i += 3) + 2];
2585
  collapse = "right";
2586
- }
2587
- break;
2588
  }
2589
  }
2590
- return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};
 
 
 
 
 
 
 
 
 
 
2591
  }
2592
 
2593
  function measureCharInner(cm, prepared, ch, bias) {
@@ -2596,55 +2481,49 @@
2596
 
2597
  var rect;
2598
  if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
2599
- for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
2600
- while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;
2601
- while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;
2602
- if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) {
2603
- rect = node.parentNode.getBoundingClientRect();
2604
- } else if (ie && cm.options.lineWrapping) {
2605
- var rects = range(node, start, end).getClientRects();
2606
- if (rects.length)
2607
- rect = rects[bias == "right" ? rects.length - 1 : 0];
2608
- else
2609
- rect = nullRect;
2610
- } else {
2611
- rect = range(node, start, end).getBoundingClientRect() || nullRect;
2612
- }
2613
- if (rect.left || rect.right || start == 0) break;
2614
  end = start;
2615
  start = start - 1;
2616
  collapse = "right";
2617
  }
2618
- if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);
2619
  } else { // If it is a widget, simply get the box for the whole widget.
2620
- if (start > 0) collapse = bias = "right";
2621
  var rects;
2622
  if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
2623
- rect = rects[bias == "right" ? rects.length - 1 : 0];
2624
  else
2625
- rect = node.getBoundingClientRect();
2626
  }
2627
  if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
2628
  var rSpan = node.parentNode.getClientRects()[0];
2629
  if (rSpan)
2630
- rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
2631
  else
2632
- rect = nullRect;
2633
  }
2634
 
2635
  var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
2636
  var mid = (rtop + rbot) / 2;
2637
  var heights = prepared.view.measure.heights;
2638
- for (var i = 0; i < heights.length - 1; i++)
2639
- if (mid < heights[i]) break;
 
2640
  var top = i ? heights[i - 1] : 0, bot = heights[i];
2641
  var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
2642
  right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
2643
  top: top, bottom: bot};
2644
- if (!rect.left && !rect.right) result.bogus = true;
2645
  if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
2646
 
2647
- return result;
2648
  }
2649
 
2650
  // Work around problem with bounding client rects on ranges being
@@ -2652,19 +2531,19 @@
2652
  function maybeUpdateRectForZooming(measure, rect) {
2653
  if (!window.screen || screen.logicalXDPI == null ||
2654
  screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
2655
- return rect;
2656
  var scaleX = screen.logicalXDPI / screen.deviceXDPI;
2657
  var scaleY = screen.logicalYDPI / screen.deviceYDPI;
2658
  return {left: rect.left * scaleX, right: rect.right * scaleX,
2659
- top: rect.top * scaleY, bottom: rect.bottom * scaleY};
2660
  }
2661
 
2662
  function clearLineMeasurementCacheFor(lineView) {
2663
  if (lineView.measure) {
2664
  lineView.measure.cache = {};
2665
  lineView.measure.heights = null;
2666
- if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
2667
- lineView.measure.caches[i] = {};
2668
  }
2669
  }
2670
 
@@ -2672,33 +2551,49 @@
2672
  cm.display.externalMeasure = null;
2673
  removeChildren(cm.display.lineMeasure);
2674
  for (var i = 0; i < cm.display.view.length; i++)
2675
- clearLineMeasurementCacheFor(cm.display.view[i]);
2676
  }
2677
 
2678
  function clearCaches(cm) {
2679
  clearLineMeasurementCache(cm);
2680
  cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
2681
- if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
2682
  cm.display.lineNumChars = null;
2683
  }
2684
 
2685
- function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
2686
- function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2687
 
2688
  // Converts a {top, bottom, left, right} box from line-local
2689
  // coordinates into another coordinate system. Context may be one of
2690
- // "line", "div" (display.lineDiv), "local"/null (editor), "window",
2691
  // or "page".
2692
- function intoCoordSystem(cm, lineObj, rect, context) {
2693
- if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
2694
- var size = widgetHeight(lineObj.widgets[i]);
2695
- rect.top += size; rect.bottom += size;
2696
  }
2697
- if (context == "line") return rect;
2698
- if (!context) context = "local";
2699
  var yOff = heightAtLine(lineObj);
2700
- if (context == "local") yOff += paddingTop(cm.display);
2701
- else yOff -= cm.display.viewOffset;
2702
  if (context == "page" || context == "window") {
2703
  var lOff = cm.display.lineSpace.getBoundingClientRect();
2704
  yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
@@ -2706,13 +2601,13 @@
2706
  rect.left += xOff; rect.right += xOff;
2707
  }
2708
  rect.top += yOff; rect.bottom += yOff;
2709
- return rect;
2710
  }
2711
 
2712
  // Coverts a box from "div" coords to another coordinate system.
2713
- // Context may be "window", "page", "div", or "local"/null.
2714
  function fromCoordSystem(cm, coords, context) {
2715
- if (context == "div") return coords;
2716
  var left = coords.left, top = coords.top;
2717
  // First move into "page" coordinate system
2718
  if (context == "page") {
@@ -2725,55 +2620,68 @@
2725
  }
2726
 
2727
  var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
2728
- return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
2729
  }
2730
 
2731
  function charCoords(cm, pos, context, lineObj, bias) {
2732
- if (!lineObj) lineObj = getLine(cm.doc, pos.line);
2733
- return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
2734
  }
2735
 
2736
  // Returns a box for a given cursor position, which may have an
2737
  // 'other' property containing the position of the secondary cursor
2738
  // on a bidi boundary.
 
 
 
 
 
 
 
 
 
 
 
 
 
2739
  function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
2740
  lineObj = lineObj || getLine(cm.doc, pos.line);
2741
- if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);
2742
  function get(ch, right) {
2743
  var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
2744
- if (right) m.left = m.right; else m.right = m.left;
2745
- return intoCoordSystem(cm, lineObj, m, context);
2746
- }
2747
- function getBidi(ch, partPos) {
2748
- var part = order[partPos], right = part.level % 2;
2749
- if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
2750
- part = order[--partPos];
2751
- ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
2752
- right = true;
2753
- } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
2754
- part = order[++partPos];
2755
- ch = bidiLeft(part) - part.level % 2;
2756
- right = false;
2757
- }
2758
- if (right && ch == part.to && ch > part.from) return get(ch - 1);
2759
- return get(ch, right);
2760
- }
2761
- var order = getOrder(lineObj), ch = pos.ch;
2762
- if (!order) return get(ch);
2763
- var partPos = getBidiPartAt(order, ch);
2764
- var val = getBidi(ch, partPos);
2765
- if (bidiOther != null) val.other = getBidi(ch, bidiOther);
2766
- return val;
2767
  }
2768
 
2769
  // Used to cheaply estimate the coordinates for a position. Used for
2770
  // intermediate scroll updates.
2771
  function estimateCoords(cm, pos) {
2772
- var left = 0, pos = clipPos(cm.doc, pos);
2773
- if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;
 
2774
  var lineObj = getLine(cm.doc, pos.line);
2775
  var top = heightAtLine(lineObj) + paddingTop(cm.display);
2776
- return {left: left, right: left, top: top, bottom: top + lineObj.height};
2777
  }
2778
 
2779
  // Positions returned by coordsChar contain some extra information.
@@ -2782,11 +2690,11 @@
2782
  // the right of the character position, for example). When outside
2783
  // is true, that means the coordinates lie outside the line's
2784
  // vertical range.
2785
- function PosWithInfo(line, ch, outside, xRel) {
2786
- var pos = Pos(line, ch);
2787
  pos.xRel = xRel;
2788
- if (outside) pos.outside = true;
2789
- return pos;
2790
  }
2791
 
2792
  // Compute the character position closest to the given coordinates.
@@ -2794,70 +2702,173 @@
2794
  function coordsChar(cm, x, y) {
2795
  var doc = cm.doc;
2796
  y += cm.display.viewOffset;
2797
- if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
2798
  var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
2799
  if (lineN > last)
2800
- return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
2801
- if (x < 0) x = 0;
2802
 
2803
  var lineObj = getLine(doc, lineN);
2804
  for (;;) {
2805
  var found = coordsCharInner(cm, lineObj, lineN, x, y);
2806
- var merged = collapsedSpanAtEnd(lineObj);
2807
- var mergedPos = merged && merged.find(0, true);
2808
- if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
2809
- lineN = lineNo(lineObj = mergedPos.to.line);
2810
- else
2811
- return found;
2812
  }
2813
  }
2814
 
2815
- function coordsCharInner(cm, lineObj, lineNo, x, y) {
2816
- var innerOff = y - heightAtLine(lineObj);
2817
- var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
2818
- var preparedMeasure = prepareMeasureForLine(cm, lineObj);
 
 
 
2819
 
2820
- function getX(ch) {
2821
- var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
2822
- wrongLine = true;
2823
- if (innerOff > sp.bottom) return sp.left - adjust;
2824
- else if (innerOff < sp.top) return sp.left + adjust;
2825
- else wrongLine = false;
2826
- return sp.left;
2827
- }
2828
 
2829
- var bidi = getOrder(lineObj), dist = lineObj.text.length;
2830
- var from = lineLeft(lineObj), to = lineRight(lineObj);
2831
- var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
 
 
2832
 
2833
- if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
2834
- // Do a binary search between these bounds.
2835
- for (;;) {
2836
- if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
2837
- var ch = x < fromX || x - fromX <= toX - x ? from : to;
2838
- var xDiff = x - (ch == from ? fromX : toX);
2839
- while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
2840
- var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
2841
- xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
2842
- return pos;
2843
- }
2844
- var step = Math.ceil(dist / 2), middle = from + step;
2845
- if (bidi) {
2846
- middle = from;
2847
- for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
2848
- }
2849
- var middleX = getX(middle);
2850
- if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
2851
- else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
2852
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2853
  }
2854
 
2855
  var measureText;
2856
  // Compute the default text height.
2857
  function textHeight(display) {
2858
- if (display.cachedTextHeight != null) return display.cachedTextHeight;
2859
  if (measureText == null) {
2860
- measureText = elt("pre");
2861
  // Measure a bunch of lines, for browsers that compute
2862
  // fractional heights.
2863
  for (var i = 0; i < 49; ++i) {
@@ -2868,275 +2879,107 @@
2868
  }
2869
  removeChildrenAndAdd(display.measure, measureText);
2870
  var height = measureText.offsetHeight / 50;
2871
- if (height > 3) display.cachedTextHeight = height;
2872
  removeChildren(display.measure);
2873
- return height || 1;
2874
  }
2875
 
2876
  // Compute the default character width.
2877
  function charWidth(display) {
2878
- if (display.cachedCharWidth != null) return display.cachedCharWidth;
2879
  var anchor = elt("span", "xxxxxxxxxx");
2880
- var pre = elt("pre", [anchor]);
2881
  removeChildrenAndAdd(display.measure, pre);
2882
  var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
2883
- if (width > 2) display.cachedCharWidth = width;
2884
- return width || 10;
2885
  }
2886
 
2887
- // OPERATIONS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2888
 
2889
- // Operations are used to wrap a series of changes to the editor
2890
- // state in such a way that each change won't have to update the
2891
- // cursor and display (which would be awkward, slow, and
2892
- // error-prone). Instead, display updates are batched and then all
2893
- // combined and executed at once.
 
2894
 
2895
- var operationGroup = null;
 
 
 
 
 
 
 
2896
 
2897
- var nextOpId = 0;
2898
- // Start a new operation.
2899
- function startOperation(cm) {
2900
- cm.curOp = {
2901
- cm: cm,
2902
- viewChanged: false, // Flag that indicates that lines might need to be redrawn
2903
- startHeight: cm.doc.height, // Used to detect need to update scrollbar
2904
- forceUpdate: false, // Used to force a redraw
2905
- updateInput: null, // Whether to reset the input textarea
2906
- typing: false, // Whether this reset should be careful to leave existing text (for compositing)
2907
- changeObjs: null, // Accumulated changes, for firing change events
2908
- cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
2909
- cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
2910
- selectionChanged: false, // Whether the selection needs to be redrawn
2911
- updateMaxLine: false, // Set when the widest line needs to be determined anew
2912
- scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
2913
- scrollToPos: null, // Used to scroll to a specific position
2914
- id: ++nextOpId // Unique ID
2915
- };
2916
- if (operationGroup) {
2917
- operationGroup.ops.push(cm.curOp);
2918
- } else {
2919
- cm.curOp.ownsGroup = operationGroup = {
2920
- ops: [cm.curOp],
2921
- delayedCallbacks: []
2922
- };
2923
  }
2924
  }
2925
 
2926
- function fireCallbacksForOps(group) {
2927
- // Calls delayed callbacks and cursorActivity handlers until no
2928
- // new ones appear
2929
- var callbacks = group.delayedCallbacks, i = 0;
2930
- do {
2931
- for (; i < callbacks.length; i++)
2932
- callbacks[i]();
2933
- for (var j = 0; j < group.ops.length; j++) {
2934
- var op = group.ops[j];
2935
- if (op.cursorActivityHandlers)
2936
- while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
2937
- op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm);
2938
- }
2939
- } while (i < callbacks.length);
2940
  }
2941
 
2942
- // Finish an operation, updating the display and signalling delayed events
2943
- function endOperation(cm) {
2944
- var op = cm.curOp, group = op.ownsGroup;
2945
- if (!group) return;
 
 
 
 
2946
 
2947
- try { fireCallbacksForOps(group); }
2948
- finally {
2949
- operationGroup = null;
2950
- for (var i = 0; i < group.ops.length; i++)
2951
- group.ops[i].cm.curOp = null;
2952
- endOperations(group);
 
 
2953
  }
 
2954
  }
2955
 
2956
- // The DOM updates done when an operation finishes are batched so
2957
- // that the minimum number of relayouts are required.
2958
- function endOperations(group) {
2959
- var ops = group.ops;
2960
- for (var i = 0; i < ops.length; i++) // Read DOM
2961
- endOperation_R1(ops[i]);
2962
- for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
2963
- endOperation_W1(ops[i]);
2964
- for (var i = 0; i < ops.length; i++) // Read DOM
2965
- endOperation_R2(ops[i]);
2966
- for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
2967
- endOperation_W2(ops[i]);
2968
- for (var i = 0; i < ops.length; i++) // Read DOM
2969
- endOperation_finish(ops[i]);
2970
- }
2971
-
2972
- function endOperation_R1(op) {
2973
- var cm = op.cm, display = cm.display;
2974
- maybeClipScrollbars(cm);
2975
- if (op.updateMaxLine) findMaxLine(cm);
2976
-
2977
- op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
2978
- op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
2979
- op.scrollToPos.to.line >= display.viewTo) ||
2980
- display.maxLineChanged && cm.options.lineWrapping;
2981
- op.update = op.mustUpdate &&
2982
- new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
2983
- }
2984
-
2985
- function endOperation_W1(op) {
2986
- op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
2987
- }
2988
-
2989
- function endOperation_R2(op) {
2990
- var cm = op.cm, display = cm.display;
2991
- if (op.updatedDisplay) updateHeightsInViewport(cm);
2992
-
2993
- op.barMeasure = measureForScrollbars(cm);
2994
-
2995
- // If the max line changed since it was last measured, measure it,
2996
- // and ensure the document's width matches it.
2997
- // updateDisplay_W2 will use these properties to do the actual resizing
2998
- if (display.maxLineChanged && !cm.options.lineWrapping) {
2999
- op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
3000
- cm.display.sizerWidth = op.adjustWidthTo;
3001
- op.barMeasure.scrollWidth =
3002
- Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
3003
- op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
3004
- }
3005
-
3006
- if (op.updatedDisplay || op.selectionChanged)
3007
- op.preparedSelection = display.input.prepareSelection();
3008
- }
3009
-
3010
- function endOperation_W2(op) {
3011
- var cm = op.cm;
3012
-
3013
- if (op.adjustWidthTo != null) {
3014
- cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
3015
- if (op.maxScrollLeft < cm.doc.scrollLeft)
3016
- setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);
3017
- cm.display.maxLineChanged = false;
3018
- }
3019
-
3020
- if (op.preparedSelection)
3021
- cm.display.input.showSelection(op.preparedSelection);
3022
- if (op.updatedDisplay)
3023
- setDocumentHeight(cm, op.barMeasure);
3024
- if (op.updatedDisplay || op.startHeight != cm.doc.height)
3025
- updateScrollbars(cm, op.barMeasure);
3026
-
3027
- if (op.selectionChanged) restartBlink(cm);
3028
-
3029
- if (cm.state.focused && op.updateInput)
3030
- cm.display.input.reset(op.typing);
3031
- }
3032
-
3033
- function endOperation_finish(op) {
3034
- var cm = op.cm, display = cm.display, doc = cm.doc;
3035
-
3036
- if (op.updatedDisplay) postUpdateDisplay(cm, op.update);
3037
-
3038
- // Abort mouse wheel delta measurement, when scrolling explicitly
3039
- if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
3040
- display.wheelStartX = display.wheelStartY = null;
3041
-
3042
- // Propagate the scroll position to the actual DOM scroller
3043
- if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
3044
- doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
3045
- display.scrollbars.setScrollTop(doc.scrollTop);
3046
- display.scroller.scrollTop = doc.scrollTop;
3047
- }
3048
- if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
3049
- doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
3050
- display.scrollbars.setScrollLeft(doc.scrollLeft);
3051
- display.scroller.scrollLeft = doc.scrollLeft;
3052
- alignHorizontally(cm);
3053
- }
3054
- // If we need to scroll a specific position into view, do so.
3055
- if (op.scrollToPos) {
3056
- var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
3057
- clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
3058
- if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
3059
- }
3060
-
3061
- // Fire events for markers that are hidden/unidden by editing or
3062
- // undoing
3063
- var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
3064
- if (hidden) for (var i = 0; i < hidden.length; ++i)
3065
- if (!hidden[i].lines.length) signal(hidden[i], "hide");
3066
- if (unhidden) for (var i = 0; i < unhidden.length; ++i)
3067
- if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
3068
-
3069
- if (display.wrapper.offsetHeight)
3070
- doc.scrollTop = cm.display.scroller.scrollTop;
3071
-
3072
- // Fire change events, and delayed event handlers
3073
- if (op.changeObjs)
3074
- signal(cm, "changes", cm, op.changeObjs);
3075
- if (op.update)
3076
- op.update.finish();
3077
- }
3078
-
3079
- // Run the given function in an operation
3080
- function runInOp(cm, f) {
3081
- if (cm.curOp) return f();
3082
- startOperation(cm);
3083
- try { return f(); }
3084
- finally { endOperation(cm); }
3085
- }
3086
- // Wraps a function in an operation. Returns the wrapped function.
3087
- function operation(cm, f) {
3088
- return function() {
3089
- if (cm.curOp) return f.apply(cm, arguments);
3090
- startOperation(cm);
3091
- try { return f.apply(cm, arguments); }
3092
- finally { endOperation(cm); }
3093
- };
3094
- }
3095
- // Used to add methods to editor and doc instances, wrapping them in
3096
- // operations.
3097
- function methodOp(f) {
3098
- return function() {
3099
- if (this.curOp) return f.apply(this, arguments);
3100
- startOperation(this);
3101
- try { return f.apply(this, arguments); }
3102
- finally { endOperation(this); }
3103
- };
3104
- }
3105
- function docMethodOp(f) {
3106
- return function() {
3107
- var cm = this.cm;
3108
- if (!cm || cm.curOp) return f.apply(this, arguments);
3109
- startOperation(cm);
3110
- try { return f.apply(this, arguments); }
3111
- finally { endOperation(cm); }
3112
- };
3113
- }
3114
-
3115
- // VIEW TRACKING
3116
-
3117
- // These objects are used to represent the visible (currently drawn)
3118
- // part of the document. A LineView may correspond to multiple
3119
- // logical lines, if those are connected by collapsed ranges.
3120
- function LineView(doc, line, lineN) {
3121
- // The starting line
3122
- this.line = line;
3123
- // Continuing lines, if any
3124
- this.rest = visualLineContinued(line);
3125
- // Number of logical lines in this visual line
3126
- this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
3127
- this.node = this.text = null;
3128
- this.hidden = lineIsHidden(doc, line);
3129
- }
3130
-
3131
- // Create a range of LineView objects for the given lines.
3132
- function buildViewArray(cm, from, to) {
3133
- var array = [], nextPos;
3134
- for (var pos = from; pos < to; pos = nextPos) {
3135
- var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
3136
- nextPos = pos + view.size;
3137
- array.push(view);
3138
  }
3139
- return array;
3140
  }
3141
 
3142
  // Updates the display.view data structure for a given change to the
@@ -3146,20 +2989,20 @@
3146
  // lines are divided into visual lines. regLineChange (below)
3147
  // registers single-line changes.
3148
  function regChange(cm, from, to, lendiff) {
3149
- if (from == null) from = cm.doc.first;
3150
- if (to == null) to = cm.doc.first + cm.doc.size;
3151
- if (!lendiff) lendiff = 0;
3152
 
3153
  var display = cm.display;
3154
  if (lendiff && to < display.viewTo &&
3155
  (display.updateLineNumbers == null || display.updateLineNumbers > from))
3156
- display.updateLineNumbers = from;
3157
 
3158
  cm.curOp.viewChanged = true;
3159
 
3160
  if (from >= display.viewTo) { // Change after
3161
  if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
3162
- resetView(cm);
3163
  } else if (to <= display.viewFrom) { // Change before
3164
  if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
3165
  resetView(cm);
@@ -3179,10 +3022,10 @@
3179
  resetView(cm);
3180
  }
3181
  } else if (to >= display.viewTo) { // Bottom overlap
3182
- var cut = viewCuttingPoint(cm, from, from, -1);
3183
- if (cut) {
3184
- display.view = display.view.slice(0, cut.index);
3185
- display.viewTo = cut.lineN;
3186
  } else {
3187
  resetView(cm);
3188
  }
@@ -3202,9 +3045,9 @@
3202
  var ext = display.externalMeasured;
3203
  if (ext) {
3204
  if (to < ext.lineN)
3205
- ext.lineN += lendiff;
3206
  else if (from < ext.lineN + ext.size)
3207
- display.externalMeasured = null;
3208
  }
3209
  }
3210
 
@@ -3214,13 +3057,13 @@
3214
  cm.curOp.viewChanged = true;
3215
  var display = cm.display, ext = cm.display.externalMeasured;
3216
  if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
3217
- display.externalMeasured = null;
3218
 
3219
- if (line < display.viewFrom || line >= display.viewTo) return;
3220
  var lineView = display.view[findViewIndex(cm, line)];
3221
- if (lineView.node == null) return;
3222
  var arr = lineView.changes || (lineView.changes = []);
3223
- if (indexOf(arr, type) == -1) arr.push(type);
3224
  }
3225
 
3226
  // Clear the view.
@@ -3230,28 +3073,16 @@
3230
  cm.display.viewOffset = 0;
3231
  }
3232
 
3233
- // Find the view element corresponding to a given line. Return null
3234
- // when the line isn't visible.
3235
- function findViewIndex(cm, n) {
3236
- if (n >= cm.display.viewTo) return null;
3237
- n -= cm.display.viewFrom;
3238
- if (n < 0) return null;
3239
- var view = cm.display.view;
3240
- for (var i = 0; i < view.length; i++) {
3241
- n -= view[i].size;
3242
- if (n < 0) return i;
3243
- }
3244
- }
3245
-
3246
  function viewCuttingPoint(cm, oldN, newN, dir) {
3247
  var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
3248
  if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
3249
- return {index: index, lineN: newN};
3250
- for (var i = 0, n = cm.display.viewFrom; i < index; i++)
3251
- n += view[i].size;
 
3252
  if (n != oldN) {
3253
  if (dir > 0) {
3254
- if (index == view.length - 1) return null;
3255
  diff = (n + view[index].size) - oldN;
3256
  index++;
3257
  } else {
@@ -3260,11 +3091,11 @@
3260
  oldN += diff; newN += diff;
3261
  }
3262
  while (visualLineNo(cm.doc, newN) != newN) {
3263
- if (index == (dir < 0 ? 0 : view.length - 1)) return null;
3264
  newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
3265
  index += dir;
3266
  }
3267
- return {index: index, lineN: newN};
3268
  }
3269
 
3270
  // Force the view to cover a given range, adding empty view element
@@ -3276,14 +3107,14 @@
3276
  display.viewFrom = from;
3277
  } else {
3278
  if (display.viewFrom > from)
3279
- display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);
3280
  else if (display.viewFrom < from)
3281
- display.view = display.view.slice(findViewIndex(cm, from));
3282
  display.viewFrom = from;
3283
  if (display.viewTo < to)
3284
- display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));
3285
  else if (display.viewTo > to)
3286
- display.view = display.view.slice(0, findViewIndex(cm, to));
3287
  }
3288
  display.viewTo = to;
3289
  }
@@ -3294,5365 +3125,6676 @@
3294
  var view = cm.display.view, dirty = 0;
3295
  for (var i = 0; i < view.length; i++) {
3296
  var lineView = view[i];
3297
- if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;
3298
  }
3299
- return dirty;
3300
  }
3301
 
3302
- // EVENT HANDLERS
 
 
3303
 
3304
- // Attach the necessary event handlers when initializing the editor
3305
- function registerEventHandlers(cm) {
3306
- var d = cm.display;
3307
- on(d.scroller, "mousedown", operation(cm, onMouseDown));
3308
- // Older IE's will not fire a second mousedown for a double click
3309
- if (ie && ie_version < 11)
3310
- on(d.scroller, "dblclick", operation(cm, function(e) {
3311
- if (signalDOMEvent(cm, e)) return;
3312
- var pos = posFromMouse(cm, e);
3313
- if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
3314
- e_preventDefault(e);
3315
- var word = cm.findWordAt(pos);
3316
- extendSelection(cm.doc, word.anchor, word.head);
3317
- }));
3318
- else
3319
- on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
3320
- // Some browsers fire contextmenu *after* opening the menu, at
3321
- // which point we can't mess with it anymore. Context menu is
3322
- // handled in onMouseDown for these browsers.
3323
- if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
3324
 
3325
- // Used to suppress mouse event handling when a touch happens
3326
- var touchFinished, prevTouch = {end: 0};
3327
- function finishTouch() {
3328
- if (d.activeTouch) {
3329
- touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);
3330
- prevTouch = d.activeTouch;
3331
- prevTouch.end = +new Date;
3332
- }
3333
- };
3334
- function isMouseLikeTouchEvent(e) {
3335
- if (e.touches.length != 1) return false;
3336
- var touch = e.touches[0];
3337
- return touch.radiusX <= 1 && touch.radiusY <= 1;
3338
- }
3339
- function farAway(touch, other) {
3340
- if (other.left == null) return true;
3341
- var dx = other.left - touch.left, dy = other.top - touch.top;
3342
- return dx * dx + dy * dy > 20 * 20;
3343
- }
3344
- on(d.scroller, "touchstart", function(e) {
3345
- if (!isMouseLikeTouchEvent(e)) {
3346
- clearTimeout(touchFinished);
3347
- var now = +new Date;
3348
- d.activeTouch = {start: now, moved: false,
3349
- prev: now - prevTouch.end <= 300 ? prevTouch : null};
3350
- if (e.touches.length == 1) {
3351
- d.activeTouch.left = e.touches[0].pageX;
3352
- d.activeTouch.top = e.touches[0].pageY;
3353
- }
3354
- }
3355
- });
3356
- on(d.scroller, "touchmove", function() {
3357
- if (d.activeTouch) d.activeTouch.moved = true;
3358
- });
3359
- on(d.scroller, "touchend", function(e) {
3360
- var touch = d.activeTouch;
3361
- if (touch && !eventInWidget(d, e) && touch.left != null &&
3362
- !touch.moved && new Date - touch.start < 300) {
3363
- var pos = cm.coordsChar(d.activeTouch, "page"), range;
3364
- if (!touch.prev || farAway(touch, touch.prev)) // Single tap
3365
- range = new Range(pos, pos);
3366
- else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
3367
- range = cm.findWordAt(pos);
3368
- else // Triple tap
3369
- range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));
3370
- cm.setSelection(range.anchor, range.head);
3371
- cm.focus();
3372
- e_preventDefault(e);
3373
- }
3374
- finishTouch();
3375
- });
3376
- on(d.scroller, "touchcancel", finishTouch);
3377
 
3378
- // Sync scrolling between fake scrollbars and real scrollable
3379
- // area, ensure viewport is updated when scrolling.
3380
- on(d.scroller, "scroll", function() {
3381
- if (d.scroller.clientHeight) {
3382
- setScrollTop(cm, d.scroller.scrollTop);
3383
- setScrollLeft(cm, d.scroller.scrollLeft, true);
3384
- signal(cm, "scroll", cm);
3385
- }
3386
- });
 
 
 
3387
 
3388
- // Listen to wheel events in order to try and update the viewport on time.
3389
- on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
3390
- on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
3391
 
3392
- // Prevent wrapper from ever scrolling
3393
- on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
 
 
3394
 
3395
- function drag_(e) {
3396
- if (!signalDOMEvent(cm, e)) e_stop(e);
3397
- }
3398
- if (cm.options.dragDrop) {
3399
- on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
3400
- on(d.scroller, "dragenter", drag_);
3401
- on(d.scroller, "dragover", drag_);
3402
- on(d.scroller, "drop", operation(cm, onDrop));
3403
  }
3404
-
3405
- var inp = d.input.getField();
3406
- on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
3407
- on(inp, "keydown", operation(cm, onKeyDown));
3408
- on(inp, "keypress", operation(cm, onKeyPress));
3409
- on(inp, "focus", bind(onFocus, cm));
3410
- on(inp, "blur", bind(onBlur, cm));
3411
- }
3412
-
3413
- // Called when the window resizes
3414
- function onResize(cm) {
3415
- var d = cm.display;
3416
- if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
3417
- return;
3418
- // Might be a text scaling operation, clear size caches.
3419
- d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
3420
- d.scrollbarsClipped = false;
3421
- cm.setSize();
3422
  }
3423
 
3424
- // MOUSE EVENTS
3425
 
3426
- // Return true when the given mouse event happened in a widget
3427
- function eventInWidget(display, e) {
3428
- for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
3429
- if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
3430
- (n.parentNode == display.sizer && n != display.mover))
3431
- return true;
3432
- }
3433
- }
3434
-
3435
- // Given a mouse event, find the corresponding position. If liberal
3436
- // is false, it checks whether a gutter or scrollbar was clicked,
3437
- // and returns null if it was. forRect is used by rectangular
3438
- // selections, and tries to estimate a character position even for
3439
- // coordinates beyond the right of the text.
3440
- function posFromMouse(cm, e, liberal, forRect) {
3441
- var display = cm.display;
3442
- if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null;
3443
 
3444
- var x, y, space = display.lineSpace.getBoundingClientRect();
3445
- // Fails unpredictably on IE[67] when mouse is dragged around quickly.
3446
- try { x = e.clientX - space.left; y = e.clientY - space.top; }
3447
- catch (e) { return null; }
3448
- var coords = coordsChar(cm, x, y), line;
3449
- if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
3450
- var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
3451
- coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
3452
  }
3453
- return coords;
3454
- }
3455
-
3456
- // A mouse down can be a single click, double click, triple click,
3457
- // start of selection drag, start of text drag, new cursor
3458
- // (ctrl-click), rectangle drag (alt-drag), or xwin
3459
- // middle-click-paste. Or it might be a click on something we should
3460
- // not interfere with, such as a scrollbar or widget.
3461
- function onMouseDown(e) {
3462
- var cm = this, display = cm.display;
3463
- if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return;
3464
- display.shift = e.shiftKey;
3465
 
3466
- if (eventInWidget(display, e)) {
3467
- if (!webkit) {
3468
- // Briefly turn off draggability, to allow widgets to do
3469
- // normal dragging things.
3470
- display.scroller.draggable = false;
3471
- setTimeout(function(){display.scroller.draggable = true;}, 100);
3472
- }
3473
- return;
3474
- }
3475
- if (clickInGutter(cm, e)) return;
3476
- var start = posFromMouse(cm, e);
3477
- window.focus();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3478
 
3479
- switch (e_button(e)) {
3480
- case 1:
3481
- if (start)
3482
- leftButtonDown(cm, e, start);
3483
- else if (e_target(e) == display.scroller)
3484
- e_preventDefault(e);
3485
- break;
3486
- case 2:
3487
- if (webkit) cm.state.lastMiddleDown = +new Date;
3488
- if (start) extendSelection(cm.doc, start);
3489
- setTimeout(function() {display.input.focus();}, 20);
3490
- e_preventDefault(e);
3491
- break;
3492
- case 3:
3493
- if (captureRightClick) onContextMenu(cm, e);
3494
- break;
3495
  }
3496
- }
3497
 
3498
- var lastClick, lastDoubleClick;
3499
- function leftButtonDown(cm, e, start) {
3500
- if (ie) setTimeout(bind(ensureFocus, cm), 0);
3501
- else ensureFocus(cm);
3502
-
3503
- var now = +new Date, type;
3504
- if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
3505
- type = "triple";
3506
- } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
3507
- type = "double";
3508
- lastDoubleClick = {time: now, pos: start};
3509
  } else {
3510
- type = "single";
3511
- lastClick = {time: now, pos: start};
 
 
 
 
 
 
 
 
 
 
 
 
3512
  }
3513
 
3514
- var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
3515
- if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
3516
- type == "single" && (contained = sel.contains(start)) > -1 &&
3517
- !sel.ranges[contained].empty())
3518
- leftButtonStartDrag(cm, e, start, modifier);
3519
- else
3520
- leftButtonSelect(cm, e, start, type, modifier);
3521
  }
3522
 
3523
- // Start a text drag. When it ends, see if any dragging actually
3524
- // happen, and treat as a click if it didn't.
3525
- function leftButtonStartDrag(cm, e, start, modifier) {
3526
  var display = cm.display;
3527
- var dragEnd = operation(cm, function(e2) {
3528
- if (webkit) display.scroller.draggable = false;
3529
- cm.state.draggingText = false;
3530
- off(document, "mouseup", dragEnd);
3531
- off(display.scroller, "drop", dragEnd);
3532
- if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
3533
- e_preventDefault(e2);
3534
- if (!modifier)
3535
- extendSelection(cm.doc, start);
3536
- // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
3537
- if (webkit || ie && ie_version == 9)
3538
- setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
3539
- else
3540
- display.input.focus();
3541
- }
3542
- });
3543
- // Let the drag handler handle this.
3544
- if (webkit) display.scroller.draggable = true;
3545
- cm.state.draggingText = dragEnd;
3546
- // IE's approach to draggable
3547
- if (display.scroller.dragDrop) display.scroller.dragDrop();
3548
- on(document, "mouseup", dragEnd);
3549
- on(display.scroller, "drop", dragEnd);
3550
  }
3551
 
3552
- // Normal selection, as opposed to text dragging.
3553
- function leftButtonSelect(cm, e, start, type, addNew) {
3554
- var display = cm.display, doc = cm.doc;
3555
- e_preventDefault(e);
3556
-
3557
- var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
3558
- if (addNew && !e.shiftKey) {
3559
- ourIndex = doc.sel.contains(start);
3560
- if (ourIndex > -1)
3561
- ourRange = ranges[ourIndex];
3562
- else
3563
- ourRange = new Range(start, start);
3564
- } else {
3565
- ourRange = doc.sel.primary();
3566
- }
3567
-
3568
- if (e.altKey) {
3569
- type = "rect";
3570
- if (!addNew) ourRange = new Range(start, start);
3571
- start = posFromMouse(cm, e, true, true);
3572
- ourIndex = -1;
3573
- } else if (type == "double") {
3574
- var word = cm.findWordAt(start);
3575
- if (cm.display.shift || doc.extend)
3576
- ourRange = extendRange(doc, ourRange, word.anchor, word.head);
3577
- else
3578
- ourRange = word;
3579
- } else if (type == "triple") {
3580
- var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
3581
- if (cm.display.shift || doc.extend)
3582
- ourRange = extendRange(doc, ourRange, line.anchor, line.head);
3583
- else
3584
- ourRange = line;
3585
- } else {
3586
- ourRange = extendRange(doc, ourRange, start);
3587
  }
 
3588
 
3589
- if (!addNew) {
3590
- ourIndex = 0;
3591
- setSelection(doc, new Selection([ourRange], 0), sel_mouse);
3592
- startSel = doc.sel;
3593
- } else if (ourIndex == -1) {
3594
- ourIndex = ranges.length;
3595
- setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
3596
- {scroll: false, origin: "*mouse"});
3597
- } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") {
3598
- setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
3599
- startSel = doc.sel;
3600
- } else {
3601
- replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
3602
- }
3603
 
3604
- var lastPos = start;
3605
- function extendTo(pos) {
3606
- if (cmp(lastPos, pos) == 0) return;
3607
- lastPos = pos;
3608
 
3609
- if (type == "rect") {
3610
- var ranges = [], tabSize = cm.options.tabSize;
3611
- var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
3612
- var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
3613
- var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
3614
- for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
3615
- line <= end; line++) {
3616
- var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
3617
- if (left == right)
3618
- ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
3619
- else if (text.length > leftPos)
3620
- ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
3621
- }
3622
- if (!ranges.length) ranges.push(new Range(start, start));
3623
- setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
3624
- {origin: "*mouse", scroll: false});
3625
- cm.scrollIntoView(pos);
3626
- } else {
3627
- var oldRange = ourRange;
3628
- var anchor = oldRange.anchor, head = pos;
3629
- if (type != "single") {
3630
- if (type == "double")
3631
- var range = cm.findWordAt(pos);
3632
- else
3633
- var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
3634
- if (cmp(range.anchor, anchor) > 0) {
3635
- head = range.head;
3636
- anchor = minPos(oldRange.from(), range.anchor);
3637
- } else {
3638
- head = range.anchor;
3639
- anchor = maxPos(oldRange.to(), range.head);
3640
- }
3641
- }
3642
- var ranges = startSel.ranges.slice(0);
3643
- ranges[ourIndex] = new Range(clipPos(doc, anchor), head);
3644
- setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);
3645
  }
 
3646
  }
 
 
 
 
3647
 
3648
- var editorSize = display.wrapper.getBoundingClientRect();
3649
- // Used to ensure timeout re-tries don't fire when another extend
3650
- // happened in the meantime (clearTimeout isn't reliable -- at
3651
- // least on Chrome, the timeouts still happen even when cleared,
3652
- // if the clear happens after their scheduled firing time).
3653
- var counter = 0;
 
 
3654
 
3655
- function extend(e) {
3656
- var curCount = ++counter;
3657
- var cur = posFromMouse(cm, e, true, type == "rect");
3658
- if (!cur) return;
3659
- if (cmp(cur, lastPos) != 0) {
3660
- ensureFocus(cm);
3661
- extendTo(cur);
3662
- var visible = visibleLines(display, doc);
3663
- if (cur.line >= visible.to || cur.line < visible.from)
3664
- setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
 
 
 
3665
  } else {
3666
- var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
3667
- if (outside) setTimeout(operation(cm, function() {
3668
- if (counter != curCount) return;
3669
- display.scroller.scrollTop += outside;
3670
- extend(e);
3671
- }), 50);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3672
  }
3673
  }
3674
-
3675
- function done(e) {
3676
- counter = Infinity;
3677
- e_preventDefault(e);
3678
- display.input.focus();
3679
- off(document, "mousemove", move);
3680
- off(document, "mouseup", up);
3681
- doc.history.lastSelOrigin = null;
3682
- }
3683
-
3684
- var move = operation(cm, function(e) {
3685
- if (!e_button(e)) done(e);
3686
- else extend(e);
3687
- });
3688
- var up = operation(cm, done);
3689
- on(document, "mousemove", move);
3690
- on(document, "mouseup", up);
3691
  }
3692
 
3693
- // Determines whether an event happened in the gutter, and fires the
3694
- // handlers for the corresponding event.
3695
- function gutterEvent(cm, e, type, prevent, signalfn) {
3696
- try { var mX = e.clientX, mY = e.clientY; }
3697
- catch(e) { return false; }
3698
- if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
3699
- if (prevent) e_preventDefault(e);
3700
-
3701
- var display = cm.display;
3702
- var lineBox = display.lineDiv.getBoundingClientRect();
3703
 
3704
- if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
3705
- mY -= lineBox.top - display.viewOffset;
 
 
 
 
 
3706
 
3707
- for (var i = 0; i < cm.options.gutters.length; ++i) {
3708
- var g = display.gutters.childNodes[i];
3709
- if (g && g.getBoundingClientRect().right >= mX) {
3710
- var line = lineAtHeight(cm.doc, mY);
3711
- var gutter = cm.options.gutters[i];
3712
- signalfn(cm, type, cm, line, gutter, e);
3713
- return e_defaultPrevented(e);
 
 
 
 
3714
  }
3715
  }
 
3716
  }
3717
 
3718
- function clickInGutter(cm, e) {
3719
- return gutterEvent(cm, e, "gutterClick", true, signalLater);
3720
- }
3721
 
3722
- // Kludge to work around strange IE behavior where it'll sometimes
3723
- // re-fire a series of drag-related events right after the drop (#1551)
3724
- var lastDrop = 0;
 
3725
 
3726
- function onDrop(e) {
3727
- var cm = this;
3728
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
3729
- return;
3730
- e_preventDefault(e);
3731
- if (ie) lastDrop = +new Date;
3732
- var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
3733
- if (!pos || isReadOnly(cm)) return;
3734
- // Might be a file drop, in which case we simply extract the text
3735
- // and insert it.
3736
- if (files && files.length && window.FileReader && window.File) {
3737
- var n = files.length, text = Array(n), read = 0;
3738
- var loadFile = function(file, i) {
3739
- var reader = new FileReader;
3740
- reader.onload = operation(cm, function() {
3741
- text[i] = reader.result;
3742
- if (++read == n) {
3743
- pos = clipPos(cm.doc, pos);
3744
- var change = {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"};
3745
- makeChange(cm.doc, change);
3746
- setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
3747
- }
3748
- });
3749
- reader.readAsText(file);
3750
- };
3751
- for (var i = 0; i < n; ++i) loadFile(files[i], i);
3752
- } else { // Normal drop
3753
- // Don't do a replace if the drop happened inside of the selected text.
3754
- if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
3755
- cm.state.draggingText(e);
3756
- // Ensure the editor is re-focused
3757
- setTimeout(function() {cm.display.input.focus();}, 20);
3758
- return;
 
 
 
 
3759
  }
3760
- try {
3761
- var text = e.dataTransfer.getData("Text");
3762
- if (text) {
3763
- if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
3764
- var selected = cm.listSelections();
3765
- setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
3766
- if (selected) for (var i = 0; i < selected.length; ++i)
3767
- replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
3768
- cm.replaceSelection(text, "around", "paste");
3769
- cm.display.input.focus();
3770
- }
3771
  }
3772
- catch(e){}
3773
  }
 
3774
  }
3775
 
3776
- function onDragStart(cm, e) {
3777
- if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
3778
- if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
 
 
 
3779
 
3780
- e.dataTransfer.setData("Text", cm.getSelection());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3781
 
3782
- // Use dummy image instead of default browsers image.
3783
- // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
3784
- if (e.dataTransfer.setDragImage && !safari) {
3785
- var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
3786
- img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
3787
- if (presto) {
3788
- img.width = img.height = 1;
3789
- cm.display.wrapper.appendChild(img);
3790
- // Force a relayout, or Opera won't use our image for some obscure reason
3791
- img._top = img.offsetTop;
3792
- }
3793
- e.dataTransfer.setDragImage(img, 0, 0);
3794
- if (presto) img.parentNode.removeChild(img);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3795
  }
3796
  }
3797
 
3798
- // SCROLL EVENTS
 
 
 
 
 
 
 
 
3799
 
3800
  // Sync the scrollable area and scrollbars, ensure the viewport
3801
  // covers the visible area.
3802
- function setScrollTop(cm, val) {
3803
- if (Math.abs(cm.doc.scrollTop - val) < 2) return;
 
 
 
 
 
 
 
 
 
3804
  cm.doc.scrollTop = val;
3805
- if (!gecko) updateDisplaySimple(cm, {top: val});
3806
- if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
3807
  cm.display.scrollbars.setScrollTop(val);
3808
- if (gecko) updateDisplaySimple(cm);
3809
- startWorker(cm, 100);
3810
  }
 
3811
  // Sync scroller and scrollbar, ensure the gutter elements are
3812
  // aligned.
3813
- function setScrollLeft(cm, val, isScroller) {
3814
- if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
3815
- val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
3816
  cm.doc.scrollLeft = val;
3817
  alignHorizontally(cm);
3818
- if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
3819
  cm.display.scrollbars.setScrollLeft(val);
3820
  }
3821
 
3822
- // Since the delta values reported on mouse wheel events are
3823
- // unstandardized between browsers and even browser versions, and
3824
- // generally horribly unpredictable, this code starts by measuring
3825
- // the scroll effect that the first few mouse wheel events have,
3826
- // and, from that, detects the way it can convert deltas to pixel
3827
- // offsets afterwards.
3828
- //
3829
- // The reason we want to know the amount a wheel event will scroll
3830
- // is that it gives us a chance to update the display before the
3831
- // actual scrolling happens, reducing flickering.
3832
-
3833
- var wheelSamples = 0, wheelPixelsPerUnit = null;
3834
- // Fill in a browser-detected starting value on browsers where we
3835
- // know one. These don't have to be accurate -- the result of them
3836
- // being wrong would just be a slight flicker on the first wheel
3837
- // scroll (if it is large enough).
3838
- if (ie) wheelPixelsPerUnit = -.53;
3839
- else if (gecko) wheelPixelsPerUnit = 15;
3840
- else if (chrome) wheelPixelsPerUnit = -.7;
3841
- else if (safari) wheelPixelsPerUnit = -1/3;
3842
 
3843
- var wheelEventDelta = function(e) {
3844
- var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
3845
- if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
3846
- if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
3847
- else if (dy == null) dy = e.wheelDelta;
3848
- return {x: dx, y: dy};
3849
- };
3850
- CodeMirror.wheelEventPixels = function(e) {
3851
- var delta = wheelEventDelta(e);
3852
- delta.x *= wheelPixelsPerUnit;
3853
- delta.y *= wheelPixelsPerUnit;
3854
- return delta;
3855
- };
 
 
 
 
3856
 
3857
- function onScrollWheel(cm, e) {
3858
- var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
 
 
 
 
3859
 
3860
- var display = cm.display, scroll = display.scroller;
3861
- // Quit if there's nothing to scroll here
3862
- if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
3863
- dy && scroll.scrollHeight > scroll.clientHeight)) return;
 
 
3864
 
3865
- // Webkit browsers on OS X abort momentum scrolls when the target
3866
- // of the scroll event is removed from the scrollable element.
3867
- // This hack (see related code in patchDisplay) makes sure the
3868
- // element is kept around.
3869
- if (dy && mac && webkit) {
3870
- outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
3871
- for (var i = 0; i < view.length; i++) {
3872
- if (view[i].node == cur) {
3873
- cm.display.currentWheelTarget = cur;
3874
- break outer;
3875
- }
3876
- }
3877
- }
3878
- }
3879
 
3880
- // On some browsers, horizontal scrolling will cause redraws to
3881
- // happen before the gutter has been realigned, causing it to
3882
- // wriggle around in a most unseemly way. When we have an
3883
- // estimated pixels/delta value, we just handle horizontal
3884
- // scrolling entirely here. It'll be slightly off from native, but
3885
- // better than glitching out.
3886
- if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
3887
- if (dy)
3888
- setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
3889
- setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
3890
- e_preventDefault(e);
3891
- display.wheelStartX = null; // Abort measurement, if in progress
3892
- return;
 
 
3893
  }
3894
 
3895
- // 'Project' the visible viewport to cover the area that is being
3896
- // scrolled into view (if we know enough to estimate it).
3897
- if (dy && wheelPixelsPerUnit != null) {
3898
- var pixels = dy * wheelPixelsPerUnit;
3899
- var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
3900
- if (pixels < 0) top = Math.max(0, top + pixels - 50);
3901
- else bot = Math.min(cm.doc.height, bot + pixels + 50);
3902
- updateDisplaySimple(cm, {top: top, bottom: bot});
 
 
3903
  }
3904
 
3905
- if (wheelSamples < 20) {
3906
- if (display.wheelStartX == null) {
3907
- display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
3908
- display.wheelDX = dx; display.wheelDY = dy;
3909
- setTimeout(function() {
3910
- if (display.wheelStartX == null) return;
3911
- var movedX = scroll.scrollLeft - display.wheelStartX;
3912
- var movedY = scroll.scrollTop - display.wheelStartY;
3913
- var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
3914
- (movedX && display.wheelDX && movedX / display.wheelDX);
3915
- display.wheelStartX = display.wheelStartY = null;
3916
- if (!sample) return;
3917
- wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
3918
- ++wheelSamples;
3919
- }, 200);
3920
- } else {
3921
- display.wheelDX += dx; display.wheelDY += dy;
3922
- }
3923
  }
3924
- }
3925
 
3926
- // KEY EVENTS
 
3927
 
3928
- // Run a handler that was bound to a key.
3929
- function doHandleBinding(cm, bound, dropShift) {
3930
- if (typeof bound == "string") {
3931
- bound = commands[bound];
3932
- if (!bound) return false;
3933
- }
3934
- // Ensure previous input has been read, so that the handler sees a
3935
- // consistent view of the document
3936
- cm.display.input.ensurePolled();
3937
- var prevShift = cm.display.shift, done = false;
3938
- try {
3939
- if (isReadOnly(cm)) cm.state.suppressEdits = true;
3940
- if (dropShift) cm.display.shift = false;
3941
- done = bound(cm) != Pass;
3942
- } finally {
3943
- cm.display.shift = prevShift;
3944
- cm.state.suppressEdits = false;
3945
- }
3946
- return done;
3947
- }
3948
 
3949
- function lookupKeyForEditor(cm, name, handle) {
3950
- for (var i = 0; i < cm.state.keyMaps.length; i++) {
3951
- var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
3952
- if (result) return result;
3953
- }
3954
- return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
3955
- || lookupKey(name, cm.options.keyMap, handle, cm);
3956
- }
3957
 
3958
- var stopSeq = new Delayed;
3959
- function dispatchKey(cm, name, e, handle) {
3960
- var seq = cm.state.keySeq;
3961
- if (seq) {
3962
- if (isModifierKey(name)) return "handled";
3963
- stopSeq.set(50, function() {
3964
- if (cm.state.keySeq == seq) {
3965
- cm.state.keySeq = null;
3966
- cm.display.input.reset();
3967
- }
3968
- });
3969
- name = seq + " " + name;
3970
- }
3971
- var result = lookupKeyForEditor(cm, name, handle);
3972
 
3973
- if (result == "multi")
3974
- cm.state.keySeq = name;
3975
- if (result == "handled")
3976
- signalLater(cm, "keyHandled", cm, name, e);
 
 
 
 
 
 
 
 
 
 
 
 
 
3977
 
3978
- if (result == "handled" || result == "multi") {
3979
- e_preventDefault(e);
3980
- restartBlink(cm);
3981
- }
 
3982
 
3983
- if (seq && !result && /\'$/.test(name)) {
3984
- e_preventDefault(e);
3985
- return true;
3986
- }
3987
- return !!result;
3988
- }
3989
 
3990
- // Handle a key from the keydown event.
3991
- function handleKeyBinding(cm, e) {
3992
- var name = keyName(e, true);
3993
- if (!name) return false;
3994
 
3995
- if (e.shiftKey && !cm.state.keySeq) {
3996
- // First try to resolve full name (including 'Shift-'). Failing
3997
- // that, see if there is a cursor-motion command (starting with
3998
- // 'go') bound to the keyname without 'Shift-'.
3999
- return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
4000
- || dispatchKey(cm, name, e, function(b) {
4001
- if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
4002
- return doHandleBinding(cm, b);
4003
- });
4004
- } else {
4005
- return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });
4006
  }
4007
  }
4008
 
4009
- // Handle a key from the keypress event
4010
- function handleCharBinding(cm, e, ch) {
4011
- return dispatchKey(cm, "'" + ch + "'", e,
4012
- function(b) { return doHandleBinding(cm, b, true); });
4013
- }
4014
-
4015
- var lastStoppedKey = null;
4016
- function onKeyDown(e) {
4017
- var cm = this;
4018
- ensureFocus(cm);
4019
- if (signalDOMEvent(cm, e)) return;
4020
- // IE does strange things with escape.
4021
- if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
4022
- var code = e.keyCode;
4023
- cm.display.shift = code == 16 || e.shiftKey;
4024
- var handled = handleKeyBinding(cm, e);
4025
- if (presto) {
4026
- lastStoppedKey = handled ? code : null;
4027
- // Opera has no cut event... we try to at least catch the key combo
4028
- if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
4029
- cm.replaceSelection("", null, "cut");
4030
- }
4031
 
4032
- // Turn mouse into crosshair when Alt is held on Mac.
4033
- if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
4034
- showCrossHair(cm);
 
 
 
 
 
 
 
 
 
 
 
4035
  }
4036
 
4037
- function showCrossHair(cm) {
4038
- var lineDiv = cm.display.lineDiv;
4039
- addClass(lineDiv, "CodeMirror-crosshair");
4040
 
4041
- function up(e) {
4042
- if (e.keyCode == 18 || !e.altKey) {
4043
- rmClass(lineDiv, "CodeMirror-crosshair");
4044
- off(document, "keyup", up);
4045
- off(document, "mouseover", up);
4046
- }
4047
  }
4048
- on(document, "keyup", up);
4049
- on(document, "mouseover", up);
4050
- }
4051
 
4052
- function onKeyUp(e) {
4053
- if (e.keyCode == 16) this.doc.sel.shift = false;
4054
- signalDOMEvent(this, e);
 
 
 
 
 
 
 
 
 
 
4055
  }
4056
 
4057
- function onKeyPress(e) {
4058
- var cm = this;
4059
- if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
4060
- var keyCode = e.keyCode, charCode = e.charCode;
4061
- if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
4062
- if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;
4063
- var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
4064
- if (handleCharBinding(cm, e, ch)) return;
4065
- cm.display.input.onKeyPress(e);
4066
- }
4067
 
4068
- // FOCUS/BLUR EVENTS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4069
 
4070
- function onFocus(cm) {
4071
- if (cm.options.readOnly == "nocursor") return;
4072
- if (!cm.state.focused) {
4073
- signal(cm, "focus", cm);
4074
- cm.state.focused = true;
4075
- addClass(cm.display.wrapper, "CodeMirror-focused");
4076
- // This test prevents this from firing when a context
4077
- // menu is closed (since the input reset would kill the
4078
- // select-all detection hack)
4079
- if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
4080
- cm.display.input.reset();
4081
- if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730
4082
- }
4083
- cm.display.input.receivedFocus();
4084
- }
4085
- restartBlink(cm);
4086
  }
4087
- function onBlur(cm) {
4088
- if (cm.state.focused) {
4089
- signal(cm, "blur", cm);
4090
- cm.state.focused = false;
4091
- rmClass(cm.display.wrapper, "CodeMirror-focused");
4092
- }
4093
- clearInterval(cm.display.blinker);
4094
- setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
 
 
 
 
 
 
 
4095
  }
4096
 
4097
- // CONTEXT MENU HANDLING
 
 
 
4098
 
4099
- // To make the context menu work, we need to briefly unhide the
4100
- // textarea (making it as unobtrusive as possible) to let the
4101
- // right-click take effect on it.
4102
- function onContextMenu(cm, e) {
4103
- if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
4104
- cm.display.input.onContextMenu(e);
4105
  }
4106
 
4107
- function contextMenuInGutter(cm, e) {
4108
- if (!hasHandler(cm, "gutterContextMenu")) return false;
4109
- return gutterEvent(cm, e, "gutterContextMenu", false, signal);
4110
  }
4111
 
4112
- // UPDATING
 
 
4113
 
4114
- // Compute the position of the end of a change (its 'to' property
4115
- // refers to the pre-change end).
4116
- var changeEnd = CodeMirror.changeEnd = function(change) {
4117
- if (!change.text) return change.to;
4118
- return Pos(change.from.line + change.text.length - 1,
4119
- lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
4120
- };
4121
 
4122
- // Adjust a position to refer to the post-change position of the
4123
- // same text, or the end of the change if the change covers it.
4124
- function adjustForChange(pos, change) {
4125
- if (cmp(pos, change.from) < 0) return pos;
4126
- if (cmp(pos, change.to) <= 0) return changeEnd(change);
 
 
 
 
 
4127
 
4128
- var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
4129
- if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;
4130
- return Pos(line, ch);
4131
  }
4132
 
4133
- function computeSelAfterChange(doc, change) {
4134
- var out = [];
4135
- for (var i = 0; i < doc.sel.ranges.length; i++) {
4136
- var range = doc.sel.ranges[i];
4137
- out.push(new Range(adjustForChange(range.anchor, change),
4138
- adjustForChange(range.head, change)));
 
 
4139
  }
4140
- return normalizeSelection(out, doc.sel.primIndex);
4141
- }
4142
 
4143
- function offsetPos(pos, old, nw) {
4144
- if (pos.line == old.line)
4145
- return Pos(nw.line, pos.ch - old.ch + nw.ch);
4146
- else
4147
- return Pos(nw.line + (pos.line - old.line), pos.ch);
4148
- }
 
4149
 
4150
- // Used by replaceSelections to allow moving the selection to the
4151
- // start or around the replaced test. Hint may be "start" or "around".
4152
- function computeReplacedSel(doc, changes, hint) {
4153
- var out = [];
4154
- var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
4155
- for (var i = 0; i < changes.length; i++) {
4156
- var change = changes[i];
4157
- var from = offsetPos(change.from, oldPrev, newPrev);
4158
- var to = offsetPos(changeEnd(change), oldPrev, newPrev);
4159
- oldPrev = change.to;
4160
- newPrev = to;
4161
- if (hint == "around") {
4162
- var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
4163
- out[i] = new Range(inv ? to : from, inv ? from : to);
4164
- } else {
4165
- out[i] = new Range(from, from);
4166
- }
4167
- }
4168
- return new Selection(out, doc.sel.primIndex);
4169
  }
4170
 
4171
- // Allow "beforeChange" event handlers to influence a change
4172
- function filterChange(doc, change, update) {
4173
- var obj = {
4174
- canceled: false,
4175
- from: change.from,
4176
- to: change.to,
4177
- text: change.text,
4178
- origin: change.origin,
4179
- cancel: function() { this.canceled = true; }
4180
- };
4181
- if (update) obj.update = function(from, to, text, origin) {
4182
- if (from) this.from = clipPos(doc, from);
4183
- if (to) this.to = clipPos(doc, to);
4184
- if (text) this.text = text;
4185
- if (origin !== undefined) this.origin = origin;
4186
- };
4187
- signal(doc, "beforeChange", doc, obj);
4188
- if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
4189
 
4190
- if (obj.canceled) return null;
4191
- return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
4192
- }
4193
 
4194
- // Apply a change to a document, and add it to the document's
4195
- // history, and propagating it to all linked documents.
4196
- function makeChange(doc, change, ignoreReadOnly) {
4197
- if (doc.cm) {
4198
- if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);
4199
- if (doc.cm.state.suppressEdits) return;
4200
- }
4201
 
4202
- if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
4203
- change = filterChange(doc, change, true);
4204
- if (!change) return;
4205
- }
4206
 
4207
- // Possibly split or suppress the update based on the presence
4208
- // of read-only spans in its range.
4209
- var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
4210
- if (split) {
4211
- for (var i = split.length - 1; i >= 0; --i)
4212
- makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});
4213
- } else {
4214
- makeChangeInner(doc, change);
4215
  }
4216
- }
4217
 
4218
- function makeChangeInner(doc, change) {
4219
- if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;
4220
- var selAfter = computeSelAfterChange(doc, change);
4221
- addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
 
 
 
4222
 
4223
- makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
4224
- var rebased = [];
4225
 
4226
- linkedDocs(doc, function(doc, sharedHist) {
4227
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
4228
- rebaseHist(doc.history, change);
4229
- rebased.push(doc.history);
4230
- }
4231
- makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
4232
- });
4233
  }
4234
 
4235
- // Revert a change stored in a document's history.
4236
- function makeChangeFromHistory(doc, type, allowSelectionOnly) {
4237
- if (doc.cm && doc.cm.state.suppressEdits) return;
4238
-
4239
- var hist = doc.history, event, selAfter = doc.sel;
4240
- var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
4241
-
4242
- // Verify that there is a useable event (so that ctrl-z won't
4243
- // needlessly clear selection events)
4244
- for (var i = 0; i < source.length; i++) {
4245
- event = source[i];
4246
- if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
4247
- break;
4248
- }
4249
- if (i == source.length) return;
4250
- hist.lastOrigin = hist.lastSelOrigin = null;
4251
-
4252
- for (;;) {
4253
- event = source.pop();
4254
- if (event.ranges) {
4255
- pushSelectionToHistory(event, dest);
4256
- if (allowSelectionOnly && !event.equals(doc.sel)) {
4257
- setSelection(doc, event, {clearRedo: false});
4258
- return;
4259
- }
4260
- selAfter = event;
4261
- }
4262
- else break;
 
 
 
 
 
4263
  }
 
4264
 
4265
- // Build up a reverse change object to add to the opposite history
4266
- // stack (redo when undoing, and vice versa).
4267
- var antiChanges = [];
4268
- pushSelectionToHistory(selAfter, dest);
4269
- dest.push({changes: antiChanges, generation: hist.generation});
4270
- hist.generation = event.generation || ++hist.maxGeneration;
4271
 
4272
- var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
 
 
 
4273
 
4274
- for (var i = event.changes.length - 1; i >= 0; --i) {
4275
- var change = event.changes[i];
4276
- change.origin = type;
4277
- if (filter && !filterChange(doc, change, false)) {
4278
- source.length = 0;
4279
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4280
  }
 
 
 
 
 
 
 
 
4281
 
4282
- antiChanges.push(historyChangeFromChange(doc, change));
4283
 
4284
- var after = i ? computeSelAfterChange(doc, change) : lst(source);
4285
- makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
4286
- if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});
4287
- var rebased = [];
4288
 
4289
- // Propagate to the linked documents
4290
- linkedDocs(doc, function(doc, sharedHist) {
4291
- if (!sharedHist && indexOf(rebased, doc.history) == -1) {
4292
- rebaseHist(doc.history, change);
4293
- rebased.push(doc.history);
4294
- }
4295
- makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
4296
- });
4297
- }
4298
- }
 
4299
 
4300
- // Sub-views need their line numbers shifted when text is added
4301
- // above or below them in the parent document.
4302
- function shiftDoc(doc, distance) {
4303
- if (distance == 0) return;
4304
- doc.first += distance;
4305
- doc.sel = new Selection(map(doc.sel.ranges, function(range) {
4306
- return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
4307
- Pos(range.head.line + distance, range.head.ch));
4308
- }), doc.sel.primIndex);
4309
- if (doc.cm) {
4310
- regChange(doc.cm, doc.first, doc.first - distance, distance);
4311
- for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
4312
- regLineChange(doc.cm, l, "gutter");
 
 
 
 
4313
  }
4314
  }
4315
 
4316
- // More lower-level change function, handling only a single document
4317
- // (not linked ones).
4318
- function makeChangeSingleDoc(doc, change, selAfter, spans) {
4319
- if (doc.cm && !doc.cm.curOp)
4320
- return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
4321
-
4322
- if (change.to.line < doc.first) {
4323
- shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
4324
- return;
 
 
 
 
4325
  }
4326
- if (change.from.line > doc.lastLine()) return;
 
4327
 
4328
- // Clip the change to the size of this doc
4329
- if (change.from.line < doc.first) {
4330
- var shift = change.text.length - 1 - (doc.first - change.from.line);
4331
- shiftDoc(doc, shift);
4332
- change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
4333
- text: [lst(change.text)], origin: change.origin};
4334
- }
4335
- var last = doc.lastLine();
4336
- if (change.to.line > last) {
4337
- change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
4338
- text: [change.text[0]], origin: change.origin};
4339
  }
4340
-
4341
- change.removed = getBetween(doc, change.from, change.to);
4342
-
4343
- if (!selAfter) selAfter = computeSelAfterChange(doc, change);
4344
- if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
4345
- else updateDoc(doc, change, spans);
4346
- setSelectionNoUndo(doc, selAfter, sel_dontScroll);
4347
  }
4348
 
4349
- // Handle the interaction of a change to a document with the editor
4350
- // that this document is part of.
4351
- function makeChangeSingleDocInEditor(cm, change, spans) {
4352
- var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
 
4353
 
4354
- var recomputeMaxLength = false, checkWidthStart = from.line;
4355
- if (!cm.options.lineWrapping) {
4356
- checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
4357
- doc.iter(checkWidthStart, to.line + 1, function(line) {
4358
- if (line == display.maxLine) {
4359
- recomputeMaxLength = true;
4360
- return true;
4361
- }
4362
- });
4363
  }
4364
 
4365
- if (doc.sel.contains(change.from, change.to) > -1)
4366
- signalCursorActivity(cm);
4367
-
4368
- updateDoc(doc, change, spans, estimateHeight(cm));
 
 
4369
 
4370
- if (!cm.options.lineWrapping) {
4371
- doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
4372
- var len = lineLength(line);
4373
- if (len > display.maxLineLength) {
4374
- display.maxLine = line;
4375
- display.maxLineLength = len;
4376
- display.maxLineChanged = true;
4377
- recomputeMaxLength = false;
4378
- }
4379
- });
4380
- if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
4381
  }
4382
 
4383
- // Adjust frontier, schedule worker
4384
- doc.frontier = Math.min(doc.frontier, from.line);
4385
- startWorker(cm, 400);
 
 
 
 
 
 
 
4386
 
4387
- var lendiff = change.text.length - (to.line - from.line) - 1;
4388
- // Remember that these lines changed, for updating the display
4389
- if (change.full)
4390
- regChange(cm);
4391
- else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
4392
- regLineChange(cm, from.line, "text");
4393
- else
4394
- regChange(cm, from.line, to.line + 1, lendiff);
4395
 
4396
- var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
4397
- if (changeHandler || changesHandler) {
4398
- var obj = {
4399
- from: from, to: to,
4400
- text: change.text,
4401
- removed: change.removed,
4402
- origin: change.origin
4403
- };
4404
- if (changeHandler) signalLater(cm, "change", cm, obj);
4405
- if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
4406
- }
4407
- cm.display.selForContextMenu = null;
4408
- }
4409
 
4410
- function replaceRange(doc, code, from, to, origin) {
4411
- if (!to) to = from;
4412
- if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
4413
- if (typeof code == "string") code = splitLines(code);
4414
- makeChange(doc, {from: from, to: to, text: code, origin: origin});
4415
- }
4416
 
4417
- // SCROLLING THINGS INTO VIEW
 
 
 
 
 
 
 
 
 
4418
 
4419
- // If an editor sits on the top or bottom of the window, partially
4420
- // scrolled out of view, this ensures that the cursor is visible.
4421
- function maybeScrollWindow(cm, coords) {
4422
- if (signalDOMEvent(cm, "scrollCursorIntoView")) return;
 
4423
 
4424
- var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
4425
- if (coords.top + box.top < 0) doScroll = true;
4426
- else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
4427
- if (doScroll != null && !phantom) {
4428
- var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
4429
- (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +
4430
- (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +
4431
- coords.left + "px; width: 2px;");
4432
- cm.display.lineSpace.appendChild(scrollNode);
4433
- scrollNode.scrollIntoView(doScroll);
4434
- cm.display.lineSpace.removeChild(scrollNode);
4435
  }
4436
- }
4437
 
4438
- // Scroll a given position into view (immediately), verifying that
4439
- // it actually became visible (as line heights are accurately
4440
- // measured, the position of something may 'drift' during drawing).
4441
- function scrollPosIntoView(cm, pos, end, margin) {
4442
- if (margin == null) margin = 0;
4443
- for (var limit = 0; limit < 5; limit++) {
4444
- var changed = false, coords = cursorCoords(cm, pos);
4445
- var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
4446
- var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
4447
- Math.min(coords.top, endCoords.top) - margin,
4448
- Math.max(coords.left, endCoords.left),
4449
- Math.max(coords.bottom, endCoords.bottom) + margin);
4450
- var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
4451
- if (scrollPos.scrollTop != null) {
4452
- setScrollTop(cm, scrollPos.scrollTop);
4453
- if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
4454
- }
4455
- if (scrollPos.scrollLeft != null) {
4456
- setScrollLeft(cm, scrollPos.scrollLeft);
4457
- if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
4458
- }
4459
- if (!changed) break;
4460
- }
4461
- return coords;
4462
- }
4463
 
4464
- // Scroll a given set of coordinates into view (immediately).
4465
- function scrollIntoView(cm, x1, y1, x2, y2) {
4466
- var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
4467
- if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
4468
- if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
4469
  }
4470
 
4471
- // Calculate a new scroll position needed to scroll the given
4472
- // rectangle into view. Returns an object with scrollTop and
4473
- // scrollLeft properties. When these are undefined, the
4474
- // vertical/horizontal position does not need to be adjusted.
4475
- function calculateScrollPos(cm, x1, y1, x2, y2) {
4476
- var display = cm.display, snapMargin = textHeight(cm.display);
4477
- if (y1 < 0) y1 = 0;
4478
- var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
4479
- var screen = displayHeight(cm), result = {};
4480
- if (y2 - y1 > screen) y2 = y1 + screen;
4481
- var docBottom = cm.doc.height + paddingVert(display);
4482
- var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
4483
- if (y1 < screentop) {
4484
- result.scrollTop = atTop ? 0 : y1;
4485
- } else if (y2 > screentop + screen) {
4486
- var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
4487
- if (newTop != screentop) result.scrollTop = newTop;
4488
- }
4489
-
4490
- var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
4491
- var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
4492
- var tooWide = x2 - x1 > screenw;
4493
- if (tooWide) x2 = x1 + screenw;
4494
- if (x1 < 10)
4495
- result.scrollLeft = 0;
4496
- else if (x1 < screenleft)
4497
- result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));
4498
- else if (x2 > screenw + screenleft - 3)
4499
- result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;
4500
- return result;
4501
- }
4502
 
4503
- // Store a relative adjustment to the scroll position in the current
4504
- // operation (to be applied when the operation finishes).
4505
- function addToScrollPos(cm, left, top) {
4506
- if (left != null || top != null) resolveScrollToPos(cm);
4507
- if (left != null)
4508
- cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;
4509
- if (top != null)
4510
- cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
4511
- }
 
 
 
 
 
 
 
 
 
 
 
 
4512
 
4513
- // Make sure that at the end of the operation the current cursor is
4514
- // shown.
4515
- function ensureCursorVisible(cm) {
4516
- resolveScrollToPos(cm);
4517
- var cur = cm.getCursor(), from = cur, to = cur;
4518
- if (!cm.options.lineWrapping) {
4519
- from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
4520
- to = Pos(cur.line, cur.ch + 1);
4521
  }
4522
- cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};
4523
  }
4524
 
4525
- // When an operation has its scrollToPos property set, and another
4526
- // scroll action is applied before the end of the operation, this
4527
- // 'simulates' scrolling that position into view in a cheap way, so
4528
- // that the effect of intermediate scroll commands is not ignored.
4529
- function resolveScrollToPos(cm) {
4530
- var range = cm.curOp.scrollToPos;
4531
- if (range) {
4532
- cm.curOp.scrollToPos = null;
4533
- var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
4534
- var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
4535
- Math.min(from.top, to.top) - range.margin,
4536
- Math.max(from.right, to.right),
4537
- Math.max(from.bottom, to.bottom) + range.margin);
4538
- cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
4539
  }
4540
  }
4541
 
4542
- // API UTILITIES
4543
-
4544
- // Indent the given line. The how parameter can be "smart",
4545
- // "add"/null, "subtract", or "prev". When aggressive is false
4546
- // (typically set to true for forced single-line indents), empty
4547
- // lines are not indented, and places where the mode returns Pass
4548
- // are left alone.
4549
- function indentLine(cm, n, how, aggressive) {
4550
- var doc = cm.doc, state;
4551
- if (how == null) how = "add";
4552
- if (how == "smart") {
4553
- // Fall back to "prev" when the mode doesn't have an indentation
4554
- // method.
4555
- if (!doc.mode.indent) how = "prev";
4556
- else state = getStateBefore(cm, n);
4557
- }
4558
 
4559
- var tabSize = cm.options.tabSize;
4560
- var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
4561
- if (line.stateAfter) line.stateAfter = null;
4562
- var curSpaceString = line.text.match(/^\s*/)[0], indentation;
4563
- if (!aggressive && !/\S/.test(line.text)) {
4564
- indentation = 0;
4565
- how = "not";
4566
- } else if (how == "smart") {
4567
- indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
4568
- if (indentation == Pass || indentation > 150) {
4569
- if (!aggressive) return;
4570
- how = "prev";
4571
- }
4572
- }
4573
- if (how == "prev") {
4574
- if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
4575
- else indentation = 0;
4576
- } else if (how == "add") {
4577
- indentation = curSpace + cm.options.indentUnit;
4578
- } else if (how == "subtract") {
4579
- indentation = curSpace - cm.options.indentUnit;
4580
- } else if (typeof how == "number") {
4581
- indentation = curSpace + how;
4582
  }
4583
- indentation = Math.max(0, indentation);
4584
-
4585
- var indentString = "", pos = 0;
4586
- if (cm.options.indentWithTabs)
4587
- for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
4588
- if (pos < indentation) indentString += spaceStr(indentation - pos);
4589
 
4590
- if (indentString != curSpaceString) {
4591
- replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
4592
- } else {
4593
- // Ensure that, if the cursor was in the whitespace at the start
4594
- // of the line, it is moved to the end of that space.
4595
- for (var i = 0; i < doc.sel.ranges.length; i++) {
4596
- var range = doc.sel.ranges[i];
4597
- if (range.head.line == n && range.head.ch < curSpaceString.length) {
4598
- var pos = Pos(n, curSpaceString.length);
4599
- replaceOneSelection(doc, i, new Range(pos, pos));
4600
- break;
 
 
 
 
 
 
 
 
4601
  }
 
4602
  }
 
4603
  }
4604
- line.stateAfter = null;
4605
  }
4606
 
4607
- // Utility for applying a change to a line by handle or number,
4608
- // returning the number and optionally registering the line as
4609
- // changed.
4610
- function changeLine(doc, handle, changeType, op) {
4611
- var no = handle, line = handle;
4612
- if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
4613
- else no = lineNo(handle);
4614
- if (no == null) return null;
4615
- if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);
4616
- return line;
4617
  }
4618
 
4619
- // Helper for deleting text near the selection(s), used to implement
4620
- // backspace, delete, and similar functionality.
4621
- function deleteNearSelection(cm, compute) {
4622
- var ranges = cm.doc.sel.ranges, kill = [];
4623
- // Build up a set of ranges to kill first, merging overlapping
4624
- // ranges.
4625
- for (var i = 0; i < ranges.length; i++) {
4626
- var toKill = compute(ranges[i]);
4627
- while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
4628
- var replaced = kill.pop();
4629
- if (cmp(replaced.from, toKill.from) < 0) {
4630
- toKill.from = replaced.from;
4631
- break;
4632
- }
4633
- }
4634
- kill.push(toKill);
4635
- }
4636
- // Next, remove those actual ranges.
4637
- runInOp(cm, function() {
4638
- for (var i = kill.length - 1; i >= 0; i--)
4639
- replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");
4640
- ensureCursorVisible(cm);
4641
- });
4642
  }
4643
 
4644
- // Used for horizontal relative motion. Dir is -1 or 1 (left or
4645
- // right), unit can be "char", "column" (like char, but doesn't
4646
- // cross line boundaries), "word" (across next word), or "group" (to
4647
- // the start of next group of word or non-word-non-whitespace
4648
- // chars). The visually param controls whether, in right-to-left
4649
- // text, direction 1 means to move towards the next index in the
4650
- // string, or towards the character to the right of the current
4651
- // position. The resulting position will have a hitSide=true
4652
- // property if it reached the end of the document.
4653
- function findPosH(doc, pos, dir, unit, visually) {
4654
- var line = pos.line, ch = pos.ch, origDir = dir;
4655
- var lineObj = getLine(doc, line);
4656
- var possible = true;
4657
- function findNextLine() {
4658
- var l = line + dir;
4659
- if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
4660
- line = l;
4661
- return lineObj = getLine(doc, l);
4662
- }
4663
- function moveOnce(boundToLine) {
4664
- var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
4665
- if (next == null) {
4666
- if (!boundToLine && findNextLine()) {
4667
- if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
4668
- else ch = dir < 0 ? lineObj.text.length : 0;
4669
- } else return (possible = false);
4670
- } else ch = next;
4671
- return true;
4672
- }
4673
-
4674
- if (unit == "char") moveOnce();
4675
- else if (unit == "column") moveOnce(true);
4676
- else if (unit == "word" || unit == "group") {
4677
- var sawType = null, group = unit == "group";
4678
- var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
4679
- for (var first = true;; first = false) {
4680
- if (dir < 0 && !moveOnce(!first)) break;
4681
- var cur = lineObj.text.charAt(ch) || "\n";
4682
- var type = isWordChar(cur, helper) ? "w"
4683
- : group && cur == "\n" ? "n"
4684
- : !group || /\s/.test(cur) ? null
4685
- : "p";
4686
- if (group && !first && !type) type = "s";
4687
- if (sawType && sawType != type) {
4688
- if (dir < 0) {dir = 1; moveOnce();}
4689
- break;
4690
- }
4691
-
4692
- if (type) sawType = type;
4693
- if (dir > 0 && !moveOnce(!first)) break;
4694
  }
4695
- }
4696
- var result = skipAtomic(doc, Pos(line, ch), origDir, true);
4697
- if (!possible) result.hitSide = true;
4698
- return result;
 
 
4699
  }
4700
 
4701
- // For relative vertical movement. Dir may be -1 or 1. Unit can be
4702
- // "page" or "line". The resulting position will have a hitSide=true
4703
- // property if it reached the end of the document.
4704
- function findPosV(cm, pos, dir, unit) {
4705
- var doc = cm.doc, x = pos.left, y;
4706
- if (unit == "page") {
4707
- var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
4708
- y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
4709
- } else if (unit == "line") {
4710
- y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
4711
- }
4712
- for (;;) {
4713
- var target = coordsChar(cm, x, y);
4714
- if (!target.outside) break;
4715
- if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
4716
- y += dir * 5;
 
4717
  }
4718
- return target;
4719
  }
4720
 
4721
- // EDITOR METHODS
4722
-
4723
- // The publicly visible API. Note that methodOp(f) means
4724
- // 'wrap f in an operation, performed on its `this` parameter'.
4725
-
4726
- // This is not the complete set of editor methods. Most of the
4727
- // methods defined on the Doc type are also injected into
4728
- // CodeMirror.prototype, for backwards compatibility and
4729
- // convenience.
4730
-
4731
- CodeMirror.prototype = {
4732
- constructor: CodeMirror,
4733
- focus: function(){window.focus(); this.display.input.focus();},
4734
-
4735
- setOption: function(option, value) {
4736
- var options = this.options, old = options[option];
4737
- if (options[option] == value && option != "mode") return;
4738
- options[option] = value;
4739
- if (optionHandlers.hasOwnProperty(option))
4740
- operation(this, optionHandlers[option])(this, value, old);
4741
- },
4742
-
4743
- getOption: function(option) {return this.options[option];},
4744
- getDoc: function() {return this.doc;},
4745
-
4746
- addKeyMap: function(map, bottom) {
4747
- this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
4748
- },
4749
- removeKeyMap: function(map) {
4750
- var maps = this.state.keyMaps;
4751
- for (var i = 0; i < maps.length; ++i)
4752
- if (maps[i] == map || maps[i].name == map) {
4753
- maps.splice(i, 1);
4754
- return true;
4755
- }
4756
- },
4757
-
4758
- addOverlay: methodOp(function(spec, options) {
4759
- var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
4760
- if (mode.startState) throw new Error("Overlays may not be stateful.");
4761
- this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
4762
- this.state.modeGen++;
4763
- regChange(this);
4764
- }),
4765
- removeOverlay: methodOp(function(spec) {
4766
- var overlays = this.state.overlays;
4767
- for (var i = 0; i < overlays.length; ++i) {
4768
- var cur = overlays[i].modeSpec;
4769
- if (cur == spec || typeof spec == "string" && cur.name == spec) {
4770
- overlays.splice(i, 1);
4771
- this.state.modeGen++;
4772
- regChange(this);
4773
- return;
4774
- }
4775
  }
4776
- }),
 
 
 
 
4777
 
4778
- indentLine: methodOp(function(n, dir, aggressive) {
4779
- if (typeof dir != "string" && typeof dir != "number") {
4780
- if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
4781
- else dir = dir ? "add" : "subtract";
4782
- }
4783
- if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
4784
- }),
4785
- indentSelection: methodOp(function(how) {
4786
- var ranges = this.doc.sel.ranges, end = -1;
4787
- for (var i = 0; i < ranges.length; i++) {
4788
- var range = ranges[i];
4789
- if (!range.empty()) {
4790
- var from = range.from(), to = range.to();
4791
- var start = Math.max(end, from.line);
4792
- end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
4793
- for (var j = start; j < end; ++j)
4794
- indentLine(this, j, how);
4795
- var newRanges = this.doc.sel.ranges;
4796
- if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
4797
- replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);
4798
- } else if (range.head.line > end) {
4799
- indentLine(this, range.head.line, how, true);
4800
- end = range.head.line;
4801
- if (i == this.doc.sel.primIndex) ensureCursorVisible(this);
4802
- }
4803
  }
4804
- }),
4805
-
4806
- // Fetch the parser token for a given character. Useful for hacks
4807
- // that want to inspect the mode state (say, for completion).
4808
- getTokenAt: function(pos, precise) {
4809
- return takeToken(this, pos, precise);
4810
- },
4811
-
4812
- getLineTokens: function(line, precise) {
4813
- return takeToken(this, Pos(line), precise, true);
4814
- },
4815
 
4816
- getTokenTypeAt: function(pos) {
4817
- pos = clipPos(this.doc, pos);
4818
- var styles = getLineStyles(this, getLine(this.doc, pos.line));
4819
- var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
4820
- var type;
4821
- if (ch == 0) type = styles[2];
4822
- else for (;;) {
4823
- var mid = (before + after) >> 1;
4824
- if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
4825
- else if (styles[mid * 2 + 1] < ch) before = mid + 1;
4826
- else { type = styles[mid * 2 + 2]; break; }
4827
- }
4828
- var cut = type ? type.indexOf("cm-overlay ") : -1;
4829
- return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);
4830
- },
4831
 
4832
- getModeAt: function(pos) {
4833
- var mode = this.doc.mode;
4834
- if (!mode.innerMode) return mode;
4835
- return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
4836
- },
4837
 
4838
- getHelper: function(pos, type) {
4839
- return this.getHelpers(pos, type)[0];
4840
- },
4841
 
4842
- getHelpers: function(pos, type) {
4843
- var found = [];
4844
- if (!helpers.hasOwnProperty(type)) return found;
4845
- var help = helpers[type], mode = this.getModeAt(pos);
4846
- if (typeof mode[type] == "string") {
4847
- if (help[mode[type]]) found.push(help[mode[type]]);
4848
- } else if (mode[type]) {
4849
- for (var i = 0; i < mode[type].length; i++) {
4850
- var val = help[mode[type][i]];
4851
- if (val) found.push(val);
4852
- }
4853
- } else if (mode.helperType && help[mode.helperType]) {
4854
- found.push(help[mode.helperType]);
4855
- } else if (help[mode.name]) {
4856
- found.push(help[mode.name]);
4857
- }
4858
- for (var i = 0; i < help._global.length; i++) {
4859
- var cur = help._global[i];
4860
- if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
4861
- found.push(cur.val);
4862
- }
4863
- return found;
4864
- },
4865
-
4866
- getStateAfter: function(line, precise) {
4867
- var doc = this.doc;
4868
- line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
4869
- return getStateBefore(this, line + 1, precise);
4870
- },
4871
-
4872
- cursorCoords: function(start, mode) {
4873
- var pos, range = this.doc.sel.primary();
4874
- if (start == null) pos = range.head;
4875
- else if (typeof start == "object") pos = clipPos(this.doc, start);
4876
- else pos = start ? range.from() : range.to();
4877
- return cursorCoords(this, pos, mode || "page");
4878
- },
4879
 
4880
- charCoords: function(pos, mode) {
4881
- return charCoords(this, clipPos(this.doc, pos), mode || "page");
4882
- },
4883
 
4884
- coordsChar: function(coords, mode) {
4885
- coords = fromCoordSystem(this, coords, mode || "page");
4886
- return coordsChar(this, coords.left, coords.top);
4887
- },
4888
 
4889
- lineAtHeight: function(height, mode) {
4890
- height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
4891
- return lineAtHeight(this.doc, height + this.display.viewOffset);
4892
- },
4893
- heightAtLine: function(line, mode) {
4894
- var end = false, last = this.doc.first + this.doc.size - 1;
4895
- if (line < this.doc.first) line = this.doc.first;
4896
- else if (line > last) { line = last; end = true; }
4897
- var lineObj = getLine(this.doc, line);
4898
- return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
4899
- (end ? this.doc.height - heightAtLine(lineObj) : 0);
4900
- },
 
4901
 
4902
- defaultTextHeight: function() { return textHeight(this.display); },
4903
- defaultCharWidth: function() { return charWidth(this.display); },
4904
 
4905
- setGutterMarker: methodOp(function(line, gutterID, value) {
4906
- return changeLine(this.doc, line, "gutter", function(line) {
4907
- var markers = line.gutterMarkers || (line.gutterMarkers = {});
4908
- markers[gutterID] = value;
4909
- if (!value && isEmpty(markers)) line.gutterMarkers = null;
4910
- return true;
4911
- });
4912
- }),
4913
 
4914
- clearGutter: methodOp(function(gutterID) {
4915
- var cm = this, doc = cm.doc, i = doc.first;
4916
- doc.iter(function(line) {
4917
- if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
4918
- line.gutterMarkers[gutterID] = null;
4919
- regLineChange(cm, i, "gutter");
4920
- if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
4921
- }
4922
- ++i;
4923
- });
4924
- }),
4925
 
4926
- addLineWidget: methodOp(function(handle, node, options) {
4927
- return addLineWidget(this, handle, node, options);
4928
- }),
 
 
4929
 
4930
- removeLineWidget: function(widget) { widget.clear(); },
 
4931
 
4932
- lineInfo: function(line) {
4933
- if (typeof line == "number") {
4934
- if (!isLine(this.doc, line)) return null;
4935
- var n = line;
4936
- line = getLine(this.doc, line);
4937
- if (!line) return null;
4938
- } else {
4939
- var n = lineNo(line);
4940
- if (n == null) return null;
4941
- }
4942
- return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
4943
- textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
4944
- widgets: line.widgets};
4945
- },
4946
 
4947
- getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},
4948
-
4949
- addWidget: function(pos, node, scroll, vert, horiz) {
4950
- var display = this.display;
4951
- pos = cursorCoords(this, clipPos(this.doc, pos));
4952
- var top = pos.bottom, left = pos.left;
4953
- node.style.position = "absolute";
4954
- node.setAttribute("cm-ignore-events", "true");
4955
- this.display.input.setUneditable(node);
4956
- display.sizer.appendChild(node);
4957
- if (vert == "over") {
4958
- top = pos.top;
4959
- } else if (vert == "above" || vert == "near") {
4960
- var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
4961
- hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
4962
- // Default to positioning above (if specified and possible); otherwise default to positioning below
4963
- if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
4964
- top = pos.top - node.offsetHeight;
4965
- else if (pos.bottom + node.offsetHeight <= vspace)
4966
- top = pos.bottom;
4967
- if (left + node.offsetWidth > hspace)
4968
- left = hspace - node.offsetWidth;
4969
- }
4970
- node.style.top = top + "px";
4971
- node.style.left = node.style.right = "";
4972
- if (horiz == "right") {
4973
- left = display.sizer.clientWidth - node.offsetWidth;
4974
- node.style.right = "0px";
4975
- } else {
4976
- if (horiz == "left") left = 0;
4977
- else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
4978
- node.style.left = left + "px";
4979
- }
4980
- if (scroll)
4981
- scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
4982
- },
4983
 
4984
- triggerOnKeyDown: methodOp(onKeyDown),
4985
- triggerOnKeyPress: methodOp(onKeyPress),
4986
- triggerOnKeyUp: onKeyUp,
4987
 
4988
- execCommand: function(cmd) {
4989
- if (commands.hasOwnProperty(cmd))
4990
- return commands[cmd](this);
4991
- },
4992
 
4993
- findPosH: function(from, amount, unit, visually) {
4994
- var dir = 1;
4995
- if (amount < 0) { dir = -1; amount = -amount; }
4996
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
4997
- cur = findPosH(this.doc, cur, dir, unit, visually);
4998
- if (cur.hitSide) break;
4999
- }
5000
- return cur;
5001
- },
5002
 
5003
- moveH: methodOp(function(dir, unit) {
5004
- var cm = this;
5005
- cm.extendSelectionsBy(function(range) {
5006
- if (cm.display.shift || cm.doc.extend || range.empty())
5007
- return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);
5008
- else
5009
- return dir < 0 ? range.from() : range.to();
5010
- }, sel_move);
5011
- }),
 
5012
 
5013
- deleteH: methodOp(function(dir, unit) {
5014
- var sel = this.doc.sel, doc = this.doc;
5015
- if (sel.somethingSelected())
5016
- doc.replaceSelection("", null, "+delete");
5017
- else
5018
- deleteNearSelection(this, function(range) {
5019
- var other = findPosH(doc, range.head, dir, unit, false);
5020
- return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
5021
- });
5022
- }),
5023
 
5024
- findPosV: function(from, amount, unit, goalColumn) {
5025
- var dir = 1, x = goalColumn;
5026
- if (amount < 0) { dir = -1; amount = -amount; }
5027
- for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
5028
- var coords = cursorCoords(this, cur, "div");
5029
- if (x == null) x = coords.left;
5030
- else coords.left = x;
5031
- cur = findPosV(this, coords, dir, unit);
5032
- if (cur.hitSide) break;
5033
- }
5034
- return cur;
5035
- },
 
5036
 
5037
- moveV: methodOp(function(dir, unit) {
5038
- var cm = this, doc = this.doc, goals = [];
5039
- var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();
5040
- doc.extendSelectionsBy(function(range) {
5041
- if (collapse)
5042
- return dir < 0 ? range.from() : range.to();
5043
- var headPos = cursorCoords(cm, range.head, "div");
5044
- if (range.goalColumn != null) headPos.left = range.goalColumn;
5045
- goals.push(headPos.left);
5046
- var pos = findPosV(cm, headPos, dir, unit);
5047
- if (unit == "page" && range == doc.sel.primary())
5048
- addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);
5049
- return pos;
5050
- }, sel_move);
5051
- if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
5052
- doc.sel.ranges[i].goalColumn = goals[i];
5053
- }),
5054
 
5055
- // Find the word at the given position (as returned by coordsChar).
5056
- findWordAt: function(pos) {
5057
- var doc = this.doc, line = getLine(doc, pos.line).text;
5058
- var start = pos.ch, end = pos.ch;
5059
- if (line) {
5060
- var helper = this.getHelper(pos, "wordChars");
5061
- if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
5062
- var startChar = line.charAt(start);
5063
- var check = isWordChar(startChar, helper)
5064
- ? function(ch) { return isWordChar(ch, helper); }
5065
- : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
5066
- : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
5067
- while (start > 0 && check(line.charAt(start - 1))) --start;
5068
- while (end < line.length && check(line.charAt(end))) ++end;
5069
- }
5070
- return new Range(Pos(pos.line, start), Pos(pos.line, end));
5071
- },
5072
 
5073
- toggleOverwrite: function(value) {
5074
- if (value != null && value == this.state.overwrite) return;
5075
- if (this.state.overwrite = !this.state.overwrite)
5076
- addClass(this.display.cursorDiv, "CodeMirror-overwrite");
5077
- else
5078
- rmClass(this.display.cursorDiv, "CodeMirror-overwrite");
 
 
 
 
 
 
 
 
5079
 
5080
- signal(this, "overwriteToggle", this, this.state.overwrite);
5081
- },
5082
- hasFocus: function() { return this.display.input.getField() == activeElt(); },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5083
 
5084
- scrollTo: methodOp(function(x, y) {
5085
- if (x != null || y != null) resolveScrollToPos(this);
5086
- if (x != null) this.curOp.scrollLeft = x;
5087
- if (y != null) this.curOp.scrollTop = y;
5088
- }),
5089
- getScrollInfo: function() {
5090
- var scroller = this.display.scroller;
5091
- return {left: scroller.scrollLeft, top: scroller.scrollTop,
5092
- height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
5093
- width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
5094
- clientHeight: displayHeight(this), clientWidth: displayWidth(this)};
5095
- },
5096
 
5097
- scrollIntoView: methodOp(function(range, margin) {
5098
- if (range == null) {
5099
- range = {from: this.doc.sel.primary().head, to: null};
5100
- if (margin == null) margin = this.options.cursorScrollMargin;
5101
- } else if (typeof range == "number") {
5102
- range = {from: Pos(range, 0), to: null};
5103
- } else if (range.from == null) {
5104
- range = {from: range, to: null};
5105
- }
5106
- if (!range.to) range.to = range.from;
5107
- range.margin = margin || 0;
5108
-
5109
- if (range.from.line != null) {
5110
- resolveScrollToPos(this);
5111
- this.curOp.scrollToPos = range;
5112
  } else {
5113
- var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
5114
- Math.min(range.from.top, range.to.top) - range.margin,
5115
- Math.max(range.from.right, range.to.right),
5116
- Math.max(range.from.bottom, range.to.bottom) + range.margin);
5117
- this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
5118
  }
5119
- }),
5120
-
5121
- setSize: methodOp(function(width, height) {
5122
- var cm = this;
5123
- function interpret(val) {
5124
- return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
5125
- }
5126
- if (width != null) cm.display.wrapper.style.width = interpret(width);
5127
- if (height != null) cm.display.wrapper.style.height = interpret(height);
5128
- if (cm.options.lineWrapping) clearLineMeasurementCache(this);
5129
- var lineNo = cm.display.viewFrom;
5130
- cm.doc.iter(lineNo, cm.display.viewTo, function(line) {
5131
- if (line.widgets) for (var i = 0; i < line.widgets.length; i++)
5132
- if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; }
5133
- ++lineNo;
5134
- });
5135
- cm.curOp.forceUpdate = true;
5136
- signal(cm, "refresh", this);
5137
- }),
5138
 
5139
- operation: function(f){return runInOp(this, f);},
5140
-
5141
- refresh: methodOp(function() {
5142
- var oldHeight = this.display.cachedTextHeight;
5143
- regChange(this);
5144
- this.curOp.forceUpdate = true;
5145
- clearCaches(this);
5146
- this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
5147
- updateGutterSpace(this);
5148
- if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
5149
- estimateLineHeights(this);
5150
- signal(this, "refresh", this);
5151
- }),
5152
 
5153
- swapDoc: methodOp(function(doc) {
5154
- var old = this.doc;
5155
- old.cm = null;
5156
- attachDoc(this, doc);
5157
- clearCaches(this);
5158
- this.display.input.reset();
5159
- this.scrollTo(doc.scrollLeft, doc.scrollTop);
5160
- this.curOp.forceScroll = true;
5161
- signalLater(this, "swapDoc", this, old);
5162
- return old;
5163
- }),
5164
 
5165
- getInputField: function(){return this.display.input.getField();},
5166
- getWrapperElement: function(){return this.display.wrapper;},
5167
- getScrollerElement: function(){return this.display.scroller;},
5168
- getGutterElement: function(){return this.display.gutters;}
 
 
 
 
5169
  };
5170
- eventMixin(CodeMirror);
5171
 
5172
- // OPTION DEFAULTS
 
 
 
 
 
5173
 
5174
- // The default configuration options.
5175
- var defaults = CodeMirror.defaults = {};
5176
- // Functions to run when options are changed.
5177
- var optionHandlers = CodeMirror.optionHandlers = {};
 
5178
 
5179
- function option(name, deflt, handle, notOnInit) {
5180
- CodeMirror.defaults[name] = deflt;
5181
- if (handle) optionHandlers[name] =
5182
- notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
5183
- }
 
 
 
 
5184
 
5185
- // Passed to option handlers when there is no old value.
5186
- var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
 
5187
 
5188
- // These two are, on init, called from the constructor because they
5189
- // have to be initialized before the editor can start at all.
5190
- option("value", "", function(cm, val) {
5191
- cm.setValue(val);
5192
- }, true);
5193
- option("mode", null, function(cm, val) {
5194
- cm.doc.modeOption = val;
5195
- loadMode(cm);
5196
- }, true);
5197
 
5198
- option("indentUnit", 2, loadMode, true);
5199
- option("indentWithTabs", false);
5200
- option("smartIndent", true);
5201
- option("tabSize", 4, function(cm) {
5202
- resetModeState(cm);
5203
- clearCaches(cm);
5204
- regChange(cm);
5205
- }, true);
5206
- option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
5207
- cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
5208
- if (old != CodeMirror.Init) cm.refresh();
5209
- });
5210
- option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
5211
- option("electricChars", true);
5212
- option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
5213
- throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME
5214
- }, true);
5215
- option("rtlMoveVisually", !windows);
5216
- option("wholeLineUpdateBefore", true);
5217
-
5218
- option("theme", "default", function(cm) {
5219
- themeChanged(cm);
5220
- guttersChanged(cm);
5221
- }, true);
5222
- option("keyMap", "default", function(cm, val, old) {
5223
- var next = getKeyMap(val);
5224
- var prev = old != CodeMirror.Init && getKeyMap(old);
5225
- if (prev && prev.detach) prev.detach(cm, next);
5226
- if (next.attach) next.attach(cm, prev || null);
5227
- });
5228
- option("extraKeys", null);
5229
-
5230
- option("lineWrapping", false, wrappingChanged, true);
5231
- option("gutters", [], function(cm) {
5232
- setGuttersForLineNumbers(cm.options);
5233
- guttersChanged(cm);
5234
- }, true);
5235
- option("fixedGutter", true, function(cm, val) {
5236
- cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
5237
- cm.refresh();
5238
- }, true);
5239
- option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);
5240
- option("scrollbarStyle", "native", function(cm) {
5241
- initScrollbars(cm);
5242
- updateScrollbars(cm);
5243
- cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
5244
- cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
5245
- }, true);
5246
- option("lineNumbers", false, function(cm) {
5247
- setGuttersForLineNumbers(cm.options);
5248
- guttersChanged(cm);
5249
- }, true);
5250
- option("firstLineNumber", 1, guttersChanged, true);
5251
- option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
5252
- option("showCursorWhenSelecting", false, updateSelection, true);
5253
-
5254
- option("resetSelectionOnContextMenu", true);
5255
-
5256
- option("readOnly", false, function(cm, val) {
5257
- if (val == "nocursor") {
5258
- onBlur(cm);
5259
- cm.display.input.blur();
5260
- cm.display.disabled = true;
5261
- } else {
5262
- cm.display.disabled = false;
5263
- if (!val) cm.display.input.reset();
5264
  }
5265
- });
5266
- option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
5267
- option("dragDrop", true);
5268
-
5269
- option("cursorBlinkRate", 530);
5270
- option("cursorScrollMargin", 0);
5271
- option("cursorHeight", 1, updateSelection, true);
5272
- option("singleCursorHeightPerLine", true, updateSelection, true);
5273
- option("workTime", 100);
5274
- option("workDelay", 100);
5275
- option("flattenSpans", true, resetModeState, true);
5276
- option("addModeClass", false, resetModeState, true);
5277
- option("pollInterval", 100);
5278
- option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});
5279
- option("historyEventDelay", 1250);
5280
- option("viewportMargin", 10, function(cm){cm.refresh();}, true);
5281
- option("maxHighlightLength", 10000, resetModeState, true);
5282
- option("moveInputWithCursor", true, function(cm, val) {
5283
- if (!val) cm.display.input.resetPosition();
5284
- });
5285
-
5286
- option("tabindex", null, function(cm, val) {
5287
- cm.display.input.getField().tabIndex = val || "";
5288
- });
5289
- option("autofocus", null);
5290
 
5291
- // MODE DEFINITION AND QUERYING
 
 
5292
 
5293
- // Known modes, by name and by MIME
5294
- var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
 
 
 
 
 
5295
 
5296
- // Extra arguments are stored as the mode's dependencies, which is
5297
- // used by (legacy) mechanisms like loadmode.js to automatically
5298
- // load a mode. (Preferred mechanism is the require/define calls.)
5299
- CodeMirror.defineMode = function(name, mode) {
5300
- if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
5301
- if (arguments.length > 2)
5302
- mode.dependencies = Array.prototype.slice.call(arguments, 2);
5303
- modes[name] = mode;
5304
- };
5305
 
5306
- CodeMirror.defineMIME = function(mime, spec) {
5307
- mimeModes[mime] = spec;
5308
- };
 
5309
 
5310
- // Given a MIME type, a {name, ...options} config object, or a name
5311
- // string, return a mode config object.
5312
- CodeMirror.resolveMode = function(spec) {
5313
- if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
5314
- spec = mimeModes[spec];
5315
- } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
5316
- var found = mimeModes[spec.name];
5317
- if (typeof found == "string") found = {name: found};
5318
- spec = createObj(found, spec);
5319
- spec.name = found.name;
5320
- } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
5321
- return CodeMirror.resolveMode("application/xml");
5322
  }
5323
- if (typeof spec == "string") return {name: spec};
5324
- else return spec || {name: "null"};
5325
- };
5326
 
5327
- // Given a mode spec (anything that resolveMode accepts), find and
5328
- // initialize an actual mode object.
5329
- CodeMirror.getMode = function(options, spec) {
5330
- var spec = CodeMirror.resolveMode(spec);
5331
- var mfactory = modes[spec.name];
5332
- if (!mfactory) return CodeMirror.getMode(options, "text/plain");
5333
- var modeObj = mfactory(options, spec);
5334
- if (modeExtensions.hasOwnProperty(spec.name)) {
5335
- var exts = modeExtensions[spec.name];
5336
- for (var prop in exts) {
5337
- if (!exts.hasOwnProperty(prop)) continue;
5338
- if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
5339
- modeObj[prop] = exts[prop];
 
 
 
 
 
 
 
 
 
 
5340
  }
5341
  }
5342
- modeObj.name = spec.name;
5343
- if (spec.helperType) modeObj.helperType = spec.helperType;
5344
- if (spec.modeProps) for (var prop in spec.modeProps)
5345
- modeObj[prop] = spec.modeProps[prop];
5346
-
5347
- return modeObj;
5348
- };
5349
-
5350
- // Minimal default mode.
5351
- CodeMirror.defineMode("null", function() {
5352
- return {token: function(stream) {stream.skipToEnd();}};
5353
- });
5354
- CodeMirror.defineMIME("text/plain", "null");
5355
-
5356
- // This can be used to attach properties to mode objects from
5357
- // outside the actual mode definition.
5358
- var modeExtensions = CodeMirror.modeExtensions = {};
5359
- CodeMirror.extendMode = function(mode, properties) {
5360
- var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
5361
- copyObj(properties, exts);
5362
- };
5363
-
5364
- // EXTENSIONS
5365
 
5366
- CodeMirror.defineExtension = function(name, func) {
5367
- CodeMirror.prototype[name] = func;
5368
- };
5369
- CodeMirror.defineDocExtension = function(name, func) {
5370
- Doc.prototype[name] = func;
5371
- };
5372
- CodeMirror.defineOption = option;
5373
 
5374
- var initHooks = [];
5375
- CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
 
 
5376
 
5377
- var helpers = CodeMirror.helpers = {};
5378
- CodeMirror.registerHelper = function(type, name, value) {
5379
- if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
5380
- helpers[type][name] = value;
5381
- };
5382
- CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
5383
- CodeMirror.registerHelper(type, name, value);
5384
- helpers[type]._global.push({pred: predicate, val: value});
5385
- };
 
5386
 
5387
- // MODE STATE HANDLING
5388
 
5389
- // Utility functions for working with state. Exported because nested
5390
- // modes need to do this for their inner modes.
 
 
 
 
 
5391
 
5392
- var copyState = CodeMirror.copyState = function(mode, state) {
5393
- if (state === true) return state;
5394
- if (mode.copyState) return mode.copyState(state);
5395
- var nstate = {};
5396
- for (var n in state) {
5397
- var val = state[n];
5398
- if (val instanceof Array) val = val.concat([]);
5399
- nstate[n] = val;
5400
  }
5401
- return nstate;
5402
- };
5403
-
5404
- var startState = CodeMirror.startState = function(mode, a1, a2) {
5405
- return mode.startState ? mode.startState(a1, a2) : true;
5406
- };
5407
-
5408
- // Given a mode and a state (for that mode), find the inner mode and
5409
- // state at the position that the state refers to.
5410
- CodeMirror.innerMode = function(mode, state) {
5411
- while (mode.innerMode) {
5412
- var info = mode.innerMode(state);
5413
- if (!info || info.mode == mode) break;
5414
- state = info.state;
5415
- mode = info.mode;
5416
  }
5417
- return info || {mode: mode, state: state};
5418
- };
5419
 
5420
- // STANDARD COMMANDS
 
 
5421
 
5422
- // Commands are parameter-less actions that can be performed on an
5423
- // editor, mostly used for keybindings.
5424
- var commands = CodeMirror.commands = {
5425
- selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},
5426
- singleSelection: function(cm) {
5427
- cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);
5428
- },
5429
- killLine: function(cm) {
5430
- deleteNearSelection(cm, function(range) {
5431
- if (range.empty()) {
5432
- var len = getLine(cm.doc, range.head.line).text.length;
5433
- if (range.head.ch == len && range.head.line < cm.lastLine())
5434
- return {from: range.head, to: Pos(range.head.line + 1, 0)};
5435
- else
5436
- return {from: range.head, to: Pos(range.head.line, len)};
5437
- } else {
5438
- return {from: range.from(), to: range.to()};
5439
- }
5440
- });
5441
- },
5442
- deleteLine: function(cm) {
5443
- deleteNearSelection(cm, function(range) {
5444
- return {from: Pos(range.from().line, 0),
5445
- to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};
5446
- });
5447
- },
5448
- delLineLeft: function(cm) {
5449
- deleteNearSelection(cm, function(range) {
5450
- return {from: Pos(range.from().line, 0), to: range.from()};
5451
- });
5452
- },
5453
- delWrappedLineLeft: function(cm) {
5454
- deleteNearSelection(cm, function(range) {
5455
- var top = cm.charCoords(range.head, "div").top + 5;
5456
- var leftPos = cm.coordsChar({left: 0, top: top}, "div");
5457
- return {from: leftPos, to: range.from()};
5458
- });
5459
- },
5460
- delWrappedLineRight: function(cm) {
5461
- deleteNearSelection(cm, function(range) {
5462
- var top = cm.charCoords(range.head, "div").top + 5;
5463
- var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
5464
- return {from: range.from(), to: rightPos };
5465
- });
5466
- },
5467
- undo: function(cm) {cm.undo();},
5468
- redo: function(cm) {cm.redo();},
5469
- undoSelection: function(cm) {cm.undoSelection();},
5470
- redoSelection: function(cm) {cm.redoSelection();},
5471
- goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
5472
- goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
5473
- goLineStart: function(cm) {
5474
- cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },
5475
- {origin: "+move", bias: 1});
5476
- },
5477
- goLineStartSmart: function(cm) {
5478
- cm.extendSelectionsBy(function(range) {
5479
- return lineStartSmart(cm, range.head);
5480
- }, {origin: "+move", bias: 1});
5481
- },
5482
- goLineEnd: function(cm) {
5483
- cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },
5484
- {origin: "+move", bias: -1});
5485
- },
5486
- goLineRight: function(cm) {
5487
- cm.extendSelectionsBy(function(range) {
5488
- var top = cm.charCoords(range.head, "div").top + 5;
5489
- return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
5490
- }, sel_move);
5491
- },
5492
- goLineLeft: function(cm) {
5493
- cm.extendSelectionsBy(function(range) {
5494
- var top = cm.charCoords(range.head, "div").top + 5;
5495
- return cm.coordsChar({left: 0, top: top}, "div");
5496
- }, sel_move);
5497
- },
5498
- goLineLeftSmart: function(cm) {
5499
- cm.extendSelectionsBy(function(range) {
5500
- var top = cm.charCoords(range.head, "div").top + 5;
5501
- var pos = cm.coordsChar({left: 0, top: top}, "div");
5502
- if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head);
5503
- return pos;
5504
- }, sel_move);
5505
- },
5506
- goLineUp: function(cm) {cm.moveV(-1, "line");},
5507
- goLineDown: function(cm) {cm.moveV(1, "line");},
5508
- goPageUp: function(cm) {cm.moveV(-1, "page");},
5509
- goPageDown: function(cm) {cm.moveV(1, "page");},
5510
- goCharLeft: function(cm) {cm.moveH(-1, "char");},
5511
- goCharRight: function(cm) {cm.moveH(1, "char");},
5512
- goColumnLeft: function(cm) {cm.moveH(-1, "column");},
5513
- goColumnRight: function(cm) {cm.moveH(1, "column");},
5514
- goWordLeft: function(cm) {cm.moveH(-1, "word");},
5515
- goGroupRight: function(cm) {cm.moveH(1, "group");},
5516
- goGroupLeft: function(cm) {cm.moveH(-1, "group");},
5517
- goWordRight: function(cm) {cm.moveH(1, "word");},
5518
- delCharBefore: function(cm) {cm.deleteH(-1, "char");},
5519
- delCharAfter: function(cm) {cm.deleteH(1, "char");},
5520
- delWordBefore: function(cm) {cm.deleteH(-1, "word");},
5521
- delWordAfter: function(cm) {cm.deleteH(1, "word");},
5522
- delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
5523
- delGroupAfter: function(cm) {cm.deleteH(1, "group");},
5524
- indentAuto: function(cm) {cm.indentSelection("smart");},
5525
- indentMore: function(cm) {cm.indentSelection("add");},
5526
- indentLess: function(cm) {cm.indentSelection("subtract");},
5527
- insertTab: function(cm) {cm.replaceSelection("\t");},
5528
- insertSoftTab: function(cm) {
5529
- var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
5530
- for (var i = 0; i < ranges.length; i++) {
5531
- var pos = ranges[i].from();
5532
- var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
5533
- spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
5534
  }
5535
- cm.replaceSelections(spaces);
5536
- },
5537
- defaultTab: function(cm) {
5538
- if (cm.somethingSelected()) cm.indentSelection("add");
5539
- else cm.execCommand("insertTab");
5540
- },
5541
- transposeChars: function(cm) {
5542
- runInOp(cm, function() {
5543
- var ranges = cm.listSelections(), newSel = [];
5544
- for (var i = 0; i < ranges.length; i++) {
5545
- var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
5546
- if (line) {
5547
- if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
5548
- if (cur.ch > 0) {
5549
- cur = new Pos(cur.line, cur.ch + 1);
5550
- cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
5551
- Pos(cur.line, cur.ch - 2), cur, "+transpose");
5552
- } else if (cur.line > cm.doc.first) {
5553
- var prev = getLine(cm.doc, cur.line - 1).text;
5554
- if (prev)
5555
- cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
5556
- Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
5557
- }
5558
- }
5559
- newSel.push(new Range(cur, cur));
5560
- }
5561
- cm.setSelections(newSel);
5562
- });
5563
- },
5564
- newlineAndIndent: function(cm) {
5565
- runInOp(cm, function() {
5566
- var len = cm.listSelections().length;
5567
- for (var i = 0; i < len; i++) {
5568
- var range = cm.listSelections()[i];
5569
- cm.replaceRange("\n", range.anchor, range.head, "+input");
5570
- cm.indentLine(range.from().line + 1, null, true);
5571
- ensureCursorVisible(cm);
5572
- }
5573
- });
5574
- },
5575
- toggleOverwrite: function(cm) {cm.toggleOverwrite();}
5576
- };
5577
 
 
 
5578
 
5579
- // STANDARD KEYMAPS
 
 
 
 
 
 
 
 
 
 
 
 
 
5580
 
5581
- var keyMap = CodeMirror.keyMap = {};
 
 
 
 
 
 
 
 
 
 
 
5582
 
5583
- keyMap.basic = {
5584
- "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
5585
- "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
5586
- "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
5587
- "Tab": "defaultTab", "Shift-Tab": "indentAuto",
5588
- "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
5589
- "Esc": "singleSelection"
5590
- };
5591
- // Note that the save and find-related commands aren't defined by
5592
- // default. User code or addons can define them. Unknown commands
5593
- // are simply ignored.
5594
- keyMap.pcDefault = {
5595
- "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
5596
- "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
5597
- "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
5598
- "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
5599
- "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
5600
- "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
5601
- "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
5602
- fallthrough: "basic"
5603
- };
5604
- // Very basic readline/emacs-style bindings, which are standard on Mac.
5605
- keyMap.emacsy = {
5606
- "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
5607
- "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
5608
- "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
5609
- "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
5610
- };
5611
- keyMap.macDefault = {
5612
- "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
5613
- "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
5614
- "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
5615
- "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
5616
- "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
5617
- "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
5618
- "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
5619
- fallthrough: ["basic", "emacsy"]
5620
- };
5621
- keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
5622
 
5623
- // KEYMAP DISPATCH
 
 
 
 
 
5624
 
5625
- function normalizeKeyName(name) {
5626
- var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
5627
- var alt, ctrl, shift, cmd;
5628
- for (var i = 0; i < parts.length - 1; i++) {
5629
- var mod = parts[i];
5630
- if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
5631
- else if (/^a(lt)?$/i.test(mod)) alt = true;
5632
- else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
5633
- else if (/^s(hift)$/i.test(mod)) shift = true;
5634
- else throw new Error("Unrecognized modifier name: " + mod);
5635
- }
5636
- if (alt) name = "Alt-" + name;
5637
- if (ctrl) name = "Ctrl-" + name;
5638
- if (cmd) name = "Cmd-" + name;
5639
- if (shift) name = "Shift-" + name;
5640
- return name;
5641
  }
5642
 
5643
- // This is a kludge to keep keymaps mostly working as raw objects
5644
- // (backwards compatibility) while at the same time support features
5645
- // like normalization and multi-stroke key bindings. It compiles a
5646
- // new normalized keymap, and then updates the old object to reflect
5647
- // this.
5648
- CodeMirror.normalizeKeyMap = function(keymap) {
5649
- var copy = {};
5650
- for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
5651
- var value = keymap[keyname];
5652
- if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
5653
- if (value == "...") { delete keymap[keyname]; continue; }
5654
 
5655
- var keys = map(keyname.split(" "), normalizeKeyName);
5656
- for (var i = 0; i < keys.length; i++) {
5657
- var val, name;
5658
- if (i == keys.length - 1) {
5659
- name = keyname;
5660
- val = value;
5661
- } else {
5662
- name = keys.slice(0, i + 1).join(" ");
5663
- val = "...";
5664
- }
5665
- var prev = copy[name];
5666
- if (!prev) copy[name] = val;
5667
- else if (prev != val) throw new Error("Inconsistent bindings for " + name);
5668
- }
5669
- delete keymap[keyname];
5670
  }
5671
- for (var prop in copy) keymap[prop] = copy[prop];
5672
- return keymap;
5673
- };
5674
 
5675
- var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {
5676
- map = getKeyMap(map);
5677
- var found = map.call ? map.call(key, context) : map[key];
5678
- if (found === false) return "nothing";
5679
- if (found === "...") return "multi";
5680
- if (found != null && handle(found)) return "handled";
 
 
 
 
 
 
 
5681
 
5682
- if (map.fallthrough) {
5683
- if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
5684
- return lookupKey(key, map.fallthrough, handle, context);
5685
- for (var i = 0; i < map.fallthrough.length; i++) {
5686
- var result = lookupKey(key, map.fallthrough[i], handle, context);
5687
- if (result) return result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5688
  }
5689
  }
5690
- };
 
 
 
 
5691
 
5692
- // Modifier key presses don't count as 'real' key presses for the
5693
- // purpose of keymap fallthrough.
5694
- var isModifierKey = CodeMirror.isModifierKey = function(value) {
5695
- var name = typeof value == "string" ? value : keyNames[value.keyCode];
5696
- return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
5697
- };
5698
 
5699
- // Look up the name of a key as indicated by an event object.
5700
- var keyName = CodeMirror.keyName = function(event, noShift) {
5701
- if (presto && event.keyCode == 34 && event["char"]) return false;
5702
- var base = keyNames[event.keyCode], name = base;
5703
- if (name == null || event.altGraphKey) return false;
5704
- if (event.altKey && base != "Alt") name = "Alt-" + name;
5705
- if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
5706
- if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
5707
- if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;
5708
- return name;
5709
- };
5710
 
5711
- function getKeyMap(val) {
5712
- return typeof val == "string" ? keyMap[val] : val;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5713
  }
5714
 
5715
- // FROMTEXTAREA
 
 
 
 
5716
 
5717
- CodeMirror.fromTextArea = function(textarea, options) {
5718
- options = options ? copyObj(options) : {};
5719
- options.value = textarea.value;
5720
- if (!options.tabindex && textarea.tabIndex)
5721
- options.tabindex = textarea.tabIndex;
5722
- if (!options.placeholder && textarea.placeholder)
5723
- options.placeholder = textarea.placeholder;
5724
- // Set autofocus to true if this textarea is focused, or if it has
5725
- // autofocus and no other element is focused.
5726
- if (options.autofocus == null) {
5727
- var hasFocus = activeElt();
5728
- options.autofocus = hasFocus == textarea ||
5729
- textarea.getAttribute("autofocus") != null && hasFocus == document.body;
5730
- }
5731
 
5732
- function save() {textarea.value = cm.getValue();}
5733
- if (textarea.form) {
5734
- on(textarea.form, "submit", save);
5735
- // Deplorable hack to make the submit method do the right thing.
5736
- if (!options.leaveSubmitMethodAlone) {
5737
- var form = textarea.form, realSubmit = form.submit;
5738
- try {
5739
- var wrappedSubmit = form.submit = function() {
5740
- save();
5741
- form.submit = realSubmit;
5742
- form.submit();
5743
- form.submit = wrappedSubmit;
5744
- };
5745
- } catch(e) {}
5746
- }
5747
  }
 
 
5748
 
5749
- options.finishInit = function(cm) {
5750
- cm.save = save;
5751
- cm.getTextArea = function() { return textarea; };
5752
- cm.toTextArea = function() {
5753
- cm.toTextArea = isNaN; // Prevent this from being ran twice
5754
- save();
5755
- textarea.parentNode.removeChild(cm.getWrapperElement());
5756
- textarea.style.display = "";
5757
- if (textarea.form) {
5758
- off(textarea.form, "submit", save);
5759
- if (typeof textarea.form.submit == "function")
5760
- textarea.form.submit = realSubmit;
5761
- }
5762
- };
5763
- };
5764
 
5765
- textarea.style.display = "none";
5766
- var cm = CodeMirror(function(node) {
5767
- textarea.parentNode.insertBefore(node, textarea.nextSibling);
5768
- }, options);
5769
- return cm;
5770
- };
 
 
 
5771
 
5772
- // STRING STREAM
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5773
 
5774
- // Fed to the mode parsers, provides helper functions to make
5775
- // parsers more succinct.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5776
 
5777
- var StringStream = CodeMirror.StringStream = function(string, tabSize) {
5778
- this.pos = this.start = 0;
5779
- this.string = string;
5780
- this.tabSize = tabSize || 8;
5781
- this.lastColumnPos = this.lastColumnValue = 0;
5782
- this.lineStart = 0;
5783
- };
5784
 
5785
- StringStream.prototype = {
5786
- eol: function() {return this.pos >= this.string.length;},
5787
- sol: function() {return this.pos == this.lineStart;},
5788
- peek: function() {return this.string.charAt(this.pos) || undefined;},
5789
- next: function() {
5790
- if (this.pos < this.string.length)
5791
- return this.string.charAt(this.pos++);
5792
- },
5793
- eat: function(match) {
5794
- var ch = this.string.charAt(this.pos);
5795
- if (typeof match == "string") var ok = ch == match;
5796
- else var ok = ch && (match.test ? match.test(ch) : match(ch));
5797
- if (ok) {++this.pos; return ch;}
5798
- },
5799
- eatWhile: function(match) {
5800
- var start = this.pos;
5801
- while (this.eat(match)){}
5802
- return this.pos > start;
5803
- },
5804
- eatSpace: function() {
5805
- var start = this.pos;
5806
- while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
5807
- return this.pos > start;
5808
- },
5809
- skipToEnd: function() {this.pos = this.string.length;},
5810
- skipTo: function(ch) {
5811
- var found = this.string.indexOf(ch, this.pos);
5812
- if (found > -1) {this.pos = found; return true;}
5813
- },
5814
- backUp: function(n) {this.pos -= n;},
5815
- column: function() {
5816
- if (this.lastColumnPos < this.start) {
5817
- this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
5818
- this.lastColumnPos = this.start;
5819
- }
5820
- return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
5821
- },
5822
- indentation: function() {
5823
- return countColumn(this.string, null, this.tabSize) -
5824
- (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
5825
- },
5826
- match: function(pattern, consume, caseInsensitive) {
5827
- if (typeof pattern == "string") {
5828
- var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
5829
- var substr = this.string.substr(this.pos, pattern.length);
5830
- if (cased(substr) == cased(pattern)) {
5831
- if (consume !== false) this.pos += pattern.length;
5832
- return true;
5833
  }
5834
- } else {
5835
- var match = this.string.slice(this.pos).match(pattern);
5836
- if (match && match.index > 0) return null;
5837
- if (match && consume !== false) this.pos += match[0].length;
5838
- return match;
5839
  }
5840
- },
5841
- current: function(){return this.string.slice(this.start, this.pos);},
5842
- hideFirstChars: function(n, inner) {
5843
- this.lineStart += n;
5844
- try { return inner(); }
5845
- finally { this.lineStart -= n; }
5846
  }
5847
- };
5848
 
5849
- // TEXTMARKERS
 
 
 
 
5850
 
5851
- // Created with markText and setBookmark methods. A TextMarker is a
5852
- // handle that can be used to clear or find a marked position in the
5853
- // document. Line objects hold arrays (markedSpans) containing
5854
- // {from, to, marker} object pointing to such marker objects, and
5855
- // indicating that such a marker is present on that line. Multiple
5856
- // lines may point to the same marker when it spans across lines.
5857
- // The spans will have null for their from/to properties when the
5858
- // marker continues beyond the start/end of the line. Markers have
5859
- // links back to the lines they currently touch.
5860
-
5861
- var nextMarkerId = 0;
5862
 
5863
- var TextMarker = CodeMirror.TextMarker = function(doc, type) {
5864
- this.lines = [];
5865
- this.type = type;
5866
- this.doc = doc;
5867
- this.id = ++nextMarkerId;
5868
- };
5869
- eventMixin(TextMarker);
5870
 
5871
- // Clear the marker.
5872
- TextMarker.prototype.clear = function() {
5873
- if (this.explicitlyCleared) return;
5874
- var cm = this.doc.cm, withOp = cm && !cm.curOp;
5875
- if (withOp) startOperation(cm);
5876
- if (hasHandler(this, "clear")) {
5877
- var found = this.find();
5878
- if (found) signalLater(this, "clear", found.from, found.to);
5879
- }
5880
- var min = null, max = null;
5881
- for (var i = 0; i < this.lines.length; ++i) {
5882
- var line = this.lines[i];
5883
- var span = getMarkedSpanFor(line.markedSpans, this);
5884
- if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");
5885
- else if (cm) {
5886
- if (span.to != null) max = lineNo(line);
5887
- if (span.from != null) min = lineNo(line);
5888
- }
5889
- line.markedSpans = removeMarkedSpan(line.markedSpans, span);
5890
- if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
5891
- updateLineHeight(line, textHeight(cm.display));
5892
- }
5893
- if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
5894
- var visual = visualLine(this.lines[i]), len = lineLength(visual);
5895
- if (len > cm.display.maxLineLength) {
5896
- cm.display.maxLine = visual;
5897
- cm.display.maxLineLength = len;
5898
- cm.display.maxLineChanged = true;
5899
- }
5900
- }
5901
 
5902
- if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);
5903
- this.lines.length = 0;
5904
- this.explicitlyCleared = true;
5905
- if (this.atomic && this.doc.cantEdit) {
5906
- this.doc.cantEdit = false;
5907
- if (cm) reCheckSelection(cm.doc);
5908
- }
5909
- if (cm) signalLater(cm, "markerCleared", cm, this);
5910
- if (withOp) endOperation(cm);
5911
- if (this.parent) this.parent.clear();
5912
- };
 
 
 
 
 
 
 
5913
 
5914
- // Find the position of the marker in the document. Returns a {from,
5915
- // to} object by default. Side can be passed to get a specific side
5916
- // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
5917
- // Pos objects returned contain a line object, rather than a line
5918
- // number (used to prevent looking up the same line twice).
5919
- TextMarker.prototype.find = function(side, lineObj) {
5920
- if (side == null && this.type == "bookmark") side = 1;
5921
- var from, to;
5922
- for (var i = 0; i < this.lines.length; ++i) {
5923
- var line = this.lines[i];
5924
- var span = getMarkedSpanFor(line.markedSpans, this);
5925
- if (span.from != null) {
5926
- from = Pos(lineObj ? line : lineNo(line), span.from);
5927
- if (side == -1) return from;
5928
- }
5929
- if (span.to != null) {
5930
- to = Pos(lineObj ? line : lineNo(line), span.to);
5931
- if (side == 1) return to;
5932
- }
5933
  }
5934
- return from && {from: from, to: to};
5935
- };
5936
 
5937
- // Signals that the marker's widget changed, and surrounding layout
5938
- // should be recomputed.
5939
- TextMarker.prototype.changed = function() {
5940
- var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
5941
- if (!pos || !cm) return;
5942
- runInOp(cm, function() {
5943
- var line = pos.line, lineN = lineNo(pos.line);
5944
- var view = findViewForLine(cm, lineN);
5945
- if (view) {
5946
- clearLineMeasurementCacheFor(view);
5947
- cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
5948
- }
5949
- cm.curOp.updateMaxLine = true;
5950
- if (!lineIsHidden(widget.doc, line) && widget.height != null) {
5951
- var oldHeight = widget.height;
5952
- widget.height = null;
5953
- var dHeight = widgetHeight(widget) - oldHeight;
5954
- if (dHeight)
5955
- updateLineHeight(line, line.height + dHeight);
5956
- }
5957
- });
5958
- };
5959
 
5960
- TextMarker.prototype.attachLine = function(line) {
5961
- if (!this.lines.length && this.doc.cm) {
5962
- var op = this.doc.cm.curOp;
5963
- if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
5964
- (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
5965
- }
5966
- this.lines.push(line);
5967
- };
5968
- TextMarker.prototype.detachLine = function(line) {
5969
- this.lines.splice(indexOf(this.lines, line), 1);
5970
- if (!this.lines.length && this.doc.cm) {
5971
- var op = this.doc.cm.curOp;
5972
- (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
5973
- }
5974
- };
5975
 
5976
- // Collapsed markers have unique ids, in order to be able to order
5977
- // them, which is needed for uniquely determining an outer marker
5978
- // when they overlap (they may nest, but not partially overlap).
5979
- var nextMarkerId = 0;
5980
 
5981
- // Create a marker, wire it up to the right lines, and
5982
- function markText(doc, from, to, options, type) {
5983
- // Shared markers (across linked documents) are handled separately
5984
- // (markTextShared will call out to this again, once per
5985
- // document).
5986
- if (options && options.shared) return markTextShared(doc, from, to, options, type);
5987
- // Ensure we are in an operation.
5988
- if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
5989
 
5990
- var marker = new TextMarker(doc, type), diff = cmp(from, to);
5991
- if (options) copyObj(options, marker, false);
5992
- // Don't connect empty markers unless clearWhenEmpty is false
5993
- if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
5994
- return marker;
5995
- if (marker.replacedWith) {
5996
- // Showing up as a widget implies collapsed (widget replaces text)
5997
- marker.collapsed = true;
5998
- marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");
5999
- if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");
6000
- if (options.insertLeft) marker.widgetNode.insertLeft = true;
6001
- }
6002
- if (marker.collapsed) {
6003
- if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
6004
- from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
6005
- throw new Error("Inserting collapsed marker partially overlapping an existing one");
6006
- sawCollapsedSpans = true;
6007
- }
6008
 
6009
- if (marker.addToHistory)
6010
- addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);
6011
 
6012
- var curLine = from.line, cm = doc.cm, updateMaxLine;
6013
- doc.iter(curLine, to.line + 1, function(line) {
6014
- if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
6015
- updateMaxLine = true;
6016
- if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
6017
- addMarkedSpan(line, new MarkedSpan(marker,
6018
- curLine == from.line ? from.ch : null,
6019
- curLine == to.line ? to.ch : null));
6020
- ++curLine;
6021
- });
6022
- // lineIsHidden depends on the presence of the spans, so needs a second pass
6023
- if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
6024
- if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
6025
- });
6026
 
6027
- if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
 
 
 
 
6028
 
6029
- if (marker.readOnly) {
6030
- sawReadOnlySpans = true;
6031
- if (doc.history.done.length || doc.history.undone.length)
6032
- doc.clearHistory();
6033
- }
6034
- if (marker.collapsed) {
6035
- marker.id = ++nextMarkerId;
6036
- marker.atomic = true;
6037
- }
6038
- if (cm) {
6039
- // Sync editor state
6040
- if (updateMaxLine) cm.curOp.updateMaxLine = true;
6041
- if (marker.collapsed)
6042
- regChange(cm, from.line, to.line + 1);
6043
- else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
6044
- for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
6045
- if (marker.atomic) reCheckSelection(cm.doc);
6046
- signalLater(cm, "markerAdded", cm, marker);
6047
  }
6048
- return marker;
6049
  }
6050
 
6051
- // SHARED TEXTMARKERS
6052
-
6053
- // A shared marker spans multiple linked documents. It is
6054
- // implemented as a meta-marker-object controlling multiple normal
6055
- // markers.
6056
- var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
6057
- this.markers = markers;
6058
- this.primary = primary;
6059
- for (var i = 0; i < markers.length; ++i)
6060
- markers[i].parent = this;
6061
- };
6062
- eventMixin(SharedTextMarker);
6063
 
6064
- SharedTextMarker.prototype.clear = function() {
6065
- if (this.explicitlyCleared) return;
6066
- this.explicitlyCleared = true;
6067
- for (var i = 0; i < this.markers.length; ++i)
6068
- this.markers[i].clear();
6069
- signalLater(this, "clear");
6070
- };
6071
- SharedTextMarker.prototype.find = function(side, lineObj) {
6072
- return this.primary.find(side, lineObj);
6073
- };
6074
 
6075
- function markTextShared(doc, from, to, options, type) {
6076
- options = copyObj(options);
6077
- options.shared = false;
6078
- var markers = [markText(doc, from, to, options, type)], primary = markers[0];
6079
- var widget = options.widgetNode;
6080
- linkedDocs(doc, function(doc) {
6081
- if (widget) options.widgetNode = widget.cloneNode(true);
6082
- markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
6083
- for (var i = 0; i < doc.linked.length; ++i)
6084
- if (doc.linked[i].isParent) return;
6085
- primary = lst(markers);
6086
- });
6087
- return new SharedTextMarker(markers, primary);
6088
- }
 
 
 
 
6089
 
6090
- function findSharedMarkers(doc) {
6091
- return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),
6092
- function(m) { return m.parent; });
 
 
 
 
6093
  }
6094
 
6095
- function copySharedMarkers(doc, markers) {
6096
- for (var i = 0; i < markers.length; i++) {
6097
- var marker = markers[i], pos = marker.find();
6098
- var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
6099
- if (cmp(mFrom, mTo)) {
6100
- var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
6101
- marker.markers.push(subMark);
6102
- subMark.parent = marker;
6103
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6104
  }
6105
  }
6106
 
6107
- function detachSharedMarkers(markers) {
6108
- for (var i = 0; i < markers.length; i++) {
6109
- var marker = markers[i], linked = [marker.primary.doc];;
6110
- linkedDocs(marker.primary.doc, function(d) { linked.push(d); });
6111
- for (var j = 0; j < marker.markers.length; j++) {
6112
- var subMarker = marker.markers[j];
6113
- if (indexOf(linked, subMarker.doc) == -1) {
6114
- subMarker.parent = null;
6115
- marker.markers.splice(j--, 1);
6116
- }
6117
- }
6118
- }
6119
  }
6120
 
6121
- // TEXTMARKER SPANS
6122
 
6123
- function MarkedSpan(marker, from, to) {
6124
- this.marker = marker;
6125
- this.from = from; this.to = to;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6126
  }
6127
 
6128
- // Search an array of spans for a span matching the given marker.
6129
- function getMarkedSpanFor(spans, marker) {
6130
- if (spans) for (var i = 0; i < spans.length; ++i) {
6131
- var span = spans[i];
6132
- if (span.marker == marker) return span;
 
6133
  }
6134
- }
6135
- // Remove a span from an array, returning undefined if no spans are
6136
- // left (we don't store arrays for lines without spans).
6137
- function removeMarkedSpan(spans, span) {
6138
- for (var r, i = 0; i < spans.length; ++i)
6139
- if (spans[i] != span) (r || (r = [])).push(spans[i]);
6140
- return r;
6141
- }
6142
- // Add a span to a line.
6143
- function addMarkedSpan(line, span) {
6144
- line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
6145
- span.marker.attachLine(line);
6146
- }
6147
 
6148
- // Used for the algorithm that adjusts markers for a change in the
6149
- // document. These functions cut an array of spans at a given
6150
- // character position, returning an array of remaining chunks (or
6151
- // undefined if nothing remains).
6152
- function markedSpansBefore(old, startCh, isInsert) {
6153
- if (old) for (var i = 0, nw; i < old.length; ++i) {
6154
- var span = old[i], marker = span.marker;
6155
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
6156
- if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
6157
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
6158
- (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
6159
- }
6160
  }
6161
- return nw;
6162
- }
6163
- function markedSpansAfter(old, endCh, isInsert) {
6164
- if (old) for (var i = 0, nw; i < old.length; ++i) {
6165
- var span = old[i], marker = span.marker;
6166
- var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
6167
- if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
6168
- var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
6169
- (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
6170
- span.to == null ? null : span.to - endCh));
6171
- }
6172
  }
6173
- return nw;
6174
  }
6175
 
6176
- // Given a change object, compute the new set of marker spans that
6177
- // cover the line in which the change took place. Removes spans
6178
- // entirely within the change, reconnects spans belonging to the
6179
- // same marker that appear on both sides of the change, and cuts off
6180
- // spans partially within the change. Returns an array of span
6181
- // arrays with one element for each line in (after) the change.
6182
- function stretchSpansOverChange(doc, change) {
6183
- if (change.full) return null;
6184
- var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
6185
- var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
6186
- if (!oldFirst && !oldLast) return null;
6187
 
6188
- var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
6189
- // Get the spans that 'stick out' on both sides
6190
- var first = markedSpansBefore(oldFirst, startCh, isInsert);
6191
- var last = markedSpansAfter(oldLast, endCh, isInsert);
6192
 
6193
- // Next, merge those two ends
6194
- var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
6195
- if (first) {
6196
- // Fix up .to properties of first
6197
- for (var i = 0; i < first.length; ++i) {
6198
- var span = first[i];
6199
- if (span.to == null) {
6200
- var found = getMarkedSpanFor(last, span.marker);
6201
- if (!found) span.to = startCh;
6202
- else if (sameLine) span.to = found.to == null ? null : found.to + offset;
6203
- }
6204
- }
6205
- }
6206
- if (last) {
6207
- // Fix up .from in last (or move them into first in case of sameLine)
6208
- for (var i = 0; i < last.length; ++i) {
6209
- var span = last[i];
6210
- if (span.to != null) span.to += offset;
6211
- if (span.from == null) {
6212
- var found = getMarkedSpanFor(first, span.marker);
6213
- if (!found) {
6214
- span.from = offset;
6215
- if (sameLine) (first || (first = [])).push(span);
6216
- }
6217
- } else {
6218
- span.from += offset;
6219
- if (sameLine) (first || (first = [])).push(span);
6220
- }
6221
  }
6222
- }
6223
- // Make sure we didn't create any zero-length spans
6224
- if (first) first = clearEmptySpans(first);
6225
- if (last && last != first) last = clearEmptySpans(last);
6226
-
6227
- var newMarkers = [first];
6228
- if (!sameLine) {
6229
- // Fill gap with whole-line-spans
6230
- var gap = change.text.length - 2, gapMarkers;
6231
- if (gap > 0 && first)
6232
- for (var i = 0; i < first.length; ++i)
6233
- if (first[i].to == null)
6234
- (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));
6235
- for (var i = 0; i < gap; ++i)
6236
- newMarkers.push(gapMarkers);
6237
- newMarkers.push(last);
6238
- }
6239
- return newMarkers;
6240
  }
6241
 
6242
- // Remove spans that are empty and don't have a clearWhenEmpty
6243
- // option of false.
6244
- function clearEmptySpans(spans) {
6245
- for (var i = 0; i < spans.length; ++i) {
6246
- var span = spans[i];
6247
- if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
6248
- spans.splice(i--, 1);
6249
- }
6250
- if (!spans.length) return null;
6251
- return spans;
6252
- }
6253
 
6254
- // Used for un/re-doing changes from the history. Combines the
6255
- // result of computing the existing spans with the set of spans that
6256
- // existed in the history (so that deleting around a span and then
6257
- // undoing brings back the span).
6258
- function mergeOldSpans(doc, change) {
6259
- var old = getOldSpans(doc, change);
6260
- var stretched = stretchSpansOverChange(doc, change);
6261
- if (!old) return stretched;
6262
- if (!stretched) return old;
6263
 
6264
- for (var i = 0; i < old.length; ++i) {
6265
- var oldCur = old[i], stretchCur = stretched[i];
6266
- if (oldCur && stretchCur) {
6267
- spans: for (var j = 0; j < stretchCur.length; ++j) {
6268
- var span = stretchCur[j];
6269
- for (var k = 0; k < oldCur.length; ++k)
6270
- if (oldCur[k].marker == span.marker) continue spans;
6271
- oldCur.push(span);
 
 
 
 
 
 
 
 
 
 
6272
  }
6273
- } else if (stretchCur) {
6274
- old[i] = stretchCur;
6275
- }
 
 
6276
  }
6277
- return old;
6278
- }
6279
 
6280
- // Used to 'clip' out readOnly ranges when making a change.
6281
- function removeReadOnlyRanges(doc, from, to) {
6282
- var markers = null;
6283
- doc.iter(from.line, to.line + 1, function(line) {
6284
- if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
6285
- var mark = line.markedSpans[i].marker;
6286
- if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
6287
- (markers || (markers = [])).push(mark);
6288
- }
6289
- });
6290
- if (!markers) return null;
6291
- var parts = [{from: from, to: to}];
6292
- for (var i = 0; i < markers.length; ++i) {
6293
- var mk = markers[i], m = mk.find(0);
6294
- for (var j = 0; j < parts.length; ++j) {
6295
- var p = parts[j];
6296
- if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;
6297
- var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
6298
- if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
6299
- newParts.push({from: p.from, to: m.from});
6300
- if (dto > 0 || !mk.inclusiveRight && !dto)
6301
- newParts.push({from: m.to, to: p.to});
6302
- parts.splice.apply(parts, newParts);
6303
- j += newParts.length - 1;
6304
  }
6305
- }
6306
- return parts;
6307
- }
6308
 
6309
- // Connect or disconnect spans from a line.
6310
- function detachMarkedSpans(line) {
6311
- var spans = line.markedSpans;
6312
- if (!spans) return;
6313
- for (var i = 0; i < spans.length; ++i)
6314
- spans[i].marker.detachLine(line);
6315
- line.markedSpans = null;
6316
- }
6317
- function attachMarkedSpans(line, spans) {
6318
- if (!spans) return;
6319
- for (var i = 0; i < spans.length; ++i)
6320
- spans[i].marker.attachLine(line);
6321
- line.markedSpans = spans;
6322
- }
6323
 
6324
- // Helpers used when computing which overlapping collapsed span
6325
- // counts as the larger one.
6326
- function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
6327
- function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
6328
 
6329
- // Returns a number indicating which of two overlapping collapsed
6330
- // spans is larger (and thus includes the other). Falls back to
6331
- // comparing ids when the spans cover exactly the same range.
6332
- function compareCollapsedMarkers(a, b) {
6333
- var lenDiff = a.lines.length - b.lines.length;
6334
- if (lenDiff != 0) return lenDiff;
6335
- var aPos = a.find(), bPos = b.find();
6336
- var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
6337
- if (fromCmp) return -fromCmp;
6338
- var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
6339
- if (toCmp) return toCmp;
6340
- return b.id - a.id;
6341
- }
6342
 
6343
- // Find out whether a line ends or starts in a collapsed span. If
6344
- // so, return the marker for that span.
6345
- function collapsedSpanAtSide(line, start) {
6346
- var sps = sawCollapsedSpans && line.markedSpans, found;
6347
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
6348
- sp = sps[i];
6349
- if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
6350
- (!found || compareCollapsedMarkers(found, sp.marker) < 0))
6351
- found = sp.marker;
6352
  }
6353
- return found;
6354
  }
6355
- function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
6356
- function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
6357
 
6358
- // Test whether there exists a collapsed span that partially
6359
- // overlaps (covers the start or end, but not both) of a new span.
6360
- // Such overlap is not allowed.
6361
- function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
6362
- var line = getLine(doc, lineNo);
6363
- var sps = sawCollapsedSpans && line.markedSpans;
6364
- if (sps) for (var i = 0; i < sps.length; ++i) {
6365
- var sp = sps[i];
6366
- if (!sp.marker.collapsed) continue;
6367
- var found = sp.marker.find(0);
6368
- var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
6369
- var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
6370
- if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
6371
- if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||
6372
- fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))
6373
- return true;
6374
  }
6375
  }
6376
 
6377
- // A visual line is a line as drawn on the screen. Folding, for
6378
- // example, can cause multiple logical lines to appear on the same
6379
- // visual line. This finds the start of the visual line that the
6380
- // given line is part of (usually that is the line itself).
6381
- function visualLine(line) {
6382
- var merged;
6383
- while (merged = collapsedSpanAtStart(line))
6384
- line = merged.find(-1, true).line;
6385
- return line;
6386
- }
6387
 
6388
- // Returns an array of logical lines that continue the visual line
6389
- // started by the argument, or undefined if there are no such lines.
6390
- function visualLineContinued(line) {
6391
- var merged, lines;
6392
- while (merged = collapsedSpanAtEnd(line)) {
6393
- line = merged.find(1, true).line;
6394
- (lines || (lines = [])).push(line);
6395
  }
6396
- return lines;
6397
- }
6398
 
6399
- // Get the line number of the start of the visual line that the
6400
- // given line number is part of.
6401
- function visualLineNo(doc, lineN) {
6402
- var line = getLine(doc, lineN), vis = visualLine(line);
6403
- if (line == vis) return lineN;
6404
- return lineNo(vis);
6405
- }
6406
- // Get the line number of the start of the next visual line after
6407
- // the given line.
6408
- function visualLineEndNo(doc, lineN) {
6409
- if (lineN > doc.lastLine()) return lineN;
6410
- var line = getLine(doc, lineN), merged;
6411
- if (!lineIsHidden(doc, line)) return lineN;
6412
- while (merged = collapsedSpanAtEnd(line))
6413
- line = merged.find(1, true).line;
6414
- return lineNo(line) + 1;
6415
- }
6416
-
6417
- // Compute whether a line is hidden. Lines count as hidden when they
6418
- // are part of a visual line that starts with another line, or when
6419
- // they are entirely covered by collapsed, non-widget span.
6420
- function lineIsHidden(doc, line) {
6421
- var sps = sawCollapsedSpans && line.markedSpans;
6422
- if (sps) for (var sp, i = 0; i < sps.length; ++i) {
6423
- sp = sps[i];
6424
- if (!sp.marker.collapsed) continue;
6425
- if (sp.from == null) return true;
6426
- if (sp.marker.widgetNode) continue;
6427
- if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
6428
- return true;
6429
- }
6430
- }
6431
- function lineIsHiddenInner(doc, line, span) {
6432
- if (span.to == null) {
6433
- var end = span.marker.find(1, true);
6434
- return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));
6435
  }
6436
- if (span.marker.inclusiveRight && span.to == line.text.length)
6437
- return true;
6438
- for (var sp, i = 0; i < line.markedSpans.length; ++i) {
6439
- sp = line.markedSpans[i];
6440
- if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
6441
- (sp.to == null || sp.to != span.from) &&
6442
- (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
6443
- lineIsHiddenInner(doc, line, sp)) return true;
6444
  }
6445
- }
6446
-
6447
- // LINE WIDGETS
6448
 
6449
- // Line widgets are block elements displayed above or below a line.
6450
 
6451
- var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
6452
- if (options) for (var opt in options) if (options.hasOwnProperty(opt))
6453
- this[opt] = options[opt];
6454
- this.cm = cm;
6455
- this.node = node;
6456
- };
6457
- eventMixin(LineWidget);
6458
 
6459
- function adjustScrollWhenAboveVisible(cm, line, diff) {
6460
- if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
6461
- addToScrollPos(cm, null, diff);
6462
  }
6463
 
6464
- LineWidget.prototype.clear = function() {
6465
- var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
6466
- if (no == null || !ws) return;
6467
- for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
6468
- if (!ws.length) line.widgets = null;
6469
- var height = widgetHeight(this);
6470
- runInOp(cm, function() {
6471
- adjustScrollWhenAboveVisible(cm, line, -height);
6472
- regLineChange(cm, no, "widget");
6473
- updateLineHeight(line, Math.max(0, line.height - height));
6474
- });
6475
- };
6476
- LineWidget.prototype.changed = function() {
6477
- var oldH = this.height, cm = this.cm, line = this.line;
6478
- this.height = null;
6479
- var diff = widgetHeight(this) - oldH;
6480
- if (!diff) return;
6481
- runInOp(cm, function() {
6482
- cm.curOp.forceUpdate = true;
6483
- adjustScrollWhenAboveVisible(cm, line, diff);
6484
- updateLineHeight(line, line.height + diff);
6485
- });
6486
- };
6487
 
6488
- function widgetHeight(widget) {
6489
- if (widget.height != null) return widget.height;
6490
- if (!contains(document.body, widget.node)) {
6491
- var parentStyle = "position: relative;";
6492
- if (widget.coverGutter)
6493
- parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;";
6494
- if (widget.noHScroll)
6495
- parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;";
6496
- removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));
6497
  }
6498
- return widget.height = widget.node.offsetHeight;
6499
- }
6500
 
6501
- function addLineWidget(cm, handle, node, options) {
6502
- var widget = new LineWidget(cm, node, options);
6503
- if (widget.noHScroll) cm.display.alignWidgets = true;
6504
- changeLine(cm.doc, handle, "widget", function(line) {
6505
- var widgets = line.widgets || (line.widgets = []);
6506
- if (widget.insertAt == null) widgets.push(widget);
6507
- else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
6508
- widget.line = line;
6509
- if (!lineIsHidden(cm.doc, line)) {
6510
- var aboveVisible = heightAtLine(line) < cm.doc.scrollTop;
6511
- updateLineHeight(line, line.height + widgetHeight(widget));
6512
- if (aboveVisible) addToScrollPos(cm, null, widget.height);
6513
- cm.curOp.forceUpdate = true;
6514
- }
6515
- return true;
6516
- });
6517
- return widget;
6518
- }
6519
 
6520
- // LINE DATA STRUCTURE
6521
 
6522
- // Line objects. These hold state related to a line, including
6523
- // highlighting info (the styles array).
6524
- var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
6525
- this.text = text;
6526
- attachMarkedSpans(this, markedSpans);
6527
- this.height = estimateHeight ? estimateHeight(this) : 1;
6528
- };
6529
- eventMixin(Line);
6530
- Line.prototype.lineNo = function() { return lineNo(this); };
 
 
 
6531
 
6532
- // Change the content (text, markers) of a line. Automatically
6533
- // invalidates cached information and tries to re-estimate the
6534
- // line's height.
6535
- function updateLine(line, text, markedSpans, estimateHeight) {
6536
- line.text = text;
6537
- if (line.stateAfter) line.stateAfter = null;
6538
- if (line.styles) line.styles = null;
6539
- if (line.order != null) line.order = null;
6540
- detachMarkedSpans(line);
6541
- attachMarkedSpans(line, markedSpans);
6542
- var estHeight = estimateHeight ? estimateHeight(line) : 1;
6543
- if (estHeight != line.height) updateLineHeight(line, estHeight);
6544
- }
6545
 
6546
- // Detach a line from the document tree and its markers.
6547
- function cleanUpLine(line) {
6548
- line.parent = null;
6549
- detachMarkedSpans(line);
6550
- }
 
 
 
6551
 
6552
- function extractLineClasses(type, output) {
6553
- if (type) for (;;) {
6554
- var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
6555
- if (!lineClass) break;
6556
- type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
6557
- var prop = lineClass[1] ? "bgClass" : "textClass";
6558
- if (output[prop] == null)
6559
- output[prop] = lineClass[2];
6560
- else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
6561
- output[prop] += " " + lineClass[2];
6562
  }
6563
- return type;
6564
  }
6565
 
6566
- function callBlankLine(mode, state) {
6567
- if (mode.blankLine) return mode.blankLine(state);
6568
- if (!mode.innerMode) return;
6569
- var inner = CodeMirror.innerMode(mode, state);
6570
- if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
6571
- }
6572
 
6573
- function readToken(mode, stream, state, inner) {
6574
- for (var i = 0; i < 10; i++) {
6575
- if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;
6576
- var style = mode.token(stream, state);
6577
- if (stream.pos > stream.start) return style;
6578
- }
6579
- throw new Error("Mode " + mode.name + " failed to advance stream.");
6580
  }
6581
 
6582
- // Utility for getTokenAt and getLineTokens
6583
- function takeToken(cm, pos, precise, asArray) {
6584
- function getObj(copy) {
6585
- return {start: stream.start, end: stream.pos,
6586
- string: stream.current(),
6587
- type: style || null,
6588
- state: copy ? copyState(doc.mode, state) : state};
6589
- }
6590
 
6591
- var doc = cm.doc, mode = doc.mode, style;
6592
- pos = clipPos(doc, pos);
6593
- var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
6594
- var stream = new StringStream(line.text, cm.options.tabSize), tokens;
6595
- if (asArray) tokens = [];
6596
- while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
6597
- stream.start = stream.pos;
6598
- style = readToken(mode, stream, state);
6599
- if (asArray) tokens.push(getObj(true));
6600
  }
6601
- return asArray ? tokens : getObj();
6602
  }
6603
 
6604
- // Run the given mode's parser over a line, calling f for each token.
6605
- function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
6606
- var flattenSpans = mode.flattenSpans;
6607
- if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
6608
- var curStart = 0, curStyle = null;
6609
- var stream = new StringStream(text, cm.options.tabSize), style;
6610
- var inner = cm.options.addModeClass && [null];
6611
- if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
6612
- while (!stream.eol()) {
6613
- if (stream.pos > cm.options.maxHighlightLength) {
6614
- flattenSpans = false;
6615
- if (forceToEnd) processLine(cm, text, state, stream.pos);
6616
- stream.pos = text.length;
6617
- style = null;
6618
- } else {
6619
- style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);
6620
- }
6621
- if (inner) {
6622
- var mName = inner[0].name;
6623
- if (mName) style = "m-" + (style ? mName + " " + style : mName);
6624
  }
6625
- if (!flattenSpans || curStyle != style) {
6626
- while (curStart < stream.start) {
6627
- curStart = Math.min(stream.start, curStart + 50000);
6628
- f(curStart, curStyle);
 
 
 
 
6629
  }
6630
- curStyle = style;
6631
  }
6632
- stream.start = stream.pos;
6633
- }
6634
- while (curStart < stream.pos) {
6635
- // Webkit seems to refuse to render text nodes longer than 57444 characters
6636
- var pos = Math.min(stream.pos, curStart + 50000);
6637
- f(pos, curStyle);
6638
- curStart = pos;
6639
  }
6640
  }
6641
 
6642
- // Compute a style array (an array starting with a mode generation
6643
- // -- for invalidation -- followed by pairs of end positions and
6644
- // style strings), which is used to highlight the tokens on the
6645
- // line.
6646
- function highlightLine(cm, line, state, forceToEnd) {
6647
- // A styles array always starts with a number identifying the
6648
- // mode/overlays that it is based on (for easy invalidation).
6649
- var st = [cm.state.modeGen], lineClasses = {};
6650
- // Compute the base array of styles
6651
- runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
6652
- st.push(end, style);
6653
- }, lineClasses, forceToEnd);
6654
 
6655
- // Run overlays, adjust style array.
6656
- for (var o = 0; o < cm.state.overlays.length; ++o) {
6657
- var overlay = cm.state.overlays[o], i = 1, at = 0;
6658
- runMode(cm, line.text, overlay.mode, true, function(end, style) {
6659
- var start = i;
6660
- // Ensure there's a token end at the current position, and that i points at it
6661
- while (at < end) {
6662
- var i_end = st[i];
6663
- if (i_end > end)
6664
- st.splice(i, 1, end, st[i+1], i_end);
6665
- i += 2;
6666
- at = Math.min(end, i_end);
6667
- }
6668
- if (!style) return;
6669
- if (overlay.opaque) {
6670
- st.splice(start, i - start, end, "cm-overlay " + style);
6671
- i = start + 2;
6672
- } else {
6673
- for (; start < i; start += 2) {
6674
- var cur = st[start+1];
6675
- st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;
6676
- }
6677
- }
6678
- }, lineClasses);
 
 
 
 
 
 
 
 
6679
  }
 
 
6680
 
6681
- return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6682
  }
6683
 
6684
- function getLineStyles(cm, line, updateFrontier) {
6685
- if (!line.styles || line.styles[0] != cm.state.modeGen) {
6686
- var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
6687
- line.styles = result.styles;
6688
- if (result.classes) line.styleClasses = result.classes;
6689
- else if (line.styleClasses) line.styleClasses = null;
6690
- if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;
6691
  }
6692
- return line.styles;
6693
  }
6694
 
6695
- // Lightweight form of highlight -- proceed over this line and
6696
- // update state, but don't save a style array. Used for lines that
6697
- // aren't currently visible.
6698
- function processLine(cm, text, state, startAt) {
6699
- var mode = cm.doc.mode;
6700
- var stream = new StringStream(text, cm.options.tabSize);
6701
- stream.start = stream.pos = startAt || 0;
6702
- if (text == "") callBlankLine(mode, state);
6703
- while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
6704
- readToken(mode, stream, state);
6705
- stream.start = stream.pos;
6706
  }
 
 
 
6707
  }
6708
 
6709
- // Convert a style as returned by a mode (either null, or a string
6710
- // containing one or more styles) to a CSS style. This is cached,
6711
- // and also looks for line-wide styles.
6712
- var styleToClassCache = {}, styleToClassCacheWithMode = {};
6713
- function interpretTokenStyle(style, options) {
6714
- if (!style || /^\s*$/.test(style)) return null;
6715
- var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
6716
- return cache[style] ||
6717
- (cache[style] = style.replace(/\S+/g, "cm-$&"));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6718
  }
6719
 
6720
- // Render the DOM representation of the text of a line. Also builds
6721
- // up a 'line map', which points at the DOM nodes that represent
6722
- // specific stretches of text, and is used by the measuring code.
6723
- // The returned object contains the DOM node, this map, and
6724
- // information about line-wide styles that were set by the mode.
6725
- function buildLineContent(cm, lineView) {
6726
- // The padding-right forces the element to have a 'border', which
6727
- // is needed on Webkit to be able to get line-level bounding
6728
- // rectangles for it (in measureChar).
6729
- var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
6730
- var builder = {pre: elt("pre", [content]), content: content,
6731
- col: 0, pos: 0, cm: cm,
6732
- splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
6733
- lineView.measure = {};
6734
-
6735
- // Iterate over the logical lines that make up this visual line.
6736
- for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
6737
- var line = i ? lineView.rest[i - 1] : lineView.line, order;
6738
- builder.pos = 0;
6739
- builder.addToken = buildToken;
6740
- // Optionally wire in some hacks into the token-rendering
6741
- // algorithm, to deal with browser quirks.
6742
- if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
6743
- builder.addToken = buildTokenBadBidi(builder.addToken, order);
6744
- builder.map = [];
6745
- var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
6746
- insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
6747
- if (line.styleClasses) {
6748
- if (line.styleClasses.bgClass)
6749
- builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
6750
- if (line.styleClasses.textClass)
6751
- builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");
6752
- }
6753
 
6754
- // Ensure at least a single node is present, for measuring.
6755
- if (builder.map.length == 0)
6756
- builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));
 
 
 
6757
 
6758
- // Store the map and a cache object for the current logical line
6759
- if (i == 0) {
6760
- lineView.measure.map = builder.map;
6761
- lineView.measure.cache = {};
6762
- } else {
6763
- (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);
6764
- (lineView.measure.caches || (lineView.measure.caches = [])).push({});
6765
- }
6766
- }
6767
 
6768
- // See issue #2901
6769
- if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
6770
- builder.content.className = "cm-tab-wrap-hack";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6771
 
6772
- signal(cm, "renderLine", cm, lineView.line, builder.pre);
6773
- if (builder.pre.className)
6774
- builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
6775
 
6776
- return builder;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6777
  }
6778
 
6779
- function defaultSpecialCharPlaceholder(ch) {
6780
- var token = elt("span", "\u2022", "cm-invalidchar");
6781
- token.title = "\\u" + ch.charCodeAt(0).toString(16);
6782
- token.setAttribute("aria-label", token.title);
6783
- return token;
6784
- }
 
 
 
 
 
6785
 
6786
- // Build up the DOM representation for a single token, and add it to
6787
- // the line map. Takes care to render special characters separately.
6788
- function buildToken(builder, text, style, startStyle, endStyle, title, css) {
6789
- if (!text) return;
6790
- var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;
6791
- var special = builder.cm.state.specialChars, mustWrap = false;
6792
- if (!special.test(text)) {
6793
- builder.col += text.length;
6794
- var content = document.createTextNode(displayText);
6795
- builder.map.push(builder.pos, builder.pos + text.length, content);
6796
- if (ie && ie_version < 9) mustWrap = true;
6797
- builder.pos += text.length;
6798
- } else {
6799
- var content = document.createDocumentFragment(), pos = 0;
6800
- while (true) {
6801
- special.lastIndex = pos;
6802
- var m = special.exec(text);
6803
- var skipped = m ? m.index - pos : text.length - pos;
6804
- if (skipped) {
6805
- var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
6806
- if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
6807
- else content.appendChild(txt);
6808
- builder.map.push(builder.pos, builder.pos + skipped, txt);
6809
- builder.col += skipped;
6810
- builder.pos += skipped;
6811
- }
6812
- if (!m) break;
6813
- pos += skipped + 1;
6814
- if (m[0] == "\t") {
6815
- var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
6816
- var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
6817
- txt.setAttribute("role", "presentation");
6818
- txt.setAttribute("cm-text", "\t");
6819
- builder.col += tabWidth;
6820
  } else {
6821
- var txt = builder.cm.options.specialCharPlaceholder(m[0]);
6822
- txt.setAttribute("cm-text", m[0]);
6823
- if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
6824
- else content.appendChild(txt);
6825
- builder.col += 1;
6826
  }
6827
- builder.map.push(builder.pos, builder.pos + 1, txt);
6828
- builder.pos++;
 
6829
  }
6830
- }
6831
- if (style || startStyle || endStyle || mustWrap || css) {
6832
- var fullStyle = style || "";
6833
- if (startStyle) fullStyle += startStyle;
6834
- if (endStyle) fullStyle += endStyle;
6835
- var token = elt("span", [content], fullStyle, css);
6836
- if (title) token.title = title;
6837
- return builder.content.appendChild(token);
6838
- }
6839
- builder.content.appendChild(content);
6840
  }
6841
 
6842
- function splitSpaces(old) {
6843
- var out = " ";
6844
- for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
6845
- out += " ";
6846
- return out;
6847
- }
6848
 
6849
- // Work around nonsense dimensions being reported for stretches of
6850
- // right-to-left text.
6851
- function buildTokenBadBidi(inner, order) {
6852
- return function(builder, text, style, startStyle, endStyle, title, css) {
6853
- style = style ? style + " cm-force-border" : "cm-force-border";
6854
- var start = builder.pos, end = start + text.length;
6855
- for (;;) {
6856
- // Find the part that overlaps with the start of this text
6857
- for (var i = 0; i < order.length; i++) {
6858
- var part = order[i];
6859
- if (part.to > start && part.from <= start) break;
6860
- }
6861
- if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
6862
- inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
6863
- startStyle = null;
6864
- text = text.slice(part.to - start);
6865
- start = part.to;
6866
  }
6867
- };
6868
  }
6869
 
6870
- function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
6871
- var widget = !ignoreWidget && marker.widgetNode;
6872
- if (widget) builder.map.push(builder.pos, builder.pos + size, widget);
6873
- if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
6874
- if (!widget)
6875
- widget = builder.content.appendChild(document.createElement("span"));
6876
- widget.setAttribute("cm-marker", marker.id);
6877
- }
6878
- if (widget) {
6879
- builder.cm.display.input.setUneditable(widget);
6880
- builder.content.appendChild(widget);
6881
- }
6882
- builder.pos += size;
6883
  }
6884
 
6885
- // Outputs a number of spans to make up a line, taking highlighting
6886
- // and marked text into account.
6887
- function insertLineContent(line, builder, styles) {
6888
- var spans = line.markedSpans, allText = line.text, at = 0;
6889
- if (!spans) {
6890
- for (var i = 1; i < styles.length; i+=2)
6891
- builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));
6892
- return;
6893
- }
6894
 
6895
- var len = allText.length, pos = 0, i = 1, text = "", style, css;
6896
- var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
6897
- for (;;) {
6898
- if (nextChange == pos) { // Update current marker set
6899
- spanStyle = spanEndStyle = spanStartStyle = title = css = "";
6900
- collapsed = null; nextChange = Infinity;
6901
- var foundBookmarks = [];
6902
- for (var j = 0; j < spans.length; ++j) {
6903
- var sp = spans[j], m = sp.marker;
6904
- if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
6905
- if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
6906
- if (m.className) spanStyle += " " + m.className;
6907
- if (m.css) css = m.css;
6908
- if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
6909
- if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
6910
- if (m.title && !title) title = m.title;
6911
- if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
6912
- collapsed = sp;
6913
- } else if (sp.from > pos && nextChange > sp.from) {
6914
- nextChange = sp.from;
6915
- }
6916
- if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);
6917
- }
6918
- if (collapsed && (collapsed.from || 0) == pos) {
6919
- buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
6920
- collapsed.marker, collapsed.from == null);
6921
- if (collapsed.to == null) return;
6922
- }
6923
- if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
6924
- buildCollapsedSpan(builder, 0, foundBookmarks[j]);
6925
- }
6926
- if (pos >= len) break;
6927
 
6928
- var upto = Math.min(len, nextChange);
6929
- while (true) {
6930
- if (text) {
6931
- var end = pos + text.length;
6932
- if (!collapsed) {
6933
- var tokenText = end > upto ? text.slice(0, upto - pos) : text;
6934
- builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
6935
- spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);
6936
- }
6937
- if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
6938
- pos = end;
6939
- spanStartStyle = "";
 
 
 
 
 
6940
  }
6941
- text = allText.slice(at, at = styles[i++]);
6942
- style = interpretTokenStyle(styles[i++], builder.cm.options);
6943
  }
 
6944
  }
 
 
 
 
 
 
6945
  }
6946
 
6947
- // DOCUMENT DATA STRUCTURE
6948
-
6949
- // By default, updates that start and end at the beginning of a line
6950
- // are treated specially, in order to make the association of line
6951
- // widgets and marker elements with the text behave more intuitive.
6952
- function isWholeLineUpdate(doc, change) {
6953
- return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
6954
- (!doc.cm || doc.cm.options.wholeLineUpdateBefore);
6955
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6956
 
6957
- // Perform a change on the document data structure.
6958
- function updateDoc(doc, change, markedSpans, estimateHeight) {
6959
- function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
6960
- function update(line, text, spans) {
6961
- updateLine(line, text, spans, estimateHeight);
6962
- signalLater(line, "change", line, change);
 
 
6963
  }
6964
- function linesFor(start, end) {
6965
- for (var i = start, result = []; i < end; ++i)
6966
- result.push(new Line(text[i], spansFor(i), estimateHeight));
6967
- return result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6968
  }
6969
 
6970
- var from = change.from, to = change.to, text = change.text;
6971
- var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
6972
- var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
6973
 
6974
- // Adjust the line structure
6975
- if (change.full) {
6976
- doc.insert(0, linesFor(0, text.length));
6977
- doc.remove(text.length, doc.size - text.length);
6978
- } else if (isWholeLineUpdate(doc, change)) {
6979
- // This is a whole-line replace. Treated specially to make
6980
- // sure line objects move the way they are supposed to.
6981
- var added = linesFor(0, text.length - 1);
6982
- update(lastLine, lastLine.text, lastSpans);
6983
- if (nlines) doc.remove(from.line, nlines);
6984
- if (added.length) doc.insert(from.line, added);
6985
- } else if (firstLine == lastLine) {
6986
- if (text.length == 1) {
6987
- update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
6988
  } else {
6989
- var added = linesFor(1, text.length - 1);
6990
- added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
6991
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
6992
- doc.insert(from.line + 1, added);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6993
  }
6994
- } else if (text.length == 1) {
6995
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
6996
- doc.remove(from.line + 1, nlines);
6997
- } else {
6998
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
6999
- update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
7000
- var added = linesFor(1, text.length - 1);
7001
- if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
7002
- doc.insert(from.line + 1, added);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7003
  }
 
 
7004
 
7005
- signalLater(doc, "change", doc, change);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7006
  }
7007
 
7008
- // The document is represented as a BTree consisting of leaves, with
7009
- // chunk of lines in them, and branches, with up to ten leaves or
7010
- // other branch nodes below them. The top node is always a branch
7011
- // node, and is the document object itself (meaning it has
7012
- // additional methods and properties).
7013
- //
7014
- // All nodes have parent links. The tree is used both to go from
7015
- // line numbers to line objects, and to go from objects to numbers.
7016
- // It also indexes by height, and is used to convert between height
7017
- // and line object, and to find the total height of the document.
7018
- //
7019
- // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
7020
 
7021
- function LeafChunk(lines) {
7022
- this.lines = lines;
7023
- this.parent = null;
7024
- for (var i = 0, height = 0; i < lines.length; ++i) {
7025
- lines[i].parent = this;
7026
- height += lines[i].height;
 
 
 
 
 
 
 
 
 
 
 
 
 
7027
  }
7028
- this.height = height;
7029
  }
7030
 
7031
- LeafChunk.prototype = {
7032
- chunkSize: function() { return this.lines.length; },
7033
- // Remove the n lines at offset 'at'.
7034
- removeInner: function(at, n) {
7035
- for (var i = at, e = at + n; i < e; ++i) {
7036
- var line = this.lines[i];
7037
- this.height -= line.height;
7038
- cleanUpLine(line);
7039
- signalLater(line, "delete");
7040
- }
7041
- this.lines.splice(at, n);
7042
- },
7043
- // Helper used to collapse a small branch into a single leaf.
7044
- collapse: function(lines) {
7045
- lines.push.apply(lines, this.lines);
7046
- },
7047
- // Insert the given array of lines at offset 'at', count them as
7048
- // having the given height.
7049
- insertInner: function(at, lines, height) {
7050
- this.height += height;
7051
- this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
7052
- for (var i = 0; i < lines.length; ++i) lines[i].parent = this;
7053
- },
7054
- // Used to iterate over a part of the tree.
7055
- iterN: function(at, n, op) {
7056
- for (var e = at + n; at < e; ++at)
7057
- if (op(this.lines[at])) return true;
7058
  }
7059
- };
7060
 
7061
- function BranchChunk(children) {
7062
- this.children = children;
7063
- var size = 0, height = 0;
7064
- for (var i = 0; i < children.length; ++i) {
7065
- var ch = children[i];
7066
- size += ch.chunkSize(); height += ch.height;
7067
- ch.parent = this;
 
 
 
 
 
 
 
 
 
 
 
 
7068
  }
7069
- this.size = size;
7070
- this.height = height;
7071
- this.parent = null;
7072
  }
7073
 
7074
- BranchChunk.prototype = {
7075
- chunkSize: function() { return this.size; },
7076
- removeInner: function(at, n) {
7077
- this.size -= n;
7078
- for (var i = 0; i < this.children.length; ++i) {
7079
- var child = this.children[i], sz = child.chunkSize();
7080
- if (at < sz) {
7081
- var rm = Math.min(n, sz - at), oldHeight = child.height;
7082
- child.removeInner(at, rm);
7083
- this.height -= oldHeight - child.height;
7084
- if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
7085
- if ((n -= rm) == 0) break;
7086
- at = 0;
7087
- } else at -= sz;
7088
- }
7089
- // If the result is smaller than 25 lines, ensure that it is a
7090
- // single leaf node.
7091
- if (this.size - n < 25 &&
7092
- (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
7093
- var lines = [];
7094
- this.collapse(lines);
7095
- this.children = [new LeafChunk(lines)];
7096
- this.children[0].parent = this;
7097
- }
7098
- },
7099
- collapse: function(lines) {
7100
- for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);
7101
- },
7102
- insertInner: function(at, lines, height) {
7103
- this.size += lines.length;
7104
- this.height += height;
7105
- for (var i = 0; i < this.children.length; ++i) {
7106
- var child = this.children[i], sz = child.chunkSize();
7107
- if (at <= sz) {
7108
- child.insertInner(at, lines, height);
7109
- if (child.lines && child.lines.length > 50) {
7110
- while (child.lines.length > 50) {
7111
- var spilled = child.lines.splice(child.lines.length - 25, 25);
7112
- var newleaf = new LeafChunk(spilled);
7113
- child.height -= newleaf.height;
7114
- this.children.splice(i + 1, 0, newleaf);
7115
- newleaf.parent = this;
7116
- }
7117
- this.maybeSpill();
7118
- }
7119
- break;
7120
- }
7121
- at -= sz;
7122
- }
7123
- },
7124
- // When a node has grown, check whether it should be split.
7125
- maybeSpill: function() {
7126
- if (this.children.length <= 10) return;
7127
- var me = this;
7128
- do {
7129
- var spilled = me.children.splice(me.children.length - 5, 5);
7130
- var sibling = new BranchChunk(spilled);
7131
- if (!me.parent) { // Become the parent node
7132
- var copy = new BranchChunk(me.children);
7133
- copy.parent = me;
7134
- me.children = [copy, sibling];
7135
- me = copy;
7136
- } else {
7137
- me.size -= sibling.size;
7138
- me.height -= sibling.height;
7139
- var myIndex = indexOf(me.parent.children, me);
7140
- me.parent.children.splice(myIndex + 1, 0, sibling);
7141
- }
7142
- sibling.parent = me.parent;
7143
- } while (me.children.length > 10);
7144
- me.parent.maybeSpill();
7145
- },
7146
- iterN: function(at, n, op) {
7147
- for (var i = 0; i < this.children.length; ++i) {
7148
- var child = this.children[i], sz = child.chunkSize();
7149
- if (at < sz) {
7150
- var used = Math.min(n, sz - at);
7151
- if (child.iterN(at, used, op)) return true;
7152
- if ((n -= used) == 0) break;
7153
- at = 0;
7154
- } else at -= sz;
7155
  }
7156
  }
7157
- };
 
 
7158
 
7159
- var nextDocId = 0;
7160
- var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
7161
- if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
7162
- if (firstLine == null) firstLine = 0;
7163
 
7164
- BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
7165
- this.first = firstLine;
7166
- this.scrollTop = this.scrollLeft = 0;
7167
- this.cantEdit = false;
7168
- this.cleanGeneration = 1;
7169
- this.frontier = firstLine;
7170
- var start = Pos(firstLine, 0);
7171
- this.sel = simpleSelection(start);
7172
- this.history = new History(null);
7173
- this.id = ++nextDocId;
7174
- this.modeOption = mode;
 
 
7175
 
7176
- if (typeof text == "string") text = splitLines(text);
7177
- updateDoc(this, {from: start, to: start, text: text});
7178
- setSelection(this, simpleSelection(start), sel_dontScroll);
 
 
 
7179
  };
7180
 
7181
- Doc.prototype = createObj(BranchChunk.prototype, {
7182
- constructor: Doc,
7183
- // Iterate over the document. Supports two forms -- with only one
7184
- // argument, it calls that for each line in the document. With
7185
- // three, it iterates over the range given by the first two (with
7186
- // the second being non-inclusive).
7187
- iter: function(from, to, op) {
7188
- if (op) this.iterN(from - this.first, to - from, op);
7189
- else this.iterN(this.first, this.first + this.size, from);
7190
- },
7191
 
7192
- // Non-public interface for adding and removing lines.
7193
- insert: function(at, lines) {
7194
- var height = 0;
7195
- for (var i = 0; i < lines.length; ++i) height += lines[i].height;
7196
- this.insertInner(at - this.first, lines, height);
7197
- },
7198
- remove: function(at, n) { this.removeInner(at - this.first, n); },
 
 
 
 
 
 
 
 
 
7199
 
7200
- // From here, the methods are part of the public interface. Most
7201
- // are also available from CodeMirror (editor) instances.
 
 
 
 
 
 
 
 
7202
 
7203
- getValue: function(lineSep) {
7204
- var lines = getLines(this, this.first, this.first + this.size);
7205
- if (lineSep === false) return lines;
7206
- return lines.join(lineSep || "\n");
7207
- },
7208
- setValue: docMethodOp(function(code) {
7209
- var top = Pos(this.first, 0), last = this.first + this.size - 1;
7210
- makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
7211
- text: splitLines(code), origin: "setValue", full: true}, true);
7212
- setSelection(this, simpleSelection(top));
7213
- }),
7214
- replaceRange: function(code, from, to, origin) {
7215
- from = clipPos(this, from);
7216
- to = to ? clipPos(this, to) : from;
7217
- replaceRange(this, code, from, to, origin);
7218
- },
7219
- getRange: function(from, to, lineSep) {
7220
- var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
7221
- if (lineSep === false) return lines;
7222
- return lines.join(lineSep || "\n");
7223
- },
7224
 
7225
- getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
 
 
7226
 
7227
- getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
7228
- getLineNumber: function(line) {return lineNo(line);},
7229
 
7230
- getLineHandleVisualStart: function(line) {
7231
- if (typeof line == "number") line = getLine(this, line);
7232
- return visualLine(line);
7233
- },
 
 
 
 
 
 
 
7234
 
7235
- lineCount: function() {return this.size;},
7236
- firstLine: function() {return this.first;},
7237
- lastLine: function() {return this.first + this.size - 1;},
 
 
7238
 
7239
- clipPos: function(pos) {return clipPos(this, pos);},
 
 
 
 
 
 
 
 
 
 
 
 
7240
 
7241
- getCursor: function(start) {
7242
- var range = this.sel.primary(), pos;
7243
- if (start == null || start == "head") pos = range.head;
7244
- else if (start == "anchor") pos = range.anchor;
7245
- else if (start == "end" || start == "to" || start === false) pos = range.to();
7246
- else pos = range.from();
7247
- return pos;
7248
- },
7249
- listSelections: function() { return this.sel.ranges; },
7250
- somethingSelected: function() {return this.sel.somethingSelected();},
 
 
7251
 
7252
- setCursor: docMethodOp(function(line, ch, options) {
7253
- setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
7254
- }),
7255
- setSelection: docMethodOp(function(anchor, head, options) {
7256
- setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
7257
- }),
7258
- extendSelection: docMethodOp(function(head, other, options) {
7259
- extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
7260
- }),
7261
- extendSelections: docMethodOp(function(heads, options) {
7262
- extendSelections(this, clipPosArray(this, heads, options));
7263
- }),
7264
- extendSelectionsBy: docMethodOp(function(f, options) {
7265
- extendSelections(this, map(this.sel.ranges, f), options);
7266
- }),
7267
- setSelections: docMethodOp(function(ranges, primary, options) {
7268
- if (!ranges.length) return;
7269
- for (var i = 0, out = []; i < ranges.length; i++)
7270
- out[i] = new Range(clipPos(this, ranges[i].anchor),
7271
- clipPos(this, ranges[i].head));
7272
- if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);
7273
- setSelection(this, normalizeSelection(out, primary), options);
7274
- }),
7275
- addSelection: docMethodOp(function(anchor, head, options) {
7276
- var ranges = this.sel.ranges.slice(0);
7277
- ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
7278
- setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);
7279
- }),
7280
 
7281
- getSelection: function(lineSep) {
7282
- var ranges = this.sel.ranges, lines;
7283
- for (var i = 0; i < ranges.length; i++) {
7284
- var sel = getBetween(this, ranges[i].from(), ranges[i].to());
7285
- lines = lines ? lines.concat(sel) : sel;
7286
- }
7287
- if (lineSep === false) return lines;
7288
- else return lines.join(lineSep || "\n");
7289
- },
7290
- getSelections: function(lineSep) {
7291
- var parts = [], ranges = this.sel.ranges;
7292
- for (var i = 0; i < ranges.length; i++) {
7293
- var sel = getBetween(this, ranges[i].from(), ranges[i].to());
7294
- if (lineSep !== false) sel = sel.join(lineSep || "\n");
7295
- parts[i] = sel;
 
 
 
 
 
 
 
7296
  }
7297
- return parts;
7298
- },
7299
- replaceSelection: function(code, collapse, origin) {
7300
- var dup = [];
7301
- for (var i = 0; i < this.sel.ranges.length; i++)
7302
- dup[i] = code;
7303
- this.replaceSelections(dup, collapse, origin || "+input");
7304
- },
7305
- replaceSelections: docMethodOp(function(code, collapse, origin) {
7306
- var changes = [], sel = this.sel;
7307
- for (var i = 0; i < sel.ranges.length; i++) {
7308
- var range = sel.ranges[i];
7309
- changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin};
7310
  }
7311
- var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
7312
- for (var i = changes.length - 1; i >= 0; i--)
7313
- makeChange(this, changes[i]);
7314
- if (newSel) setSelectionReplaceHistory(this, newSel);
7315
- else if (this.cm) ensureCursorVisible(this.cm);
7316
- }),
7317
- undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
7318
- redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
7319
- undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
7320
- redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
 
 
 
7321
 
7322
- setExtending: function(val) {this.extend = val;},
7323
- getExtending: function() {return this.extend;},
 
 
 
7324
 
7325
- historySize: function() {
7326
- var hist = this.history, done = 0, undone = 0;
7327
- for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;
7328
- for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;
7329
- return {undo: done, redo: undone};
7330
- },
7331
- clearHistory: function() {this.history = new History(this.history.maxGeneration);},
7332
 
7333
- markClean: function() {
7334
- this.cleanGeneration = this.changeGeneration(true);
7335
- },
7336
- changeGeneration: function(forceSplit) {
7337
- if (forceSplit)
7338
- this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;
7339
- return this.history.generation;
7340
- },
7341
- isClean: function (gen) {
7342
- return this.history.generation == (gen || this.cleanGeneration);
7343
- },
7344
 
7345
- getHistory: function() {
7346
- return {done: copyHistoryArray(this.history.done),
7347
- undone: copyHistoryArray(this.history.undone)};
7348
- },
7349
- setHistory: function(histData) {
7350
- var hist = this.history = new History(this.history.maxGeneration);
7351
- hist.done = copyHistoryArray(histData.done.slice(0), null, true);
7352
- hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
7353
- },
 
 
7354
 
7355
- addLineClass: docMethodOp(function(handle, where, cls) {
7356
- return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
7357
- var prop = where == "text" ? "textClass"
7358
- : where == "background" ? "bgClass"
7359
- : where == "gutter" ? "gutterClass" : "wrapClass";
7360
- if (!line[prop]) line[prop] = cls;
7361
- else if (classTest(cls).test(line[prop])) return false;
7362
- else line[prop] += " " + cls;
7363
- return true;
7364
- });
7365
- }),
7366
- removeLineClass: docMethodOp(function(handle, where, cls) {
7367
- return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
7368
- var prop = where == "text" ? "textClass"
7369
- : where == "background" ? "bgClass"
7370
- : where == "gutter" ? "gutterClass" : "wrapClass";
7371
- var cur = line[prop];
7372
- if (!cur) return false;
7373
- else if (cls == null) line[prop] = null;
7374
- else {
7375
- var found = cur.match(classTest(cls));
7376
- if (!found) return false;
7377
- var end = found.index + found[0].length;
7378
- line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7379
  }
7380
- return true;
7381
- });
7382
- }),
7383
-
7384
- markText: function(from, to, options) {
7385
- return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
7386
- },
7387
- setBookmark: function(pos, options) {
7388
- var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
7389
- insertLeft: options && options.insertLeft,
7390
- clearWhenEmpty: false, shared: options && options.shared};
7391
- pos = clipPos(this, pos);
7392
- return markText(this, pos, pos, realOpts, "bookmark");
7393
- },
7394
- findMarksAt: function(pos) {
7395
- pos = clipPos(this, pos);
7396
- var markers = [], spans = getLine(this, pos.line).markedSpans;
7397
- if (spans) for (var i = 0; i < spans.length; ++i) {
7398
- var span = spans[i];
7399
- if ((span.from == null || span.from <= pos.ch) &&
7400
- (span.to == null || span.to >= pos.ch))
7401
- markers.push(span.marker.parent || span.marker);
7402
- }
7403
- return markers;
7404
- },
7405
- findMarks: function(from, to, filter) {
7406
- from = clipPos(this, from); to = clipPos(this, to);
7407
- var found = [], lineNo = from.line;
7408
- this.iter(from.line, to.line + 1, function(line) {
7409
- var spans = line.markedSpans;
7410
- if (spans) for (var i = 0; i < spans.length; i++) {
7411
- var span = spans[i];
7412
- if (!(lineNo == from.line && from.ch > span.to ||
7413
- span.from == null && lineNo != from.line||
7414
- lineNo == to.line && span.from > to.ch) &&
7415
- (!filter || filter(span.marker)))
7416
- found.push(span.marker.parent || span.marker);
7417
  }
7418
- ++lineNo;
7419
- });
7420
- return found;
7421
- },
7422
- getAllMarks: function() {
7423
- var markers = [];
7424
- this.iter(function(line) {
7425
- var sps = line.markedSpans;
7426
- if (sps) for (var i = 0; i < sps.length; ++i)
7427
- if (sps[i].from != null) markers.push(sps[i].marker);
7428
- });
7429
- return markers;
7430
- },
7431
 
7432
- posFromIndex: function(off) {
7433
- var ch, lineNo = this.first;
7434
- this.iter(function(line) {
7435
- var sz = line.text.length + 1;
7436
- if (sz > off) { ch = off; return true; }
7437
- off -= sz;
7438
- ++lineNo;
7439
- });
7440
- return clipPos(this, Pos(lineNo, ch));
7441
- },
7442
- indexFromPos: function (coords) {
7443
- coords = clipPos(this, coords);
7444
- var index = coords.ch;
7445
- if (coords.line < this.first || coords.ch < 0) return 0;
7446
- this.iter(this.first, coords.line, function (line) {
7447
- index += line.text.length + 1;
7448
- });
7449
- return index;
7450
- },
7451
 
7452
- copy: function(copyHistory) {
7453
- var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
7454
- doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
7455
- doc.sel = this.sel;
7456
- doc.extend = false;
7457
- if (copyHistory) {
7458
- doc.history.undoDepth = this.history.undoDepth;
7459
- doc.setHistory(this.getHistory());
 
 
 
 
 
 
 
 
 
7460
  }
7461
- return doc;
7462
- },
7463
 
7464
- linkedDoc: function(options) {
7465
- if (!options) options = {};
7466
- var from = this.first, to = this.first + this.size;
7467
- if (options.from != null && options.from > from) from = options.from;
7468
- if (options.to != null && options.to < to) to = options.to;
7469
- var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
7470
- if (options.sharedHist) copy.history = this.history;
7471
- (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
7472
- copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
7473
- copySharedMarkers(copy, findSharedMarkers(this));
7474
- return copy;
7475
- },
7476
- unlinkDoc: function(other) {
7477
- if (other instanceof CodeMirror) other = other.doc;
7478
- if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
7479
- var link = this.linked[i];
7480
- if (link.doc != other) continue;
7481
- this.linked.splice(i, 1);
7482
- other.unlinkDoc(this);
7483
- detachSharedMarkers(findSharedMarkers(this));
7484
- break;
7485
- }
7486
- // If the histories were shared, split them again
7487
- if (other.history == this.history) {
7488
- var splitIds = [other.id];
7489
- linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
7490
- other.history = new History(null);
7491
- other.history.done = copyHistoryArray(this.history.done, splitIds);
7492
- other.history.undone = copyHistoryArray(this.history.undone, splitIds);
7493
  }
7494
- },
7495
- iterLinkedDocs: function(f) {linkedDocs(this, f);},
 
 
7496
 
7497
- getMode: function() {return this.mode;},
7498
- getEditor: function() {return this.cm;}
7499
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7500
 
7501
- // Public alias.
7502
- Doc.prototype.eachLine = Doc.prototype.iter;
 
 
 
7503
 
7504
- // Set up methods on CodeMirror's prototype to redirect to the editor's document.
7505
- var dontDelegate = "iter insert remove copy getEditor".split(" ");
7506
- for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
7507
- CodeMirror.prototype[prop] = (function(method) {
7508
- return function() {return method.apply(this.doc, arguments);};
7509
- })(Doc.prototype[prop]);
7510
 
7511
- eventMixin(Doc);
 
 
 
 
 
 
 
 
 
 
 
 
7512
 
7513
- // Call f for all linked documents.
7514
- function linkedDocs(doc, f, sharedHistOnly) {
7515
- function propagate(doc, skip, sharedHist) {
7516
- if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
7517
- var rel = doc.linked[i];
7518
- if (rel.doc == skip) continue;
7519
- var shared = sharedHist && rel.sharedHist;
7520
- if (sharedHistOnly && !shared) continue;
7521
- f(rel.doc, shared);
7522
- propagate(rel.doc, doc, shared);
 
 
 
7523
  }
7524
  }
7525
- propagate(doc, null, true);
7526
  }
7527
 
7528
- // Attach a document to an editor.
7529
- function attachDoc(cm, doc) {
7530
- if (doc.cm) throw new Error("This document is already in use.");
7531
- cm.doc = doc;
7532
- doc.cm = cm;
7533
- estimateLineHeights(cm);
7534
- loadMode(cm);
7535
- if (!cm.options.lineWrapping) findMaxLine(cm);
7536
- cm.options.mode = doc.modeOption;
7537
- regChange(cm);
7538
  }
7539
 
7540
- // LINE UTILITIES
7541
 
7542
- // Find the line object corresponding to the given line number.
7543
- function getLine(doc, n) {
7544
- n -= doc.first;
7545
- if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");
7546
- for (var chunk = doc; !chunk.lines;) {
7547
- for (var i = 0;; ++i) {
7548
- var child = chunk.children[i], sz = child.chunkSize();
7549
- if (n < sz) { chunk = child; break; }
7550
- n -= sz;
7551
- }
7552
- }
7553
- return chunk.lines[n];
7554
  }
7555
 
7556
- // Get the part of a document between two positions, as an array of
7557
- // strings.
7558
- function getBetween(doc, start, end) {
7559
- var out = [], n = start.line;
7560
- doc.iter(start.line, end.line + 1, function(line) {
7561
- var text = line.text;
7562
- if (n == end.line) text = text.slice(0, end.ch);
7563
- if (n == start.line) text = text.slice(start.ch);
7564
- out.push(text);
7565
- ++n;
7566
- });
7567
- return out;
7568
  }
7569
- // Get the lines between from and to, as array of strings.
7570
- function getLines(doc, from, to) {
7571
- var out = [];
7572
- doc.iter(from, to, function(line) { out.push(line.text); });
7573
- return out;
7574
  }
7575
 
7576
- // Update the height of a line, propagating the height change
7577
- // upwards to parent nodes.
7578
- function updateLineHeight(line, height) {
7579
- var diff = height - line.height;
7580
- if (diff) for (var n = line; n; n = n.parent) n.height += diff;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7581
  }
7582
 
7583
- // Given a line object, find its line number by walking up through
7584
- // its parent links.
7585
- function lineNo(line) {
7586
- if (line.parent == null) return null;
7587
- var cur = line.parent, no = indexOf(cur.lines, line);
7588
- for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
7589
- for (var i = 0;; ++i) {
7590
- if (chunk.children[i] == cur) break;
7591
- no += chunk.children[i].chunkSize();
7592
- }
 
 
 
 
 
 
 
 
 
 
 
7593
  }
7594
- return no + cur.first;
 
 
 
7595
  }
7596
 
7597
- // Find the line at the given vertical position, using the height
7598
- // information in the document tree.
7599
- function lineAtHeight(chunk, h) {
7600
- var n = chunk.first;
7601
- outer: do {
7602
- for (var i = 0; i < chunk.children.length; ++i) {
7603
- var child = chunk.children[i], ch = child.height;
7604
- if (h < ch) { chunk = child; continue outer; }
7605
- h -= ch;
7606
- n += child.chunkSize();
7607
- }
7608
- return n;
7609
- } while (!chunk.lines);
7610
- for (var i = 0; i < chunk.lines.length; ++i) {
7611
- var line = chunk.lines[i], lh = line.height;
7612
- if (h < lh) break;
7613
- h -= lh;
7614
- }
7615
- return n + i;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7616
  }
7617
 
 
 
 
 
7618
 
7619
- // Find the height above the given line.
7620
- function heightAtLine(lineObj) {
7621
- lineObj = visualLine(lineObj);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7622
 
7623
- var h = 0, chunk = lineObj.parent;
7624
- for (var i = 0; i < chunk.lines.length; ++i) {
7625
- var line = chunk.lines[i];
7626
- if (line == lineObj) break;
7627
- else h += line.height;
7628
- }
7629
- for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
7630
- for (var i = 0; i < p.children.length; ++i) {
7631
- var cur = p.children[i];
7632
- if (cur == chunk) break;
7633
- else h += cur.height;
7634
  }
7635
  }
7636
- return h;
7637
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7638
 
7639
- // Get the bidi ordering for the given line (and cache it). Returns
7640
- // false for lines that are fully left-to-right, and an array of
7641
- // BidiSpan objects otherwise.
7642
- function getOrder(line) {
7643
- var order = line.order;
7644
- if (order == null) order = line.order = bidiOrdering(line.text);
7645
- return order;
7646
- }
 
7647
 
7648
- // HISTORY
 
 
7649
 
7650
- function History(startGen) {
7651
- // Arrays of change events and selections. Doing something adds an
7652
- // event to done and clears undo. Undoing moves events from done
7653
- // to undone, redoing moves them in the other direction.
7654
- this.done = []; this.undone = [];
7655
- this.undoDepth = Infinity;
7656
- // Used to track when changes can be merged into a single undo
7657
- // event
7658
- this.lastModTime = this.lastSelTime = 0;
7659
- this.lastOp = this.lastSelOp = null;
7660
- this.lastOrigin = this.lastSelOrigin = null;
7661
- // Used by the isClean() method
7662
- this.generation = this.maxGeneration = startGen || 1;
7663
- }
7664
 
7665
- // Create a history change event from an updateDoc-style change
7666
- // object.
7667
- function historyChangeFromChange(doc, change) {
7668
- var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
7669
- attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
7670
- linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
7671
- return histChange;
7672
  }
7673
 
7674
- // Pop all selection events off the end of a history array. Stop at
7675
- // a change event.
7676
- function clearSelectionEvents(array) {
7677
- while (array.length) {
7678
- var last = lst(array);
7679
- if (last.ranges) array.pop();
7680
- else break;
 
 
 
 
 
 
 
 
 
7681
  }
7682
- }
7683
 
7684
- // Find the top change event in the history. Pop off selection
7685
- // events that are in the way.
7686
- function lastChangeEvent(hist, force) {
7687
- if (force) {
7688
- clearSelectionEvents(hist.done);
7689
- return lst(hist.done);
7690
- } else if (hist.done.length && !lst(hist.done).ranges) {
7691
- return lst(hist.done);
7692
- } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
7693
- hist.done.pop();
7694
- return lst(hist.done);
 
 
7695
  }
7696
- }
 
 
 
 
 
 
 
 
 
 
7697
 
7698
- // Register a change in the history. Merges changes that are within
7699
- // a single operation, ore are close together with an origin that
7700
- // allows merging (starting with "+") into a single event.
7701
- function addChangeToHistory(doc, change, selAfter, opId) {
7702
- var hist = doc.history;
7703
- hist.undone.length = 0;
7704
- var time = +new Date, cur;
7705
 
7706
- if ((hist.lastOp == opId ||
7707
- hist.lastOrigin == change.origin && change.origin &&
7708
- ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
7709
- change.origin.charAt(0) == "*")) &&
7710
- (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
7711
- // Merge this change into the last event
7712
- var last = lst(cur.changes);
7713
- if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
7714
- // Optimized case for simple insertion -- don't want to add
7715
- // new changesets for every character typed
7716
- last.to = changeEnd(change);
7717
- } else {
7718
- // Add new sub-event
7719
- cur.changes.push(historyChangeFromChange(doc, change));
7720
- }
7721
  } else {
7722
- // Can not be merged, start a new event.
7723
- var before = lst(hist.done);
7724
- if (!before || !before.ranges)
7725
- pushSelectionToHistory(doc.sel, hist.done);
7726
- cur = {changes: [historyChangeFromChange(doc, change)],
7727
- generation: hist.generation};
7728
- hist.done.push(cur);
7729
- while (hist.done.length > hist.undoDepth) {
7730
- hist.done.shift();
7731
- if (!hist.done[0].ranges) hist.done.shift();
7732
  }
7733
  }
7734
- hist.done.push(selAfter);
7735
- hist.generation = ++hist.maxGeneration;
7736
- hist.lastModTime = hist.lastSelTime = time;
7737
- hist.lastOp = hist.lastSelOp = opId;
7738
- hist.lastOrigin = hist.lastSelOrigin = change.origin;
7739
-
7740
- if (!last) signal(doc, "historyAdded");
7741
  }
7742
 
7743
- function selectionEventCanBeMerged(doc, origin, prev, sel) {
7744
- var ch = origin.charAt(0);
7745
- return ch == "*" ||
7746
- ch == "+" &&
7747
- prev.ranges.length == sel.ranges.length &&
7748
- prev.somethingSelected() == sel.somethingSelected() &&
7749
- new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
7750
  }
7751
 
7752
- // Called whenever the selection changes, sets the new selection as
7753
- // the pending selection in the history, and pushes the old pending
7754
- // selection into the 'done' array when it was significantly
7755
- // different (in number of selected ranges, emptiness, or time).
7756
- function addSelectionToHistory(doc, sel, opId, options) {
7757
- var hist = doc.history, origin = options && options.origin;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7758
 
7759
- // A new event is started when the previous origin does not match
7760
- // the current, or the origins don't allow matching. Origins
7761
- // starting with * are always merged, those starting with + are
7762
- // merged when similar and close together in time.
7763
- if (opId == hist.lastSelOp ||
7764
- (origin && hist.lastSelOrigin == origin &&
7765
- (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
7766
- selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
7767
- hist.done[hist.done.length - 1] = sel;
7768
- else
7769
- pushSelectionToHistory(sel, hist.done);
 
 
 
 
 
 
 
 
 
7770
 
7771
- hist.lastSelTime = +new Date;
7772
- hist.lastSelOrigin = origin;
7773
- hist.lastSelOp = opId;
7774
- if (options && options.clearRedo !== false)
7775
- clearSelectionEvents(hist.undone);
7776
  }
7777
 
7778
- function pushSelectionToHistory(sel, dest) {
7779
- var top = lst(dest);
7780
- if (!(top && top.ranges && top.equals(sel)))
7781
- dest.push(sel);
 
 
 
 
7782
  }
7783
 
7784
- // Used to store marked span information in the history.
7785
- function attachLocalSpans(doc, change, from, to) {
7786
- var existing = change["spans_" + doc.id], n = 0;
7787
- doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
7788
- if (line.markedSpans)
7789
- (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
7790
- ++n;
7791
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7792
  }
7793
 
7794
- // When un/re-doing restores text containing marked spans, those
7795
- // that have been explicitly cleared should not be restored.
7796
- function removeClearedSpans(spans) {
7797
- if (!spans) return null;
7798
- for (var i = 0, out; i < spans.length; ++i) {
7799
- if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
7800
- else if (out) out.push(spans[i]);
7801
  }
7802
- return !out ? spans : out.length ? out : null;
7803
  }
7804
 
7805
- // Retrieve and filter the old marked spans stored in a change event.
7806
- function getOldSpans(doc, change) {
7807
- var found = change["spans_" + doc.id];
7808
- if (!found) return null;
7809
- for (var i = 0, nw = []; i < change.text.length; ++i)
7810
- nw.push(removeClearedSpans(found[i]));
7811
- return nw;
7812
  }
7813
 
7814
- // Used both to provide a JSON-safe object in .getHistory, and, when
7815
- // detaching a document, to split the history in two
7816
- function copyHistoryArray(events, newGroup, instantiateSel) {
7817
- for (var i = 0, copy = []; i < events.length; ++i) {
7818
- var event = events[i];
7819
- if (event.ranges) {
7820
- copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
7821
- continue;
7822
- }
7823
- var changes = event.changes, newChanges = [];
7824
- copy.push({changes: newChanges});
7825
- for (var j = 0; j < changes.length; ++j) {
7826
- var change = changes[j], m;
7827
- newChanges.push({from: change.from, to: change.to, text: change.text});
7828
- if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
7829
- if (indexOf(newGroup, Number(m[1])) > -1) {
7830
- lst(newChanges)[prop] = change[prop];
7831
- delete change[prop];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7832
  }
7833
  }
7834
- }
7835
- }
7836
- return copy;
7837
- }
7838
 
7839
- // Rebasing/resetting history to deal with externally-sourced changes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7840
 
7841
- function rebaseHistSelSingle(pos, from, to, diff) {
7842
- if (to < pos.line) {
7843
- pos.line += diff;
7844
- } else if (from < pos.line) {
7845
- pos.line = from;
7846
- pos.ch = 0;
7847
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7848
  }
7849
 
7850
- // Tries to rebase an array of history events given a change in the
7851
- // document. If the change touches the same lines as the event, the
7852
- // event, and everything 'behind' it, is discarded. If the change is
7853
- // before the event, the event's positions are updated. Uses a
7854
- // copy-on-write scheme for the positions, to avoid having to
7855
- // reallocate them all on every rebase, but also avoid problems with
7856
- // shared position objects being unsafely updated.
7857
- function rebaseHistArray(array, from, to, diff) {
7858
- for (var i = 0; i < array.length; ++i) {
7859
- var sub = array[i], ok = true;
7860
- if (sub.ranges) {
7861
- if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
7862
- for (var j = 0; j < sub.ranges.length; j++) {
7863
- rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
7864
- rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7865
  }
7866
- continue;
 
 
 
7867
  }
7868
- for (var j = 0; j < sub.changes.length; ++j) {
7869
- var cur = sub.changes[j];
7870
- if (to < cur.from.line) {
7871
- cur.from = Pos(cur.from.line + diff, cur.from.ch);
7872
- cur.to = Pos(cur.to.line + diff, cur.to.ch);
7873
- } else if (from <= cur.to.line) {
7874
- ok = false;
7875
- break;
7876
- }
7877
  }
7878
- if (!ok) {
7879
- array.splice(0, i + 1);
7880
- i = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7881
  }
7882
  }
 
 
 
7883
  }
7884
 
7885
- function rebaseHist(hist, change) {
7886
- var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
7887
- rebaseHistArray(hist.done, from, to, diff);
7888
- rebaseHistArray(hist.undone, from, to, diff);
7889
- }
 
 
 
 
7890
 
7891
- // EVENT UTILITIES
 
 
 
 
 
 
 
 
 
 
 
7892
 
7893
- // Due to the fact that we still support jurassic IE versions, some
7894
- // compatibility wrappers are needed.
7895
 
7896
- var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
7897
- if (e.preventDefault) e.preventDefault();
7898
- else e.returnValue = false;
7899
- };
7900
- var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
7901
- if (e.stopPropagation) e.stopPropagation();
7902
- else e.cancelBubble = true;
7903
  };
7904
- function e_defaultPrevented(e) {
7905
- return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
7906
- }
7907
- var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
7908
 
7909
- function e_target(e) {return e.target || e.srcElement;}
7910
- function e_button(e) {
7911
- var b = e.which;
7912
- if (b == null) {
7913
- if (e.button & 1) b = 1;
7914
- else if (e.button & 2) b = 3;
7915
- else if (e.button & 4) b = 2;
 
 
 
 
 
 
7916
  }
7917
- if (mac && e.ctrlKey && b == 1) b = 3;
7918
- return b;
7919
- }
7920
 
7921
- // EVENT HANDLING
 
 
 
 
7922
 
7923
- // Lightweight event framework. on/off also work on DOM nodes,
7924
- // registering native DOM handlers.
 
 
 
 
 
 
 
 
 
 
7925
 
7926
- var on = CodeMirror.on = function(emitter, type, f) {
7927
- if (emitter.addEventListener)
7928
- emitter.addEventListener(type, f, false);
7929
- else if (emitter.attachEvent)
7930
- emitter.attachEvent("on" + type, f);
7931
- else {
7932
- var map = emitter._handlers || (emitter._handlers = {});
7933
- var arr = map[type] || (map[type] = []);
7934
- arr.push(f);
7935
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7936
  };
7937
 
7938
- var off = CodeMirror.off = function(emitter, type, f) {
7939
- if (emitter.removeEventListener)
7940
- emitter.removeEventListener(type, f, false);
7941
- else if (emitter.detachEvent)
7942
- emitter.detachEvent("on" + type, f);
7943
- else {
7944
- var arr = emitter._handlers && emitter._handlers[type];
7945
- if (!arr) return;
7946
- for (var i = 0; i < arr.length; ++i)
7947
- if (arr[i] == f) { arr.splice(i, 1); break; }
7948
  }
7949
  };
7950
 
7951
- var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
7952
- var arr = emitter._handlers && emitter._handlers[type];
7953
- if (!arr) return;
7954
- var args = Array.prototype.slice.call(arguments, 2);
7955
- for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
7956
  };
7957
 
7958
- var orphanDelayedCallbacks = null;
 
 
 
 
7959
 
7960
- // Often, we want to signal events at a point where we are in the
7961
- // middle of some work, but don't want the handler to start calling
7962
- // other methods on the editor, which might be in an inconsistent
7963
- // state or simply not expect any other events to happen.
7964
- // signalLater looks whether there are any handlers, and schedules
7965
- // them to be executed when the last operation ends, or, if no
7966
- // operation is active, when a timeout fires.
7967
- function signalLater(emitter, type /*, values...*/) {
7968
- var arr = emitter._handlers && emitter._handlers[type];
7969
- if (!arr) return;
7970
- var args = Array.prototype.slice.call(arguments, 2), list;
7971
- if (operationGroup) {
7972
- list = operationGroup.delayedCallbacks;
7973
- } else if (orphanDelayedCallbacks) {
7974
- list = orphanDelayedCallbacks;
7975
- } else {
7976
- list = orphanDelayedCallbacks = [];
7977
- setTimeout(fireOrphanDelayed, 0);
7978
  }
7979
- function bnd(f) {return function(){f.apply(null, args);};};
7980
- for (var i = 0; i < arr.length; ++i)
7981
- list.push(bnd(arr[i]));
7982
- }
7983
 
7984
- function fireOrphanDelayed() {
7985
- var delayed = orphanDelayedCallbacks;
7986
- orphanDelayedCallbacks = null;
7987
- for (var i = 0; i < delayed.length; ++i) delayed[i]();
7988
- }
 
7989
 
7990
- // The DOM events that CodeMirror handles can be overridden by
7991
- // registering a (non-DOM) handler on the editor for the event name,
7992
- // and preventDefault-ing the event in that handler.
7993
- function signalDOMEvent(cm, e, override) {
7994
- if (typeof e == "string")
7995
- e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
7996
- signal(cm, override || e.type, cm, e);
7997
- return e_defaultPrevented(e) || e.codemirrorIgnore;
7998
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7999
 
8000
- function signalCursorActivity(cm) {
8001
- var arr = cm._handlers && cm._handlers.cursorActivity;
8002
- if (!arr) return;
8003
- var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
8004
- for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
8005
- set.push(arr[i]);
8006
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8007
 
8008
- function hasHandler(emitter, type) {
8009
- var arr = emitter._handlers && emitter._handlers[type];
8010
- return arr && arr.length > 0;
8011
- }
 
 
8012
 
8013
- // Add on and off methods to a constructor's prototype, to make
8014
- // registering events on such objects more convenient.
8015
- function eventMixin(ctor) {
8016
- ctor.prototype.on = function(type, f) {on(this, type, f);};
8017
- ctor.prototype.off = function(type, f) {off(this, type, f);};
8018
- }
 
 
 
8019
 
8020
- // MISC UTILITIES
8021
 
8022
- // Number of pixels added to scroller and sizer to hide scrollbar
8023
- var scrollerGap = 30;
 
 
 
 
8024
 
8025
- // Returned or thrown by various protocols to signal 'I'm not
8026
- // handling this'.
8027
- var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
 
 
 
 
 
8028
 
8029
- // Reused option objects for setSelection & friends
8030
- var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
 
 
 
8031
 
8032
- function Delayed() {this.id = null;}
8033
- Delayed.prototype.set = function(ms, f) {
8034
- clearTimeout(this.id);
8035
- this.id = setTimeout(f, ms);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8036
  };
8037
 
8038
- // Counts the column offset in a string, taking tabs into account.
8039
- // Used mostly to find indentation.
8040
- var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
8041
- if (end == null) {
8042
- end = string.search(/[^\s\u00a0]/);
8043
- if (end == -1) end = string.length;
8044
  }
8045
- for (var i = startIndex || 0, n = startValue || 0;;) {
8046
- var nextTab = string.indexOf("\t", i);
8047
- if (nextTab < 0 || nextTab >= end)
8048
- return n + (end - i);
8049
- n += nextTab - i;
8050
- n += tabSize - (n % tabSize);
8051
- i = nextTab + 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8052
  }
8053
  };
8054
 
8055
- // The inverse of countColumn -- find the offset that corresponds to
8056
- // a particular column.
8057
- function findColumn(string, goal, tabSize) {
8058
- for (var pos = 0, col = 0;;) {
8059
- var nextTab = string.indexOf("\t", pos);
8060
- if (nextTab == -1) nextTab = string.length;
8061
- var skipped = nextTab - pos;
8062
- if (nextTab == string.length || col + skipped >= goal)
8063
- return pos + Math.min(skipped, goal - col);
8064
- col += nextTab - pos;
8065
- col += tabSize - (col % tabSize);
8066
- pos = nextTab + 1;
8067
- if (col >= goal) return pos;
8068
- }
8069
- }
 
 
 
 
 
 
 
 
 
 
 
 
8070
 
8071
- var spaceStrs = [""];
8072
- function spaceStr(n) {
8073
- while (spaceStrs.length <= n)
8074
- spaceStrs.push(lst(spaceStrs) + " ");
8075
- return spaceStrs[n];
8076
- }
8077
 
8078
- function lst(arr) { return arr[arr.length-1]; }
 
 
8079
 
8080
- var selectInput = function(node) { node.select(); };
8081
- if (ios) // Mobile Safari apparently has a bug where select() is broken.
8082
- selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
8083
- else if (ie) // Suppress mysterious IE10 errors
8084
- selectInput = function(node) { try { node.select(); } catch(_e) {} };
8085
 
8086
- function indexOf(array, elt) {
8087
- for (var i = 0; i < array.length; ++i)
8088
- if (array[i] == elt) return i;
8089
- return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8090
  }
8091
- function map(array, f) {
8092
- var out = [];
8093
- for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
8094
- return out;
 
8095
  }
8096
 
8097
- function nothing() {}
8098
 
8099
- function createObj(base, props) {
8100
- var inst;
8101
- if (Object.create) {
8102
- inst = Object.create(base);
8103
- } else {
8104
- nothing.prototype = base;
8105
- inst = new nothing();
 
 
8106
  }
8107
- if (props) copyObj(props, inst);
8108
- return inst;
8109
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8110
 
8111
- function copyObj(obj, target, overwrite) {
8112
- if (!target) target = {};
8113
- for (var prop in obj)
8114
- if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
8115
- target[prop] = obj[prop];
8116
- return target;
8117
- }
8118
 
8119
- function bind(f) {
8120
- var args = Array.prototype.slice.call(arguments, 1);
8121
- return function(){return f.apply(null, args);};
 
 
 
 
 
 
 
 
 
 
8122
  }
8123
 
8124
- var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
8125
- var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
8126
- return /\w/.test(ch) || ch > "\x80" &&
8127
- (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
8128
- };
8129
- function isWordChar(ch, helper) {
8130
- if (!helper) return isWordCharBasic(ch);
8131
- if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
8132
- return helper.test(ch);
 
 
 
 
 
 
 
 
8133
  }
8134
 
8135
- function isEmpty(obj) {
8136
- for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
8137
- return true;
8138
- }
 
 
 
 
 
 
 
 
8139
 
8140
- // Extending unicode characters. A series of a non-extending char +
8141
- // any number of extending chars is treated as a single unit as far
8142
- // as editing and measuring is concerned. This is not fully correct,
8143
- // since some scripts/fonts/browsers also treat other configurations
8144
- // of code points as a group.
8145
- var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
8146
- function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
8147
 
8148
- // DOM UTILITIES
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8149
 
8150
- function elt(tag, content, className, style) {
8151
- var e = document.createElement(tag);
8152
- if (className) e.className = className;
8153
- if (style) e.style.cssText = style;
8154
- if (typeof content == "string") e.appendChild(document.createTextNode(content));
8155
- else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
8156
- return e;
 
 
 
 
 
 
 
 
8157
  }
8158
 
8159
- var range;
8160
- if (document.createRange) range = function(node, start, end, endNode) {
8161
- var r = document.createRange();
8162
- r.setEnd(endNode || node, end);
8163
- r.setStart(node, start);
8164
- return r;
8165
- };
8166
- else range = function(node, start, end) {
8167
- var r = document.body.createTextRange();
8168
- try { r.moveToElementText(node.parentNode); }
8169
- catch(e) { return r; }
8170
- r.collapse(true);
8171
- r.moveEnd("character", end);
8172
- r.moveStart("character", start);
8173
- return r;
 
8174
  };
8175
 
8176
- function removeChildren(e) {
8177
- for (var count = e.childNodes.length; count > 0; --count)
8178
- e.removeChild(e.firstChild);
8179
- return e;
8180
- }
8181
 
8182
- function removeChildrenAndAdd(parent, e) {
8183
- return removeChildren(parent).appendChild(e);
8184
- }
8185
 
8186
- var contains = CodeMirror.contains = function(parent, child) {
8187
- if (child.nodeType == 3) // Android browser always returns false when child is a textnode
8188
- child = child.parentNode;
8189
- if (parent.contains)
8190
- return parent.contains(child);
8191
- do {
8192
- if (child.nodeType == 11) child = child.host;
8193
- if (child == parent) return true;
8194
- } while (child = child.parentNode);
8195
- };
8196
 
8197
- function activeElt() { return document.activeElement; }
8198
- // Older versions of IE throws unspecified error when touching
8199
- // document.activeElement in some cases (during loading, in iframe)
8200
- if (ie && ie_version < 11) activeElt = function() {
8201
- try { return document.activeElement; }
8202
- catch(e) { return document.body; }
8203
- };
8204
 
8205
- function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
8206
- var rmClass = CodeMirror.rmClass = function(node, cls) {
8207
- var current = node.className;
8208
- var match = classTest(cls).exec(current);
8209
- if (match) {
8210
- var after = current.slice(match.index + match[0].length);
8211
- node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
8212
- }
8213
- };
8214
- var addClass = CodeMirror.addClass = function(node, cls) {
8215
- var current = node.className;
8216
- if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
8217
- };
8218
- function joinClasses(a, b) {
8219
- var as = a.split(" ");
8220
- for (var i = 0; i < as.length; i++)
8221
- if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
8222
- return b;
8223
- }
8224
 
8225
- // WINDOW-WIDE EVENTS
 
8226
 
8227
- // These must be handled carefully, because naively registering a
8228
- // handler for each editor will cause the editors to never be
8229
- // garbage collected.
8230
 
8231
- function forEachCodeMirror(f) {
8232
- if (!document.body.getElementsByClassName) return;
8233
- var byClass = document.body.getElementsByClassName("CodeMirror");
8234
- for (var i = 0; i < byClass.length; i++) {
8235
- var cm = byClass[i].CodeMirror;
8236
- if (cm) f(cm);
 
 
 
 
 
 
 
 
 
 
 
 
8237
  }
8238
- }
 
8239
 
8240
- var globalsRegistered = false;
8241
- function ensureGlobalHandlers() {
8242
- if (globalsRegistered) return;
8243
- registerGlobalHandlers();
8244
- globalsRegistered = true;
8245
- }
8246
- function registerGlobalHandlers() {
8247
- // When the window resizes, we need to refresh active editors.
8248
- var resizeTimer;
8249
- on(window, "resize", function() {
8250
- if (resizeTimer == null) resizeTimer = setTimeout(function() {
8251
- resizeTimer = null;
8252
- forEachCodeMirror(onResize);
8253
- }, 100);
8254
  });
8255
- // When the window loses focus, we want to show the editor as blurred
8256
- on(window, "blur", function() {
8257
- forEachCodeMirror(onBlur);
 
8258
  });
8259
- }
8260
 
8261
- // FEATURE DETECTION
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8262
 
8263
- // Detect drag-and-drop
8264
- var dragAndDrop = function() {
8265
- // There is *some* kind of drag-and-drop support in IE6-8, but I
8266
- // couldn't get it to work yet.
8267
- if (ie && ie_version < 9) return false;
8268
- var div = elt('div');
8269
- return "draggable" in div || "dragDrop" in div;
8270
- }();
8271
 
8272
- var zwspSupported;
8273
- function zeroWidthElement(measure) {
8274
- if (zwspSupported == null) {
8275
- var test = elt("span", "\u200b");
8276
- removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
8277
- if (measure.firstChild.offsetHeight != 0)
8278
- zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);
8279
  }
8280
- var node = zwspSupported ? elt("span", "\u200b") :
8281
- elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
8282
- node.setAttribute("cm-text", "");
8283
- return node;
8284
- }
8285
 
8286
- // Feature-detect IE's crummy client rect reporting for bidi text
8287
- var badBidiRects;
8288
- function hasBadBidiRects(measure) {
8289
- if (badBidiRects != null) return badBidiRects;
8290
- var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
8291
- var r0 = range(txt, 0, 1).getBoundingClientRect();
8292
- if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
8293
- var r1 = range(txt, 1, 2).getBoundingClientRect();
8294
- return badBidiRects = (r1.right - r0.right < 3);
8295
- }
8296
 
8297
- // See if "".split is the broken IE version, if so, provide an
8298
- // alternative way to split lines.
8299
- var splitLines = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
8300
- var pos = 0, result = [], l = string.length;
8301
- while (pos <= l) {
8302
- var nl = string.indexOf("\n", pos);
8303
- if (nl == -1) nl = string.length;
8304
- var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
8305
- var rt = line.indexOf("\r");
8306
- if (rt != -1) {
8307
- result.push(line.slice(0, rt));
8308
- pos += rt + 1;
8309
- } else {
8310
- result.push(line);
8311
- pos = nl + 1;
8312
- }
8313
  }
8314
- return result;
8315
- } : function(string){return string.split(/\r\n?|\n/);};
8316
 
8317
- var hasSelection = window.getSelection ? function(te) {
8318
- try { return te.selectionStart != te.selectionEnd; }
8319
- catch(e) { return false; }
8320
- } : function(te) {
8321
- try {var range = te.ownerDocument.selection.createRange();}
8322
- catch(e) {}
8323
- if (!range || range.parentElement() != te) return false;
8324
- return range.compareEndPoints("StartToEnd", range) != 0;
8325
  };
8326
 
8327
- var hasCopyEvent = (function() {
8328
- var e = elt("div");
8329
- if ("oncopy" in e) return true;
8330
- e.setAttribute("oncopy", "return;");
8331
- return typeof e.oncopy == "function";
8332
- })();
 
 
 
8333
 
8334
- var badZoomedRects = null;
8335
- function hasBadZoomedRects(measure) {
8336
- if (badZoomedRects != null) return badZoomedRects;
8337
- var node = removeChildrenAndAdd(measure, elt("span", "x"));
8338
- var normal = node.getBoundingClientRect();
8339
- var fromRange = range(node, 0, 1).getBoundingClientRect();
8340
- return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;
8341
- }
8342
-
8343
- // KEY NAMES
8344
-
8345
- var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
8346
- 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
8347
- 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
8348
- 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete",
8349
- 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
8350
- 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
8351
- 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"};
8352
- CodeMirror.keyNames = keyNames;
8353
- (function() {
8354
- // Number keys
8355
- for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
8356
- // Alphabetic keys
8357
- for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
8358
- // Function keys
8359
- for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
8360
- })();
8361
 
8362
- // BIDI HELPERS
8363
 
8364
- function iterateBidiSections(order, from, to, f) {
8365
- if (!order) return f(from, to, "ltr");
8366
- var found = false;
8367
- for (var i = 0; i < order.length; ++i) {
8368
- var part = order[i];
8369
- if (part.from < to && part.to > from || from == to && part.to == from) {
8370
- f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
8371
- found = true;
8372
- }
8373
  }
8374
- if (!found) f(from, to, "ltr");
8375
- }
8376
 
8377
- function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
8378
- function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
8379
 
8380
- function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
8381
- function lineRight(line) {
8382
- var order = getOrder(line);
8383
- if (!order) return line.text.length;
8384
- return bidiRight(lst(order));
8385
- }
8386
 
8387
- function lineStart(cm, lineN) {
8388
- var line = getLine(cm.doc, lineN);
8389
- var visual = visualLine(line);
8390
- if (visual != line) lineN = lineNo(visual);
8391
- var order = getOrder(visual);
8392
- var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
8393
- return Pos(lineN, ch);
8394
- }
8395
- function lineEnd(cm, lineN) {
8396
- var merged, line = getLine(cm.doc, lineN);
8397
- while (merged = collapsedSpanAtEnd(line)) {
8398
- line = merged.find(1, true).line;
8399
- lineN = null;
8400
- }
8401
- var order = getOrder(line);
8402
- var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
8403
- return Pos(lineN == null ? lineNo(line) : lineN, ch);
8404
- }
8405
- function lineStartSmart(cm, pos) {
8406
- var start = lineStart(cm, pos.line);
8407
- var line = getLine(cm.doc, start.line);
8408
- var order = getOrder(line);
8409
- if (!order || order[0].level == 0) {
8410
- var firstNonWS = Math.max(0, line.text.search(/\S/));
8411
- var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
8412
- return Pos(start.line, inWS ? 0 : firstNonWS);
8413
- }
8414
- return start;
8415
- }
8416
 
8417
- function compareBidiLevel(order, a, b) {
8418
- var linedir = order[0].level;
8419
- if (a == linedir) return true;
8420
- if (b == linedir) return false;
8421
- return a < b;
8422
- }
8423
- var bidiOther;
8424
- function getBidiPartAt(order, pos) {
8425
- bidiOther = null;
8426
- for (var i = 0, found; i < order.length; ++i) {
8427
- var cur = order[i];
8428
- if (cur.from < pos && cur.to > pos) return i;
8429
- if ((cur.from == pos || cur.to == pos)) {
8430
- if (found == null) {
8431
- found = i;
8432
- } else if (compareBidiLevel(order, cur.level, order[found].level)) {
8433
- if (cur.from != cur.to) bidiOther = found;
8434
- return i;
8435
- } else {
8436
- if (cur.from != cur.to) bidiOther = i;
8437
- return found;
8438
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8439
  }
8440
- }
8441
- return found;
8442
- }
8443
 
8444
- function moveInLine(line, pos, dir, byUnit) {
8445
- if (!byUnit) return pos + dir;
8446
- do pos += dir;
8447
- while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
8448
- return pos;
8449
- }
8450
 
8451
- // This is needed in order to move 'visually' through bi-directional
8452
- // text -- i.e., pressing left should make the cursor go left, even
8453
- // when in RTL text. The tricky part is the 'jumps', where RTL and
8454
- // LTR text touch each other. This often requires the cursor offset
8455
- // to move more than one unit, in order to visually move one unit.
8456
- function moveVisually(line, start, dir, byUnit) {
8457
- var bidi = getOrder(line);
8458
- if (!bidi) return moveLogically(line, start, dir, byUnit);
8459
- var pos = getBidiPartAt(bidi, start), part = bidi[pos];
8460
- var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
8461
 
8462
- for (;;) {
8463
- if (target > part.from && target < part.to) return target;
8464
- if (target == part.from || target == part.to) {
8465
- if (getBidiPartAt(bidi, target) == pos) return target;
8466
- part = bidi[pos += dir];
8467
- return (dir > 0) == part.level % 2 ? part.to : part.from;
8468
- } else {
8469
- part = bidi[pos += dir];
8470
- if (!part) return null;
8471
- if ((dir > 0) == part.level % 2)
8472
- target = moveInLine(line, part.to, -1, byUnit);
8473
- else
8474
- target = moveInLine(line, part.from, 1, byUnit);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8475
  }
8476
  }
8477
- }
8478
 
8479
- function moveLogically(line, start, dir, byUnit) {
8480
- var target = start + dir;
8481
- if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
8482
- return target < 0 || target > line.text.length ? null : target;
8483
- }
 
 
 
 
 
 
 
8484
 
8485
- // Bidirectional ordering algorithm
8486
- // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
8487
- // that this (partially) implements.
 
 
8488
 
8489
- // One-char codes used for character types:
8490
- // L (L): Left-to-Right
8491
- // R (R): Right-to-Left
8492
- // r (AL): Right-to-Left Arabic
8493
- // 1 (EN): European Number
8494
- // + (ES): European Number Separator
8495
- // % (ET): European Number Terminator
8496
- // n (AN): Arabic Number
8497
- // , (CS): Common Number Separator
8498
- // m (NSM): Non-Spacing Mark
8499
- // b (BN): Boundary Neutral
8500
- // s (B): Paragraph Separator
8501
- // t (S): Segment Separator
8502
- // w (WS): Whitespace
8503
- // N (ON): Other Neutrals
8504
 
8505
- // Returns null if characters are ordered as they appear
8506
- // (left-to-right), or an array of sections ({from, to, level}
8507
- // objects) in the order in which they occur visually.
8508
- var bidiOrdering = (function() {
8509
- // Character types for codepoints 0 to 0xff
8510
- var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
8511
- // Character types for codepoints 0x600 to 0x6ff
8512
- var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";
8513
- function charType(code) {
8514
- if (code <= 0xf7) return lowTypes.charAt(code);
8515
- else if (0x590 <= code && code <= 0x5f4) return "R";
8516
- else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);
8517
- else if (0x6ee <= code && code <= 0x8ac) return "r";
8518
- else if (0x2000 <= code && code <= 0x200b) return "w";
8519
- else if (code == 0x200c) return "b";
8520
- else return "L";
8521
  }
8522
 
8523
- var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
8524
- var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
8525
- // Browsers seem to always treat the boundaries of block elements as being L.
8526
- var outerType = "L";
8527
 
8528
- function BidiSpan(level, from, to) {
8529
- this.level = level;
8530
- this.from = from; this.to = to;
 
 
 
 
 
 
 
 
 
 
 
 
 
8531
  }
8532
 
8533
- return function(str) {
8534
- if (!bidiRE.test(str)) return false;
8535
- var len = str.length, types = [];
8536
- for (var i = 0, type; i < len; ++i)
8537
- types.push(type = charType(str.charCodeAt(i)));
 
 
 
 
 
 
 
 
 
 
8538
 
8539
- // W1. Examine each non-spacing mark (NSM) in the level run, and
8540
- // change the type of the NSM to the type of the previous
8541
- // character. If the NSM is at the start of the level run, it will
8542
- // get the type of sor.
8543
- for (var i = 0, prev = outerType; i < len; ++i) {
8544
- var type = types[i];
8545
- if (type == "m") types[i] = prev;
8546
- else prev = type;
8547
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8548
 
8549
- // W2. Search backwards from each instance of a European number
8550
- // until the first strong type (R, L, AL, or sor) is found. If an
8551
- // AL is found, change the type of the European number to Arabic
8552
- // number.
8553
- // W3. Change all ALs to R.
8554
- for (var i = 0, cur = outerType; i < len; ++i) {
8555
- var type = types[i];
8556
- if (type == "1" && cur == "r") types[i] = "n";
8557
- else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
8558
- }
8559
 
8560
- // W4. A single European separator between two European numbers
8561
- // changes to a European number. A single common separator between
8562
- // two numbers of the same type changes to that type.
8563
- for (var i = 1, prev = types[0]; i < len - 1; ++i) {
8564
- var type = types[i];
8565
- if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
8566
- else if (type == "," && prev == types[i+1] &&
8567
- (prev == "1" || prev == "n")) types[i] = prev;
8568
- prev = type;
8569
- }
8570
 
8571
- // W5. A sequence of European terminators adjacent to European
8572
- // numbers changes to all European numbers.
8573
- // W6. Otherwise, separators and terminators change to Other
8574
- // Neutral.
8575
- for (var i = 0; i < len; ++i) {
8576
- var type = types[i];
8577
- if (type == ",") types[i] = "N";
8578
- else if (type == "%") {
8579
- for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
8580
- var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
8581
- for (var j = i; j < end; ++j) types[j] = replace;
8582
- i = end - 1;
8583
- }
8584
- }
8585
 
8586
- // W7. Search backwards from each instance of a European number
8587
- // until the first strong type (R, L, or sor) is found. If an L is
8588
- // found, then change the type of the European number to L.
8589
- for (var i = 0, cur = outerType; i < len; ++i) {
8590
- var type = types[i];
8591
- if (cur == "L" && type == "1") types[i] = "L";
8592
- else if (isStrong.test(type)) cur = type;
8593
- }
8594
 
8595
- // N1. A sequence of neutrals takes the direction of the
8596
- // surrounding strong text if the text on both sides has the same
8597
- // direction. European and Arabic numbers act as if they were R in
8598
- // terms of their influence on neutrals. Start-of-level-run (sor)
8599
- // and end-of-level-run (eor) are used at level run boundaries.
8600
- // N2. Any remaining neutrals take the embedding direction.
8601
- for (var i = 0; i < len; ++i) {
8602
- if (isNeutral.test(types[i])) {
8603
- for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
8604
- var before = (i ? types[i-1] : outerType) == "L";
8605
- var after = (end < len ? types[end] : outerType) == "L";
8606
- var replace = before || after ? "L" : "R";
8607
- for (var j = i; j < end; ++j) types[j] = replace;
8608
- i = end - 1;
8609
- }
8610
- }
8611
 
8612
- // Here we depart from the documented algorithm, in order to avoid
8613
- // building up an actual levels array. Since there are only three
8614
- // levels (0, 1, 2) in an implementation that doesn't take
8615
- // explicit embedding into account, we can build up the order on
8616
- // the fly, without following the level-based algorithm.
8617
- var order = [], m;
8618
- for (var i = 0; i < len;) {
8619
- if (countsAsLeft.test(types[i])) {
8620
- var start = i;
8621
- for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
8622
- order.push(new BidiSpan(0, start, i));
8623
- } else {
8624
- var pos = i, at = order.length;
8625
- for (++i; i < len && types[i] != "L"; ++i) {}
8626
- for (var j = pos; j < i;) {
8627
- if (countsAsNum.test(types[j])) {
8628
- if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));
8629
- var nstart = j;
8630
- for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
8631
- order.splice(at, 0, new BidiSpan(2, nstart, j));
8632
- pos = j;
8633
- } else ++j;
8634
- }
8635
- if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));
8636
- }
8637
- }
8638
- if (order[0].level == 1 && (m = str.match(/^\s+/))) {
8639
- order[0].from = m[0].length;
8640
- order.unshift(new BidiSpan(0, 0, m[0].length));
8641
- }
8642
- if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
8643
- lst(order).to -= m[0].length;
8644
- order.push(new BidiSpan(0, len - m[0].length, len));
8645
- }
8646
- if (order[0].level != lst(order).level)
8647
- order.push(new BidiSpan(order[0].level, len, len));
8648
 
8649
- return order;
8650
- };
8651
- })();
 
 
 
 
 
 
 
 
 
 
 
8652
 
8653
- // THE END
8654
 
8655
- CodeMirror.version = "5.0.1";
 
 
8656
 
8657
  return CodeMirror;
8658
- });
 
1
  // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: https://codemirror.net/LICENSE
3
 
4
+ // This is CodeMirror (https://codemirror.net), a code editor
5
  // implemented in JavaScript on top of the browser's DOM.
6
  //
7
  // You can find some technical background for some of the code below
8
  // at http://marijnhaverbeke.nl/blog/#cm-internals .
9
 
10
+ (function (global, factory) {
11
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
12
+ typeof define === 'function' && define.amd ? define(factory) :
13
+ (global = global || self, global.CodeMirror = factory());
14
+ }(this, (function () { 'use strict';
 
 
 
 
 
 
15
 
16
  // Kludges for bugs and behavior differences that can't be feature
17
  // detected are enabled based on userAgent etc sniffing.
18
+ var userAgent = navigator.userAgent;
19
+ var platform = navigator.platform;
20
+
21
+ var gecko = /gecko\/\d/i.test(userAgent);
22
+ var ie_upto10 = /MSIE \d/.test(userAgent);
23
+ var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
24
+ var edge = /Edge\/(\d+)/.exec(userAgent);
25
+ var ie = ie_upto10 || ie_11up || edge;
26
+ var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]);
27
+ var webkit = !edge && /WebKit\//.test(userAgent);
28
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
29
+ var chrome = !edge && /Chrome\//.test(userAgent);
30
+ var presto = /Opera\//.test(userAgent);
31
  var safari = /Apple Computer/.test(navigator.vendor);
32
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
33
+ var phantom = /PhantomJS/.test(userAgent);
34
 
35
+ var ios = safari && (/Mobile\/\w+/.test(userAgent) || navigator.maxTouchPoints > 2);
36
+ var android = /Android/.test(userAgent);
37
  // This is woefully incomplete. Suggestions for alternative methods welcome.
38
+ var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
39
+ var mac = ios || /Mac/.test(platform);
40
+ var chromeOS = /\bCrOS\b/.test(userAgent);
41
+ var windows = /win/i.test(platform);
42
 
43
+ var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
44
+ if (presto_version) { presto_version = Number(presto_version[1]); }
45
  if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
46
  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
47
  var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
48
  var captureRightClick = gecko || (ie && ie_version >= 9);
49
 
50
+ function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
 
 
 
51
 
52
+ var rmClass = function(node, cls) {
53
+ var current = node.className;
54
+ var match = classTest(cls).exec(current);
55
+ if (match) {
56
+ var after = current.slice(match.index + match[0].length);
57
+ node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
58
+ }
59
+ };
60
 
61
+ function removeChildren(e) {
62
+ for (var count = e.childNodes.length; count > 0; --count)
63
+ { e.removeChild(e.firstChild); }
64
+ return e
65
+ }
66
 
67
+ function removeChildrenAndAdd(parent, e) {
68
+ return removeChildren(parent).appendChild(e)
69
+ }
 
70
 
71
+ function elt(tag, content, className, style) {
72
+ var e = document.createElement(tag);
73
+ if (className) { e.className = className; }
74
+ if (style) { e.style.cssText = style; }
75
+ if (typeof content == "string") { e.appendChild(document.createTextNode(content)); }
76
+ else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } }
77
+ return e
78
+ }
79
+ // wrapper for elt, which removes the elt from the accessibility tree
80
+ function eltP(tag, content, className, style) {
81
+ var e = elt(tag, content, className, style);
82
+ e.setAttribute("role", "presentation");
83
+ return e
84
+ }
85
 
86
+ var range;
87
+ if (document.createRange) { range = function(node, start, end, endNode) {
88
+ var r = document.createRange();
89
+ r.setEnd(endNode || node, end);
90
+ r.setStart(node, start);
91
+ return r
92
+ }; }
93
+ else { range = function(node, start, end) {
94
+ var r = document.body.createTextRange();
95
+ try { r.moveToElementText(node.parentNode); }
96
+ catch(e) { return r }
97
+ r.collapse(true);
98
+ r.moveEnd("character", end);
99
+ r.moveStart("character", start);
100
+ return r
101
+ }; }
102
 
103
+ function contains(parent, child) {
104
+ if (child.nodeType == 3) // Android browser always returns false when child is a textnode
105
+ { child = child.parentNode; }
106
+ if (parent.contains)
107
+ { return parent.contains(child) }
108
+ do {
109
+ if (child.nodeType == 11) { child = child.host; }
110
+ if (child == parent) { return true }
111
+ } while (child = child.parentNode)
112
+ }
 
 
113
 
114
+ function activeElt() {
115
+ // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
116
+ // IE < 10 will throw when accessed while the page is loading or in an iframe.
117
+ // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
118
+ var activeElement;
119
+ try {
120
+ activeElement = document.activeElement;
121
+ } catch(e) {
122
+ activeElement = document.body || null;
123
+ }
124
+ while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
125
+ { activeElement = activeElement.shadowRoot.activeElement; }
126
+ return activeElement
127
+ }
128
 
129
+ function addClass(node, cls) {
130
+ var current = node.className;
131
+ if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; }
132
+ }
133
+ function joinClasses(a, b) {
134
+ var as = a.split(" ");
135
+ for (var i = 0; i < as.length; i++)
136
+ { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } }
137
+ return b
138
+ }
139
 
140
+ var selectInput = function(node) { node.select(); };
141
+ if (ios) // Mobile Safari apparently has a bug where select() is broken.
142
+ { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; }
143
+ else if (ie) // Suppress mysterious IE10 errors
144
+ { selectInput = function(node) { try { node.select(); } catch(_e) {} }; }
145
 
146
+ function bind(f) {
147
+ var args = Array.prototype.slice.call(arguments, 1);
148
+ return function(){return f.apply(null, args)}
149
+ }
150
 
151
+ function copyObj(obj, target, overwrite) {
152
+ if (!target) { target = {}; }
153
+ for (var prop in obj)
154
+ { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
155
+ { target[prop] = obj[prop]; } }
156
+ return target
157
+ }
158
 
159
+ // Counts the column offset in a string, taking tabs into account.
160
+ // Used mostly to find indentation.
161
+ function countColumn(string, end, tabSize, startIndex, startValue) {
162
+ if (end == null) {
163
+ end = string.search(/[^\s\u00a0]/);
164
+ if (end == -1) { end = string.length; }
165
+ }
166
+ for (var i = startIndex || 0, n = startValue || 0;;) {
167
+ var nextTab = string.indexOf("\t", i);
168
+ if (nextTab < 0 || nextTab >= end)
169
+ { return n + (end - i) }
170
+ n += nextTab - i;
171
+ n += tabSize - (n % tabSize);
172
+ i = nextTab + 1;
173
+ }
174
  }
175
 
176
+ var Delayed = function() {
177
+ this.id = null;
178
+ this.f = null;
179
+ this.time = 0;
180
+ this.handler = bind(this.onTimeout, this);
181
+ };
182
+ Delayed.prototype.onTimeout = function (self) {
183
+ self.id = 0;
184
+ if (self.time <= +new Date) {
185
+ self.f();
186
+ } else {
187
+ setTimeout(self.handler, self.time - +new Date);
188
+ }
189
+ };
190
+ Delayed.prototype.set = function (ms, f) {
191
+ this.f = f;
192
+ var time = +new Date + ms;
193
+ if (!this.id || time < this.time) {
194
+ clearTimeout(this.id);
195
+ this.id = setTimeout(this.handler, ms);
196
+ this.time = time;
197
+ }
198
+ };
199
 
200
+ function indexOf(array, elt) {
201
+ for (var i = 0; i < array.length; ++i)
202
+ { if (array[i] == elt) { return i } }
203
+ return -1
204
+ }
205
 
206
+ // Number of pixels added to scroller and sizer to hide scrollbar
207
+ var scrollerGap = 50;
 
208
 
209
+ // Returned or thrown by various protocols to signal 'I'm not
210
+ // handling this'.
211
+ var Pass = {toString: function(){return "CodeMirror.Pass"}};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
+ // Reused option objects for setSelection & friends
214
+ var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
 
215
 
216
+ // The inverse of countColumn -- find the offset that corresponds to
217
+ // a particular column.
218
+ function findColumn(string, goal, tabSize) {
219
+ for (var pos = 0, col = 0;;) {
220
+ var nextTab = string.indexOf("\t", pos);
221
+ if (nextTab == -1) { nextTab = string.length; }
222
+ var skipped = nextTab - pos;
223
+ if (nextTab == string.length || col + skipped >= goal)
224
+ { return pos + Math.min(skipped, goal - col) }
225
+ col += nextTab - pos;
226
+ col += tabSize - (col % tabSize);
227
+ pos = nextTab + 1;
228
+ if (col >= goal) { return pos }
229
  }
230
+ }
231
 
232
+ var spaceStrs = [""];
233
+ function spaceStr(n) {
234
+ while (spaceStrs.length <= n)
235
+ { spaceStrs.push(lst(spaceStrs) + " "); }
236
+ return spaceStrs[n]
237
+ }
 
 
 
 
 
 
 
238
 
239
+ function lst(arr) { return arr[arr.length-1] }
 
240
 
241
+ function map(array, f) {
242
+ var out = [];
243
+ for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); }
244
+ return out
245
+ }
 
 
246
 
247
+ function insertSorted(array, value, score) {
248
+ var pos = 0, priority = score(value);
249
+ while (pos < array.length && score(array[pos]) <= priority) { pos++; }
250
+ array.splice(pos, 0, value);
251
+ }
252
 
253
+ function nothing() {}
 
 
 
 
254
 
255
+ function createObj(base, props) {
256
+ var inst;
257
+ if (Object.create) {
258
+ inst = Object.create(base);
259
+ } else {
260
+ nothing.prototype = base;
261
+ inst = new nothing();
262
+ }
263
+ if (props) { copyObj(props, inst); }
264
+ return inst
265
+ }
266
 
267
+ var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
268
+ function isWordCharBasic(ch) {
269
+ return /\w/.test(ch) || ch > "\x80" &&
270
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
271
+ }
272
+ function isWordChar(ch, helper) {
273
+ if (!helper) { return isWordCharBasic(ch) }
274
+ if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true }
275
+ return helper.test(ch)
276
+ }
277
 
278
+ function isEmpty(obj) {
279
+ for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }
280
+ return true
281
+ }
282
 
283
+ // Extending unicode characters. A series of a non-extending char +
284
+ // any number of extending chars is treated as a single unit as far
285
+ // as editing and measuring is concerned. This is not fully correct,
286
+ // since some scripts/fonts/browsers also treat other configurations
287
+ // of code points as a group.
288
+ var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
289
+ function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }
290
 
291
+ // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range.
292
+ function skipExtendingChars(str, pos, dir) {
293
+ while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; }
294
+ return pos
295
  }
296
 
297
+ // Returns the value from the range [`from`; `to`] that satisfies
298
+ // `pred` and is closest to `from`. Assumes that at least `to`
299
+ // satisfies `pred`. Supports `from` being greater than `to`.
300
+ function findFirst(pred, from, to) {
301
+ // At any point we are certain `to` satisfies `pred`, don't know
302
+ // whether `from` does.
303
+ var dir = from > to ? -1 : 1;
304
+ for (;;) {
305
+ if (from == to) { return from }
306
+ var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF);
307
+ if (mid == from) { return pred(mid) ? from : to }
308
+ if (pred(mid)) { to = mid; }
309
+ else { from = mid + dir; }
310
+ }
311
+ }
312
 
313
+ // BIDI HELPERS
314
 
315
+ function iterateBidiSections(order, from, to, f) {
316
+ if (!order) { return f(from, to, "ltr", 0) }
317
+ var found = false;
318
+ for (var i = 0; i < order.length; ++i) {
319
+ var part = order[i];
320
+ if (part.from < to && part.to > from || from == to && part.to == from) {
321
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i);
322
+ found = true;
323
+ }
324
+ }
325
+ if (!found) { f(from, to, "ltr"); }
326
  }
327
 
328
+ var bidiOther = null;
329
+ function getBidiPartAt(order, ch, sticky) {
330
+ var found;
331
+ bidiOther = null;
332
+ for (var i = 0; i < order.length; ++i) {
333
+ var cur = order[i];
334
+ if (cur.from < ch && cur.to > ch) { return i }
335
+ if (cur.to == ch) {
336
+ if (cur.from != cur.to && sticky == "before") { found = i; }
337
+ else { bidiOther = i; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  }
339
+ if (cur.from == ch) {
340
+ if (cur.from != cur.to && sticky != "before") { found = i; }
341
+ else { bidiOther = i; }
342
+ }
343
+ }
344
+ return found != null ? found : bidiOther
 
 
 
 
 
 
 
 
345
  }
346
 
347
+ // Bidirectional ordering algorithm
348
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
349
+ // that this (partially) implements.
 
 
350
 
351
+ // One-char codes used for character types:
352
+ // L (L): Left-to-Right
353
+ // R (R): Right-to-Left
354
+ // r (AL): Right-to-Left Arabic
355
+ // 1 (EN): European Number
356
+ // + (ES): European Number Separator
357
+ // % (ET): European Number Terminator
358
+ // n (AN): Arabic Number
359
+ // , (CS): Common Number Separator
360
+ // m (NSM): Non-Spacing Mark
361
+ // b (BN): Boundary Neutral
362
+ // s (B): Paragraph Separator
363
+ // t (S): Segment Separator
364
+ // w (WS): Whitespace
365
+ // N (ON): Other Neutrals
366
 
367
+ // Returns null if characters are ordered as they appear
368
+ // (left-to-right), or an array of sections ({from, to, level}
369
+ // objects) in the order in which they occur visually.
370
+ var bidiOrdering = (function() {
371
+ // Character types for codepoints 0 to 0xff
372
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
373
+ // Character types for codepoints 0x600 to 0x6f9
374
+ var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";
375
+ function charType(code) {
376
+ if (code <= 0xf7) { return lowTypes.charAt(code) }
377
+ else if (0x590 <= code && code <= 0x5f4) { return "R" }
378
+ else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }
379
+ else if (0x6ee <= code && code <= 0x8ac) { return "r" }
380
+ else if (0x2000 <= code && code <= 0x200b) { return "w" }
381
+ else if (code == 0x200c) { return "b" }
382
+ else { return "L" }
383
  }
 
 
 
384
 
385
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
386
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
 
 
387
 
388
+ function BidiSpan(level, from, to) {
389
+ this.level = level;
390
+ this.from = from; this.to = to;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  }
 
 
392
 
393
+ return function(str, direction) {
394
+ var outerType = direction == "ltr" ? "L" : "R";
 
 
 
 
 
 
 
 
 
 
 
 
395
 
396
+ if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false }
397
+ var len = str.length, types = [];
398
+ for (var i = 0; i < len; ++i)
399
+ { types.push(charType(str.charCodeAt(i))); }
 
 
 
 
 
 
 
400
 
401
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
402
+ // change the type of the NSM to the type of the previous
403
+ // character. If the NSM is at the start of the level run, it will
404
+ // get the type of sor.
405
+ for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {
406
+ var type = types[i$1];
407
+ if (type == "m") { types[i$1] = prev; }
408
+ else { prev = type; }
409
+ }
410
 
411
+ // W2. Search backwards from each instance of a European number
412
+ // until the first strong type (R, L, AL, or sor) is found. If an
413
+ // AL is found, change the type of the European number to Arabic
414
+ // number.
415
+ // W3. Change all ALs to R.
416
+ for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {
417
+ var type$1 = types[i$2];
418
+ if (type$1 == "1" && cur == "r") { types[i$2] = "n"; }
419
+ else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } }
420
+ }
 
 
 
 
 
 
 
421
 
422
+ // W4. A single European separator between two European numbers
423
+ // changes to a European number. A single common separator between
424
+ // two numbers of the same type changes to that type.
425
+ for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {
426
+ var type$2 = types[i$3];
427
+ if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; }
428
+ else if (type$2 == "," && prev$1 == types[i$3+1] &&
429
+ (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; }
430
+ prev$1 = type$2;
431
+ }
432
 
433
+ // W5. A sequence of European terminators adjacent to European
434
+ // numbers changes to all European numbers.
435
+ // W6. Otherwise, separators and terminators change to Other
436
+ // Neutral.
437
+ for (var i$4 = 0; i$4 < len; ++i$4) {
438
+ var type$3 = types[i$4];
439
+ if (type$3 == ",") { types[i$4] = "N"; }
440
+ else if (type$3 == "%") {
441
+ var end = (void 0);
442
+ for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {}
443
+ var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
444
+ for (var j = i$4; j < end; ++j) { types[j] = replace; }
445
+ i$4 = end - 1;
446
+ }
447
+ }
448
 
449
+ // W7. Search backwards from each instance of a European number
450
+ // until the first strong type (R, L, or sor) is found. If an L is
451
+ // found, then change the type of the European number to L.
452
+ for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {
453
+ var type$4 = types[i$5];
454
+ if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; }
455
+ else if (isStrong.test(type$4)) { cur$1 = type$4; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
  }
457
 
458
+ // N1. A sequence of neutrals takes the direction of the
459
+ // surrounding strong text if the text on both sides has the same
460
+ // direction. European and Arabic numbers act as if they were R in
461
+ // terms of their influence on neutrals. Start-of-level-run (sor)
462
+ // and end-of-level-run (eor) are used at level run boundaries.
463
+ // N2. Any remaining neutrals take the embedding direction.
464
+ for (var i$6 = 0; i$6 < len; ++i$6) {
465
+ if (isNeutral.test(types[i$6])) {
466
+ var end$1 = (void 0);
467
+ for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}
468
+ var before = (i$6 ? types[i$6-1] : outerType) == "L";
469
+ var after = (end$1 < len ? types[end$1] : outerType) == "L";
470
+ var replace$1 = before == after ? (before ? "L" : "R") : outerType;
471
+ for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; }
472
+ i$6 = end$1 - 1;
473
+ }
474
  }
475
 
476
+ // Here we depart from the documented algorithm, in order to avoid
477
+ // building up an actual levels array. Since there are only three
478
+ // levels (0, 1, 2) in an implementation that doesn't take
479
+ // explicit embedding into account, we can build up the order on
480
+ // the fly, without following the level-based algorithm.
481
+ var order = [], m;
482
+ for (var i$7 = 0; i$7 < len;) {
483
+ if (countsAsLeft.test(types[i$7])) {
484
+ var start = i$7;
485
+ for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}
486
+ order.push(new BidiSpan(0, start, i$7));
487
+ } else {
488
+ var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0;
489
+ for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {}
490
+ for (var j$2 = pos; j$2 < i$7;) {
491
+ if (countsAsNum.test(types[j$2])) {
492
+ if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; }
493
+ var nstart = j$2;
494
+ for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}
495
+ order.splice(at, 0, new BidiSpan(2, nstart, j$2));
496
+ at += isRTL;
497
+ pos = j$2;
498
+ } else { ++j$2; }
499
+ }
500
+ if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); }
501
+ }
502
+ }
503
+ if (direction == "ltr") {
504
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
505
+ order[0].from = m[0].length;
506
+ order.unshift(new BidiSpan(0, 0, m[0].length));
507
+ }
508
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
509
+ lst(order).to -= m[0].length;
510
+ order.push(new BidiSpan(0, len - m[0].length, len));
511
+ }
512
  }
513
 
514
+ return direction == "rtl" ? order.reverse() : order
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
  }
516
+ })();
517
+
518
+ // Get the bidi ordering for the given line (and cache it). Returns
519
+ // false for lines that are fully left-to-right, and an array of
520
+ // BidiSpan objects otherwise.
521
+ function getOrder(line, direction) {
522
+ var order = line.order;
523
+ if (order == null) { order = line.order = bidiOrdering(line.text, direction); }
524
+ return order
525
+ }
526
 
527
+ // EVENT HANDLING
528
 
529
+ // Lightweight event framework. on/off also work on DOM nodes,
530
+ // registering native DOM handlers.
 
 
 
 
531
 
532
+ var noHandlers = [];
533
 
534
+ var on = function(emitter, type, f) {
535
+ if (emitter.addEventListener) {
536
+ emitter.addEventListener(type, f, false);
537
+ } else if (emitter.attachEvent) {
538
+ emitter.attachEvent("on" + type, f);
539
+ } else {
540
+ var map = emitter._handlers || (emitter._handlers = {});
541
+ map[type] = (map[type] || noHandlers).concat(f);
542
  }
543
+ };
544
 
545
+ function getHandlers(emitter, type) {
546
+ return emitter._handlers && emitter._handlers[type] || noHandlers
 
 
 
 
 
 
 
 
 
 
 
547
  }
548
 
549
+ function off(emitter, type, f) {
550
+ if (emitter.removeEventListener) {
551
+ emitter.removeEventListener(type, f, false);
552
+ } else if (emitter.detachEvent) {
553
+ emitter.detachEvent("on" + type, f);
554
+ } else {
555
+ var map = emitter._handlers, arr = map && map[type];
556
+ if (arr) {
557
+ var index = indexOf(arr, f);
558
+ if (index > -1)
559
+ { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); }
560
+ }
561
  }
562
  }
563
 
564
+ function signal(emitter, type /*, values...*/) {
565
+ var handlers = getHandlers(emitter, type);
566
+ if (!handlers.length) { return }
567
+ var args = Array.prototype.slice.call(arguments, 2);
568
+ for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); }
569
+ }
570
 
571
+ // The DOM events that CodeMirror handles can be overridden by
572
+ // registering a (non-DOM) handler on the editor for the event name,
573
+ // and preventDefault-ing the event in that handler.
574
+ function signalDOMEvent(cm, e, override) {
575
+ if (typeof e == "string")
576
+ { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; }
577
+ signal(cm, override || e.type, cm, e);
578
+ return e_defaultPrevented(e) || e.codemirrorIgnore
579
+ }
580
 
581
+ function signalCursorActivity(cm) {
582
+ var arr = cm._handlers && cm._handlers.cursorActivity;
583
+ if (!arr) { return }
584
+ var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
585
+ for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)
586
+ { set.push(arr[i]); } }
 
 
 
 
587
  }
588
 
589
+ function hasHandler(emitter, type) {
590
+ return getHandlers(emitter, type).length > 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
  }
592
 
593
+ // Add on and off methods to a constructor's prototype, to make
594
+ // registering events on such objects more convenient.
595
+ function eventMixin(ctor) {
596
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
597
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
 
 
 
 
 
 
 
 
 
 
 
 
 
598
  }
599
 
600
+ // Due to the fact that we still support jurassic IE versions, some
601
+ // compatibility wrappers are needed.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
602
 
603
+ function e_preventDefault(e) {
604
+ if (e.preventDefault) { e.preventDefault(); }
605
+ else { e.returnValue = false; }
606
  }
607
+ function e_stopPropagation(e) {
608
+ if (e.stopPropagation) { e.stopPropagation(); }
609
+ else { e.cancelBubble = true; }
 
 
 
610
  }
611
+ function e_defaultPrevented(e) {
612
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  }
614
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
615
 
616
+ function e_target(e) {return e.target || e.srcElement}
617
+ function e_button(e) {
618
+ var b = e.which;
619
+ if (b == null) {
620
+ if (e.button & 1) { b = 1; }
621
+ else if (e.button & 2) { b = 3; }
622
+ else if (e.button & 4) { b = 2; }
 
 
 
 
 
 
 
 
 
 
623
  }
624
+ if (mac && e.ctrlKey && b == 1) { b = 3; }
625
+ return b
626
  }
627
 
628
+ // Detect drag-and-drop
629
+ var dragAndDrop = function() {
630
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
631
+ // couldn't get it to work yet.
632
+ if (ie && ie_version < 9) { return false }
633
+ var div = elt('div');
634
+ return "draggable" in div || "dragDrop" in div
635
+ }();
636
 
637
+ var zwspSupported;
638
+ function zeroWidthElement(measure) {
639
+ if (zwspSupported == null) {
640
+ var test = elt("span", "\u200b");
641
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
642
+ if (measure.firstChild.offsetHeight != 0)
643
+ { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); }
644
  }
645
+ var node = zwspSupported ? elt("span", "\u200b") :
646
+ elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
647
+ node.setAttribute("cm-text", "");
648
+ return node
649
+ }
650
 
651
+ // Feature-detect IE's crummy client rect reporting for bidi text
652
+ var badBidiRects;
653
+ function hasBadBidiRects(measure) {
654
+ if (badBidiRects != null) { return badBidiRects }
655
+ var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
656
+ var r0 = range(txt, 0, 1).getBoundingClientRect();
657
+ var r1 = range(txt, 1, 2).getBoundingClientRect();
658
+ removeChildren(measure);
659
+ if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)
660
+ return badBidiRects = (r1.right - r0.right < 3)
661
+ }
662
 
663
+ // See if "".split is the broken IE version, if so, provide an
664
+ // alternative way to split lines.
665
+ var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) {
666
+ var pos = 0, result = [], l = string.length;
667
+ while (pos <= l) {
668
+ var nl = string.indexOf("\n", pos);
669
+ if (nl == -1) { nl = string.length; }
670
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
671
+ var rt = line.indexOf("\r");
672
+ if (rt != -1) {
673
+ result.push(line.slice(0, rt));
674
+ pos += rt + 1;
675
+ } else {
676
+ result.push(line);
677
+ pos = nl + 1;
678
+ }
679
  }
680
+ return result
681
+ } : function (string) { return string.split(/\r\n?|\n/); };
682
 
683
+ var hasSelection = window.getSelection ? function (te) {
684
+ try { return te.selectionStart != te.selectionEnd }
685
+ catch(e) { return false }
686
+ } : function (te) {
687
+ var range;
688
+ try {range = te.ownerDocument.selection.createRange();}
689
+ catch(e) {}
690
+ if (!range || range.parentElement() != te) { return false }
691
+ return range.compareEndPoints("StartToEnd", range) != 0
692
+ };
693
 
694
+ var hasCopyEvent = (function () {
695
+ var e = elt("div");
696
+ if ("oncopy" in e) { return true }
697
+ e.setAttribute("oncopy", "return;");
698
+ return typeof e.oncopy == "function"
699
+ })();
700
 
701
+ var badZoomedRects = null;
702
+ function hasBadZoomedRects(measure) {
703
+ if (badZoomedRects != null) { return badZoomedRects }
704
+ var node = removeChildrenAndAdd(measure, elt("span", "x"));
705
+ var normal = node.getBoundingClientRect();
706
+ var fromRange = range(node, 0, 1).getBoundingClientRect();
707
+ return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
708
+ }
709
 
710
+ // Known modes, by name and by MIME
711
+ var modes = {}, mimeModes = {};
 
 
712
 
713
+ // Extra arguments are stored as the mode's dependencies, which is
714
+ // used by (legacy) mechanisms like loadmode.js to automatically
715
+ // load a mode. (Preferred mechanism is the require/define calls.)
716
+ function defineMode(name, mode) {
717
+ if (arguments.length > 2)
718
+ { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
719
+ modes[name] = mode;
720
+ }
 
 
721
 
722
+ function defineMIME(mime, spec) {
723
+ mimeModes[mime] = spec;
724
+ }
 
 
725
 
726
+ // Given a MIME type, a {name, ...options} config object, or a name
727
+ // string, return a mode config object.
728
+ function resolveMode(spec) {
729
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
730
+ spec = mimeModes[spec];
731
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
732
+ var found = mimeModes[spec.name];
733
+ if (typeof found == "string") { found = {name: found}; }
734
+ spec = createObj(found, spec);
735
+ spec.name = found.name;
736
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
737
+ return resolveMode("application/xml")
738
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
739
+ return resolveMode("application/json")
740
  }
741
+ if (typeof spec == "string") { return {name: spec} }
742
+ else { return spec || {name: "null"} }
 
 
743
  }
744
 
745
+ // Given a mode spec (anything that resolveMode accepts), find and
746
+ // initialize an actual mode object.
747
+ function getMode(options, spec) {
748
+ spec = resolveMode(spec);
749
+ var mfactory = modes[spec.name];
750
+ if (!mfactory) { return getMode(options, "text/plain") }
751
+ var modeObj = mfactory(options, spec);
752
+ if (modeExtensions.hasOwnProperty(spec.name)) {
753
+ var exts = modeExtensions[spec.name];
754
+ for (var prop in exts) {
755
+ if (!exts.hasOwnProperty(prop)) { continue }
756
+ if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
757
+ modeObj[prop] = exts[prop];
 
 
758
  }
 
 
 
 
 
 
759
  }
760
+ modeObj.name = spec.name;
761
+ if (spec.helperType) { modeObj.helperType = spec.helperType; }
762
+ if (spec.modeProps) { for (var prop$1 in spec.modeProps)
763
+ { modeObj[prop$1] = spec.modeProps[prop$1]; } }
764
 
765
+ return modeObj
 
 
 
 
766
  }
767
 
768
+ // This can be used to attach properties to mode objects from
769
+ // outside the actual mode definition.
770
+ var modeExtensions = {};
771
+ function extendMode(mode, properties) {
772
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
773
+ copyObj(properties, exts);
 
 
 
 
 
774
  }
775
 
776
+ function copyState(mode, state) {
777
+ if (state === true) { return state }
778
+ if (mode.copyState) { return mode.copyState(state) }
779
+ var nstate = {};
780
+ for (var n in state) {
781
+ var val = state[n];
782
+ if (val instanceof Array) { val = val.concat([]); }
783
+ nstate[n] = val;
784
+ }
785
+ return nstate
786
  }
787
 
788
+ // Given a mode and a state (for that mode), find the inner mode and
789
+ // state at the position that the state refers to.
790
+ function innerMode(mode, state) {
791
+ var info;
792
+ while (mode.innerMode) {
793
+ info = mode.innerMode(state);
794
+ if (!info || info.mode == mode) { break }
795
+ state = info.state;
796
+ mode = info.mode;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
797
  }
798
+ return info || {mode: mode, state: state}
799
  }
800
 
801
+ function startState(mode, a1, a2) {
802
+ return mode.startState ? mode.startState(a1, a2) : true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
803
  }
804
 
805
+ // STRING STREAM
 
 
 
 
 
 
806
 
807
+ // Fed to the mode parsers, provides helper functions to make
808
+ // parsers more succinct.
 
 
 
 
 
 
 
809
 
810
+ var StringStream = function(string, tabSize, lineOracle) {
811
+ this.pos = this.start = 0;
812
+ this.string = string;
813
+ this.tabSize = tabSize || 8;
814
+ this.lastColumnPos = this.lastColumnValue = 0;
815
+ this.lineStart = 0;
816
+ this.lineOracle = lineOracle;
817
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
 
819
+ StringStream.prototype.eol = function () {return this.pos >= this.string.length};
820
+ StringStream.prototype.sol = function () {return this.pos == this.lineStart};
821
+ StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
822
+ StringStream.prototype.next = function () {
823
+ if (this.pos < this.string.length)
824
+ { return this.string.charAt(this.pos++) }
825
+ };
826
+ StringStream.prototype.eat = function (match) {
827
+ var ch = this.string.charAt(this.pos);
828
+ var ok;
829
+ if (typeof match == "string") { ok = ch == match; }
830
+ else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
831
+ if (ok) {++this.pos; return ch}
832
+ };
833
+ StringStream.prototype.eatWhile = function (match) {
834
+ var start = this.pos;
835
+ while (this.eat(match)){}
836
+ return this.pos > start
837
+ };
838
+ StringStream.prototype.eatSpace = function () {
839
+ var start = this.pos;
840
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
841
+ return this.pos > start
842
+ };
843
+ StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
844
+ StringStream.prototype.skipTo = function (ch) {
845
+ var found = this.string.indexOf(ch, this.pos);
846
+ if (found > -1) {this.pos = found; return true}
847
+ };
848
+ StringStream.prototype.backUp = function (n) {this.pos -= n;};
849
+ StringStream.prototype.column = function () {
850
+ if (this.lastColumnPos < this.start) {
851
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
852
+ this.lastColumnPos = this.start;
853
  }
854
+ return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
855
+ };
856
+ StringStream.prototype.indentation = function () {
857
+ return countColumn(this.string, null, this.tabSize) -
858
+ (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
859
+ };
860
+ StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
861
+ if (typeof pattern == "string") {
862
+ var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
863
+ var substr = this.string.substr(this.pos, pattern.length);
864
+ if (cased(substr) == cased(pattern)) {
865
+ if (consume !== false) { this.pos += pattern.length; }
866
+ return true
867
+ }
868
+ } else {
869
+ var match = this.string.slice(this.pos).match(pattern);
870
+ if (match && match.index > 0) { return null }
871
+ if (match && consume !== false) { this.pos += match[0].length; }
872
+ return match
873
  }
874
+ };
875
+ StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
876
+ StringStream.prototype.hideFirstChars = function (n, inner) {
877
+ this.lineStart += n;
878
+ try { return inner() }
879
+ finally { this.lineStart -= n; }
880
+ };
881
+ StringStream.prototype.lookAhead = function (n) {
882
+ var oracle = this.lineOracle;
883
+ return oracle && oracle.lookAhead(n)
884
+ };
885
+ StringStream.prototype.baseToken = function () {
886
+ var oracle = this.lineOracle;
887
+ return oracle && oracle.baseToken(this.pos)
888
+ };
889
 
890
+ // Find the line object corresponding to the given line number.
891
+ function getLine(doc, n) {
892
+ n -= doc.first;
893
+ if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") }
894
+ var chunk = doc;
895
+ while (!chunk.lines) {
896
+ for (var i = 0;; ++i) {
897
+ var child = chunk.children[i], sz = child.chunkSize();
898
+ if (n < sz) { chunk = child; break }
899
+ n -= sz;
900
+ }
901
  }
902
+ return chunk.lines[n]
903
  }
904
 
905
+ // Get the part of a document between two positions, as an array of
906
+ // strings.
907
+ function getBetween(doc, start, end) {
908
+ var out = [], n = start.line;
909
+ doc.iter(start.line, end.line + 1, function (line) {
910
+ var text = line.text;
911
+ if (n == end.line) { text = text.slice(0, end.ch); }
912
+ if (n == start.line) { text = text.slice(start.ch); }
913
+ out.push(text);
914
+ ++n;
915
+ });
916
+ return out
917
  }
918
+ // Get the lines between from and to, as array of strings.
919
+ function getLines(doc, from, to) {
920
+ var out = [];
921
+ doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value
922
+ return out
 
 
 
 
 
 
 
 
 
 
 
 
923
  }
924
 
925
+ // Update the height of a line, propagating the height change
926
+ // upwards to parent nodes.
927
+ function updateLineHeight(line, height) {
928
+ var diff = height - line.height;
929
+ if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } }
 
 
 
930
  }
931
 
932
+ // Given a line object, find its line number by walking up through
933
+ // its parent links.
934
+ function lineNo(line) {
935
+ if (line.parent == null) { return null }
936
+ var cur = line.parent, no = indexOf(cur.lines, line);
937
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
938
+ for (var i = 0;; ++i) {
939
+ if (chunk.children[i] == cur) { break }
940
+ no += chunk.children[i].chunkSize();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
941
  }
942
  }
943
+ return no + cur.first
944
  }
945
 
946
+ // Find the line at the given vertical position, using the height
947
+ // information in the document tree.
948
+ function lineAtHeight(chunk, h) {
949
+ var n = chunk.first;
950
+ outer: do {
951
+ for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {
952
+ var child = chunk.children[i$1], ch = child.height;
953
+ if (h < ch) { chunk = child; continue outer }
954
+ h -= ch;
955
+ n += child.chunkSize();
956
+ }
957
+ return n
958
+ } while (!chunk.lines)
959
+ var i = 0;
960
+ for (; i < chunk.lines.length; ++i) {
961
+ var line = chunk.lines[i], lh = line.height;
962
+ if (h < lh) { break }
963
+ h -= lh;
964
  }
965
+ return n + i
966
  }
967
 
968
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}
 
 
 
 
 
 
 
 
 
 
 
969
 
970
+ function lineNumberFor(options, i) {
971
+ return String(options.lineNumberFormatter(i + options.firstLineNumber))
 
 
 
 
972
  }
973
 
974
+ // A Pos instance represents a position within the text.
975
+ function Pos(line, ch, sticky) {
976
+ if ( sticky === void 0 ) sticky = null;
 
 
 
 
 
 
 
 
 
 
 
 
977
 
978
+ if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) }
979
+ this.line = line;
980
+ this.ch = ch;
981
+ this.sticky = sticky;
 
 
 
 
 
 
 
 
 
 
 
 
982
  }
983
 
 
 
 
 
 
 
 
 
984
  // Compare two positions, return 0 if they are the same, a negative
985
  // number when a is less, and a positive number otherwise.
986
+ function cmp(a, b) { return a.line - b.line || a.ch - b.ch }
987
 
988
+ function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 }
 
 
989
 
990
+ function copyPos(x) {return Pos(x.line, x.ch)}
991
+ function maxPos(a, b) { return cmp(a, b) < 0 ? b : a }
992
+ function minPos(a, b) { return cmp(a, b) < 0 ? a : b }
993
 
994
+ // Most of the external API clips given positions to make sure they
995
+ // actually exist within the document.
996
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}
997
+ function clipPos(doc, pos) {
998
+ if (pos.line < doc.first) { return Pos(doc.first, 0) }
999
+ var last = doc.first + doc.size - 1;
1000
+ if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }
1001
+ return clipToLen(pos, getLine(doc, pos.line).text.length)
1002
  }
1003
+ function clipToLen(pos, linelen) {
1004
+ var ch = pos.ch;
1005
+ if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }
1006
+ else if (ch < 0) { return Pos(pos.line, 0) }
1007
+ else { return pos }
1008
+ }
1009
+ function clipPosArray(doc, array) {
1010
+ var out = [];
1011
+ for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); }
1012
+ return out
1013
  }
1014
 
1015
+ var SavedContext = function(state, lookAhead) {
1016
+ this.state = state;
1017
+ this.lookAhead = lookAhead;
1018
+ };
1019
 
1020
+ var Context = function(doc, state, line, lookAhead) {
1021
+ this.state = state;
1022
+ this.doc = doc;
1023
+ this.line = line;
1024
+ this.maxLookAhead = lookAhead || 0;
1025
+ this.baseTokens = null;
1026
+ this.baseTokenPos = 1;
1027
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1028
 
1029
+ Context.prototype.lookAhead = function (n) {
1030
+ var line = this.doc.getLine(this.line + n);
1031
+ if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; }
1032
+ return line
1033
+ };
1034
 
1035
+ Context.prototype.baseToken = function (n) {
1036
+ if (!this.baseTokens) { return null }
1037
+ while (this.baseTokens[this.baseTokenPos] <= n)
1038
+ { this.baseTokenPos += 2; }
1039
+ var type = this.baseTokens[this.baseTokenPos + 1];
1040
+ return {type: type && type.replace(/( |^)overlay .*/, ""),
1041
+ size: this.baseTokens[this.baseTokenPos] - n}
 
 
 
 
1042
  };
1043
 
1044
+ Context.prototype.nextLine = function () {
1045
+ this.line++;
1046
+ if (this.maxLookAhead > 0) { this.maxLookAhead--; }
1047
+ };
 
 
 
 
 
 
 
 
 
 
1048
 
1049
+ Context.fromSaved = function (doc, saved, line) {
1050
+ if (saved instanceof SavedContext)
1051
+ { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) }
1052
+ else
1053
+ { return new Context(doc, copyState(doc.mode, saved), line) }
1054
+ };
1055
 
1056
+ Context.prototype.save = function (copy) {
1057
+ var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state;
1058
+ return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state
1059
+ };
 
 
1060
 
 
 
1061
 
1062
+ // Compute a style array (an array starting with a mode generation
1063
+ // -- for invalidation -- followed by pairs of end positions and
1064
+ // style strings), which is used to highlight the tokens on the
1065
+ // line.
1066
+ function highlightLine(cm, line, context, forceToEnd) {
1067
+ // A styles array always starts with a number identifying the
1068
+ // mode/overlays that it is based on (for easy invalidation).
1069
+ var st = [cm.state.modeGen], lineClasses = {};
1070
+ // Compute the base array of styles
1071
+ runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); },
1072
+ lineClasses, forceToEnd);
1073
+ var state = context.state;
1074
 
1075
+ // Run overlays, adjust style array.
1076
+ var loop = function ( o ) {
1077
+ context.baseTokens = st;
1078
+ var overlay = cm.state.overlays[o], i = 1, at = 0;
1079
+ context.state = true;
1080
+ runMode(cm, line.text, overlay.mode, context, function (end, style) {
1081
+ var start = i;
1082
+ // Ensure there's a token end at the current position, and that i points at it
1083
+ while (at < end) {
1084
+ var i_end = st[i];
1085
+ if (i_end > end)
1086
+ { st.splice(i, 1, end, st[i+1], i_end); }
1087
+ i += 2;
1088
+ at = Math.min(end, i_end);
1089
  }
1090
+ if (!style) { return }
1091
+ if (overlay.opaque) {
1092
+ st.splice(start, i - start, end, "overlay " + style);
1093
+ i = start + 2;
 
 
 
 
 
 
 
 
 
1094
  } else {
1095
+ for (; start < i; start += 2) {
1096
+ var cur = st[start+1];
1097
+ st[start+1] = (cur ? cur + " " : "") + "overlay " + style;
 
 
 
 
 
1098
  }
1099
  }
1100
+ }, lineClasses);
1101
+ context.state = state;
1102
+ context.baseTokens = null;
1103
+ context.baseTokenPos = 1;
1104
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1105
 
1106
+ for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );
 
 
 
 
 
 
 
 
1107
 
1108
+ return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}
1109
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1110
 
1111
+ function getLineStyles(cm, line, updateFrontier) {
1112
+ if (!line.styles || line.styles[0] != cm.state.modeGen) {
1113
+ var context = getContextBefore(cm, lineNo(line));
1114
+ var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state);
1115
+ var result = highlightLine(cm, line, context);
1116
+ if (resetState) { context.state = resetState; }
1117
+ line.stateAfter = context.save(!resetState);
1118
+ line.styles = result.styles;
1119
+ if (result.classes) { line.styleClasses = result.classes; }
1120
+ else if (line.styleClasses) { line.styleClasses = null; }
1121
+ if (updateFrontier === cm.doc.highlightFrontier)
1122
+ { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); }
1123
+ }
1124
+ return line.styles
1125
+ }
1126
 
1127
+ function getContextBefore(cm, n, precise) {
1128
+ var doc = cm.doc, display = cm.display;
1129
+ if (!doc.mode.startState) { return new Context(doc, true, n) }
1130
+ var start = findStartLine(cm, n, precise);
1131
+ var saved = start > doc.first && getLine(doc, start - 1).stateAfter;
1132
+ var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start);
1133
+
1134
+ doc.iter(start, n, function (line) {
1135
+ processLine(cm, line.text, context);
1136
+ var pos = context.line;
1137
+ line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null;
1138
+ context.nextLine();
1139
+ });
1140
+ if (precise) { doc.modeFrontier = context.line; }
1141
+ return context
1142
+ }
1143
 
1144
+ // Lightweight form of highlight -- proceed over this line and
1145
+ // update state, but don't save a style array. Used for lines that
1146
+ // aren't currently visible.
1147
+ function processLine(cm, text, context, startAt) {
1148
+ var mode = cm.doc.mode;
1149
+ var stream = new StringStream(text, cm.options.tabSize, context);
1150
+ stream.start = stream.pos = startAt || 0;
1151
+ if (text == "") { callBlankLine(mode, context.state); }
1152
+ while (!stream.eol()) {
1153
+ readToken(mode, stream, context.state);
1154
+ stream.start = stream.pos;
1155
+ }
1156
+ }
1157
 
1158
+ function callBlankLine(mode, state) {
1159
+ if (mode.blankLine) { return mode.blankLine(state) }
1160
+ if (!mode.innerMode) { return }
1161
+ var inner = innerMode(mode, state);
1162
+ if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }
1163
+ }
1164
 
1165
+ function readToken(mode, stream, state, inner) {
1166
+ for (var i = 0; i < 10; i++) {
1167
+ if (inner) { inner[0] = innerMode(mode, state).mode; }
1168
+ var style = mode.token(stream, state);
1169
+ if (stream.pos > stream.start) { return style }
1170
+ }
1171
+ throw new Error("Mode " + mode.name + " failed to advance stream.")
1172
+ }
1173
 
1174
+ var Token = function(stream, type, state) {
1175
+ this.start = stream.start; this.end = stream.pos;
1176
+ this.string = stream.current();
1177
+ this.type = type || null;
1178
+ this.state = state;
1179
+ };
1180
 
1181
+ // Utility for getTokenAt and getLineTokens
1182
+ function takeToken(cm, pos, precise, asArray) {
1183
+ var doc = cm.doc, mode = doc.mode, style;
1184
+ pos = clipPos(doc, pos);
1185
+ var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise);
1186
+ var stream = new StringStream(line.text, cm.options.tabSize, context), tokens;
1187
+ if (asArray) { tokens = []; }
1188
+ while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
1189
+ stream.start = stream.pos;
1190
+ style = readToken(mode, stream, context.state);
1191
+ if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); }
1192
+ }
1193
+ return asArray ? tokens : new Token(stream, style, context.state)
1194
+ }
1195
 
1196
+ function extractLineClasses(type, output) {
1197
+ if (type) { for (;;) {
1198
+ var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
1199
+ if (!lineClass) { break }
1200
+ type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
1201
+ var prop = lineClass[1] ? "bgClass" : "textClass";
1202
+ if (output[prop] == null)
1203
+ { output[prop] = lineClass[2]; }
1204
+ else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop]))
1205
+ { output[prop] += " " + lineClass[2]; }
1206
+ } }
1207
+ return type
1208
+ }
1209
 
1210
+ // Run the given mode's parser over a line, calling f for each token.
1211
+ function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) {
1212
+ var flattenSpans = mode.flattenSpans;
1213
+ if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; }
1214
+ var curStart = 0, curStyle = null;
1215
+ var stream = new StringStream(text, cm.options.tabSize, context), style;
1216
+ var inner = cm.options.addModeClass && [null];
1217
+ if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); }
1218
+ while (!stream.eol()) {
1219
+ if (stream.pos > cm.options.maxHighlightLength) {
1220
+ flattenSpans = false;
1221
+ if (forceToEnd) { processLine(cm, text, context, stream.pos); }
1222
+ stream.pos = text.length;
1223
+ style = null;
1224
+ } else {
1225
+ style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1226
  }
1227
+ if (inner) {
1228
+ var mName = inner[0].name;
1229
+ if (mName) { style = "m-" + (style ? mName + " " + style : mName); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1230
  }
1231
+ if (!flattenSpans || curStyle != style) {
1232
+ while (curStart < stream.start) {
1233
+ curStart = Math.min(stream.start, curStart + 5000);
1234
+ f(curStart, curStyle);
 
 
 
 
 
 
 
 
 
 
 
 
1235
  }
1236
+ curStyle = style;
1237
  }
1238
+ stream.start = stream.pos;
1239
+ }
1240
+ while (curStart < stream.pos) {
1241
+ // Webkit seems to refuse to render text nodes longer than 57444
1242
+ // characters, and returns inaccurate measurements in nodes
1243
+ // starting around 5000 chars.
1244
+ var pos = Math.min(stream.pos, curStart + 5000);
1245
+ f(pos, curStyle);
1246
+ curStart = pos;
1247
+ }
1248
+ }
1249
 
1250
+ // Finds the line to start with when starting a parse. Tries to
1251
+ // find a line with a stateAfter, so that it can start with a
1252
+ // valid state. If that fails, it returns the line with the
1253
+ // smallest indentation, which tends to need the least context to
1254
+ // parse correctly.
1255
+ function findStartLine(cm, n, precise) {
1256
+ var minindent, minline, doc = cm.doc;
1257
+ var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
1258
+ for (var search = n; search > lim; --search) {
1259
+ if (search <= doc.first) { return doc.first }
1260
+ var line = getLine(doc, search - 1), after = line.stateAfter;
1261
+ if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier))
1262
+ { return search }
1263
+ var indented = countColumn(line.text, null, cm.options.tabSize);
1264
+ if (minline == null || minindent > indented) {
1265
+ minline = search - 1;
1266
+ minindent = indented;
1267
  }
1268
+ }
1269
+ return minline
1270
+ }
1271
 
1272
+ function retreatFrontier(doc, n) {
1273
+ doc.modeFrontier = Math.min(doc.modeFrontier, n);
1274
+ if (doc.highlightFrontier < n - 10) { return }
1275
+ var start = doc.first;
1276
+ for (var line = n - 1; line > start; line--) {
1277
+ var saved = getLine(doc, line).stateAfter;
1278
+ // change is on 3
1279
+ // state on line 1 looked ahead 2 -- so saw 3
1280
+ // test 1 + 2 < 3 should cover this
1281
+ if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) {
1282
+ start = line + 1;
1283
+ break
1284
+ }
1285
+ }
1286
+ doc.highlightFrontier = Math.min(doc.highlightFrontier, start);
1287
+ }
1288
 
1289
+ // Optimize some code when these features are not used.
1290
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
1291
 
1292
+ function seeReadOnlySpans() {
1293
+ sawReadOnlySpans = true;
 
 
 
1294
  }
1295
 
1296
+ function seeCollapsedSpans() {
1297
+ sawCollapsedSpans = true;
1298
+ }
 
 
 
 
 
 
 
 
 
 
 
1299
 
1300
+ // TEXTMARKER SPANS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1301
 
1302
+ function MarkedSpan(marker, from, to) {
1303
+ this.marker = marker;
1304
+ this.from = from; this.to = to;
1305
+ }
1306
 
1307
+ // Search an array of spans for a span matching the given marker.
1308
+ function getMarkedSpanFor(spans, marker) {
1309
+ if (spans) { for (var i = 0; i < spans.length; ++i) {
1310
+ var span = spans[i];
1311
+ if (span.marker == marker) { return span }
1312
+ } }
1313
+ }
1314
+ // Remove a span from an array, returning undefined if no spans are
1315
+ // left (we don't store arrays for lines without spans).
1316
+ function removeMarkedSpan(spans, span) {
1317
+ var r;
1318
+ for (var i = 0; i < spans.length; ++i)
1319
+ { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }
1320
+ return r
1321
+ }
1322
+ // Add a span to a line.
1323
+ function addMarkedSpan(line, span) {
1324
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
1325
+ span.marker.attachLine(line);
1326
+ }
1327
 
1328
+ // Used for the algorithm that adjusts markers for a change in the
1329
+ // document. These functions cut an array of spans at a given
1330
+ // character position, returning an array of remaining chunks (or
1331
+ // undefined if nothing remains).
1332
+ function markedSpansBefore(old, startCh, isInsert) {
1333
+ var nw;
1334
+ if (old) { for (var i = 0; i < old.length; ++i) {
1335
+ var span = old[i], marker = span.marker;
1336
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
1337
+ if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
1338
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh)
1339
+ ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1340
  }
1341
+ } }
1342
+ return nw
1343
+ }
1344
+ function markedSpansAfter(old, endCh, isInsert) {
1345
+ var nw;
1346
+ if (old) { for (var i = 0; i < old.length; ++i) {
1347
+ var span = old[i], marker = span.marker;
1348
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
1349
+ if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
1350
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh)
1351
+ ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
1352
+ span.to == null ? null : span.to - endCh));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1353
  }
1354
+ } }
1355
+ return nw
1356
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1357
 
1358
+ // Given a change object, compute the new set of marker spans that
1359
+ // cover the line in which the change took place. Removes spans
1360
+ // entirely within the change, reconnects spans belonging to the
1361
+ // same marker that appear on both sides of the change, and cuts off
1362
+ // spans partially within the change. Returns an array of span
1363
+ // arrays with one element for each line in (after) the change.
1364
+ function stretchSpansOverChange(doc, change) {
1365
+ if (change.full) { return null }
1366
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
1367
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
1368
+ if (!oldFirst && !oldLast) { return null }
1369
 
1370
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
1371
+ // Get the spans that 'stick out' on both sides
1372
+ var first = markedSpansBefore(oldFirst, startCh, isInsert);
1373
+ var last = markedSpansAfter(oldLast, endCh, isInsert);
 
 
1374
 
1375
+ // Next, merge those two ends
1376
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
1377
+ if (first) {
1378
+ // Fix up .to properties of first
1379
+ for (var i = 0; i < first.length; ++i) {
1380
+ var span = first[i];
1381
+ if (span.to == null) {
1382
+ var found = getMarkedSpanFor(last, span.marker);
1383
+ if (!found) { span.to = startCh; }
1384
+ else if (sameLine) { span.to = found.to == null ? null : found.to + offset; }
1385
  }
1386
  }
1387
+ }
1388
+ if (last) {
1389
+ // Fix up .from in last (or move them into first in case of sameLine)
1390
+ for (var i$1 = 0; i$1 < last.length; ++i$1) {
1391
+ var span$1 = last[i$1];
1392
+ if (span$1.to != null) { span$1.to += offset; }
1393
+ if (span$1.from == null) {
1394
+ var found$1 = getMarkedSpanFor(first, span$1.marker);
1395
+ if (!found$1) {
1396
+ span$1.from = offset;
1397
+ if (sameLine) { (first || (first = [])).push(span$1); }
1398
+ }
1399
+ } else {
1400
+ span$1.from += offset;
1401
+ if (sameLine) { (first || (first = [])).push(span$1); }
1402
+ }
1403
+ }
1404
+ }
1405
+ // Make sure we didn't create any zero-length spans
1406
+ if (first) { first = clearEmptySpans(first); }
1407
+ if (last && last != first) { last = clearEmptySpans(last); }
1408
 
1409
+ var newMarkers = [first];
1410
+ if (!sameLine) {
1411
+ // Fill gap with whole-line-spans
1412
+ var gap = change.text.length - 2, gapMarkers;
1413
+ if (gap > 0 && first)
1414
+ { for (var i$2 = 0; i$2 < first.length; ++i$2)
1415
+ { if (first[i$2].to == null)
1416
+ { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } }
1417
+ for (var i$3 = 0; i$3 < gap; ++i$3)
1418
+ { newMarkers.push(gapMarkers); }
1419
+ newMarkers.push(last);
1420
+ }
1421
+ return newMarkers
1422
+ }
1423
 
1424
+ // Remove spans that are empty and don't have a clearWhenEmpty
1425
+ // option of false.
1426
+ function clearEmptySpans(spans) {
1427
+ for (var i = 0; i < spans.length; ++i) {
1428
+ var span = spans[i];
1429
+ if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
1430
+ { spans.splice(i--, 1); }
1431
+ }
1432
+ if (!spans.length) { return null }
1433
+ return spans
1434
+ }
1435
+
1436
+ // Used to 'clip' out readOnly ranges when making a change.
1437
+ function removeReadOnlyRanges(doc, from, to) {
1438
+ var markers = null;
1439
+ doc.iter(from.line, to.line + 1, function (line) {
1440
+ if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
1441
+ var mark = line.markedSpans[i].marker;
1442
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
1443
+ { (markers || (markers = [])).push(mark); }
1444
+ } }
1445
+ });
1446
+ if (!markers) { return null }
1447
+ var parts = [{from: from, to: to}];
1448
+ for (var i = 0; i < markers.length; ++i) {
1449
+ var mk = markers[i], m = mk.find(0);
1450
+ for (var j = 0; j < parts.length; ++j) {
1451
+ var p = parts[j];
1452
+ if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }
1453
+ var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
1454
+ if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
1455
+ { newParts.push({from: p.from, to: m.from}); }
1456
+ if (dto > 0 || !mk.inclusiveRight && !dto)
1457
+ { newParts.push({from: m.to, to: p.to}); }
1458
+ parts.splice.apply(parts, newParts);
1459
+ j += newParts.length - 3;
1460
  }
1461
+ }
1462
+ return parts
1463
+ }
1464
 
1465
+ // Connect or disconnect spans from a line.
1466
+ function detachMarkedSpans(line) {
1467
+ var spans = line.markedSpans;
1468
+ if (!spans) { return }
1469
+ for (var i = 0; i < spans.length; ++i)
1470
+ { spans[i].marker.detachLine(line); }
1471
+ line.markedSpans = null;
1472
+ }
1473
+ function attachMarkedSpans(line, spans) {
1474
+ if (!spans) { return }
1475
+ for (var i = 0; i < spans.length; ++i)
1476
+ { spans[i].marker.attachLine(line); }
1477
+ line.markedSpans = spans;
1478
+ }
1479
 
1480
+ // Helpers used when computing which overlapping collapsed span
1481
+ // counts as the larger one.
1482
+ function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }
1483
+ function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1484
 
1485
+ // Returns a number indicating which of two overlapping collapsed
1486
+ // spans is larger (and thus includes the other). Falls back to
1487
+ // comparing ids when the spans cover exactly the same range.
1488
+ function compareCollapsedMarkers(a, b) {
1489
+ var lenDiff = a.lines.length - b.lines.length;
1490
+ if (lenDiff != 0) { return lenDiff }
1491
+ var aPos = a.find(), bPos = b.find();
1492
+ var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
1493
+ if (fromCmp) { return -fromCmp }
1494
+ var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
1495
+ if (toCmp) { return toCmp }
1496
+ return b.id - a.id
1497
+ }
 
 
 
 
1498
 
1499
+ // Find out whether a line ends or starts in a collapsed span. If
1500
+ // so, return the marker for that span.
1501
+ function collapsedSpanAtSide(line, start) {
1502
+ var sps = sawCollapsedSpans && line.markedSpans, found;
1503
+ if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
1504
+ sp = sps[i];
1505
+ if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
1506
+ (!found || compareCollapsedMarkers(found, sp.marker) < 0))
1507
+ { found = sp.marker; }
1508
+ } }
1509
+ return found
1510
+ }
1511
+ function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
1512
+ function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }
1513
 
1514
+ function collapsedSpanAround(line, ch) {
1515
+ var sps = sawCollapsedSpans && line.markedSpans, found;
1516
+ if (sps) { for (var i = 0; i < sps.length; ++i) {
1517
+ var sp = sps[i];
1518
+ if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) &&
1519
+ (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; }
1520
+ } }
1521
+ return found
1522
+ }
1523
 
1524
+ // Test whether there exists a collapsed span that partially
1525
+ // overlaps (covers the start or end, but not both) of a new span.
1526
+ // Such overlap is not allowed.
1527
+ function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
1528
+ var line = getLine(doc, lineNo);
1529
+ var sps = sawCollapsedSpans && line.markedSpans;
1530
+ if (sps) { for (var i = 0; i < sps.length; ++i) {
1531
+ var sp = sps[i];
1532
+ if (!sp.marker.collapsed) { continue }
1533
+ var found = sp.marker.find(0);
1534
+ var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
1535
+ var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
1536
+ if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }
1537
+ if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
1538
+ fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
1539
+ { return true }
1540
+ } }
1541
+ }
1542
 
1543
+ // A visual line is a line as drawn on the screen. Folding, for
1544
+ // example, can cause multiple logical lines to appear on the same
1545
+ // visual line. This finds the start of the visual line that the
1546
+ // given line is part of (usually that is the line itself).
1547
+ function visualLine(line) {
1548
+ var merged;
1549
+ while (merged = collapsedSpanAtStart(line))
1550
+ { line = merged.find(-1, true).line; }
1551
+ return line
1552
+ }
1553
 
1554
+ function visualLineEnd(line) {
1555
+ var merged;
1556
+ while (merged = collapsedSpanAtEnd(line))
1557
+ { line = merged.find(1, true).line; }
1558
+ return line
1559
+ }
1560
 
1561
+ // Returns an array of logical lines that continue the visual line
1562
+ // started by the argument, or undefined if there are no such lines.
1563
+ function visualLineContinued(line) {
1564
+ var merged, lines;
1565
+ while (merged = collapsedSpanAtEnd(line)) {
1566
+ line = merged.find(1, true).line
1567
+ ;(lines || (lines = [])).push(line);
1568
  }
1569
+ return lines
 
 
1570
  }
1571
 
1572
+ // Get the line number of the start of the visual line that the
1573
+ // given line number is part of.
1574
+ function visualLineNo(doc, lineN) {
1575
+ var line = getLine(doc, lineN), vis = visualLine(line);
1576
+ if (line == vis) { return lineN }
1577
+ return lineNo(vis)
1578
+ }
1579
 
1580
+ // Get the line number of the start of the next visual line after
1581
+ // the given line.
1582
+ function visualLineEndNo(doc, lineN) {
1583
+ if (lineN > doc.lastLine()) { return lineN }
1584
+ var line = getLine(doc, lineN), merged;
1585
+ if (!lineIsHidden(doc, line)) { return lineN }
1586
+ while (merged = collapsedSpanAtEnd(line))
1587
+ { line = merged.find(1, true).line; }
1588
+ return lineNo(line) + 1
1589
+ }
1590
+
1591
+ // Compute whether a line is hidden. Lines count as hidden when they
1592
+ // are part of a visual line that starts with another line, or when
1593
+ // they are entirely covered by collapsed, non-widget span.
1594
+ function lineIsHidden(doc, line) {
1595
+ var sps = sawCollapsedSpans && line.markedSpans;
1596
+ if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
1597
+ sp = sps[i];
1598
+ if (!sp.marker.collapsed) { continue }
1599
+ if (sp.from == null) { return true }
1600
+ if (sp.marker.widgetNode) { continue }
1601
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
1602
+ { return true }
1603
+ } }
1604
+ }
1605
+ function lineIsHiddenInner(doc, line, span) {
1606
+ if (span.to == null) {
1607
+ var end = span.marker.find(1, true);
1608
+ return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))
1609
  }
1610
+ if (span.marker.inclusiveRight && span.to == line.text.length)
1611
+ { return true }
1612
+ for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {
1613
+ sp = line.markedSpans[i];
1614
+ if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
1615
+ (sp.to == null || sp.to != span.from) &&
1616
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
1617
+ lineIsHiddenInner(doc, line, sp)) { return true }
1618
  }
1619
  }
1620
 
1621
+ // Find the height above the given line.
1622
+ function heightAtLine(lineObj) {
1623
+ lineObj = visualLine(lineObj);
1624
+
1625
+ var h = 0, chunk = lineObj.parent;
1626
+ for (var i = 0; i < chunk.lines.length; ++i) {
1627
+ var line = chunk.lines[i];
1628
+ if (line == lineObj) { break }
1629
+ else { h += line.height; }
1630
+ }
1631
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
1632
+ for (var i$1 = 0; i$1 < p.children.length; ++i$1) {
1633
+ var cur = p.children[i$1];
1634
+ if (cur == chunk) { break }
1635
+ else { h += cur.height; }
1636
  }
1637
  }
1638
+ return h
1639
+ }
1640
 
1641
+ // Compute the character length of a line, taking into account
1642
+ // collapsed ranges (see markText) that might hide parts, and join
1643
+ // other lines onto it.
1644
+ function lineLength(line) {
1645
+ if (line.height == 0) { return 0 }
1646
+ var len = line.text.length, merged, cur = line;
1647
+ while (merged = collapsedSpanAtStart(cur)) {
1648
+ var found = merged.find(0, true);
1649
+ cur = found.from.line;
1650
+ len += found.from.ch - found.to.ch;
1651
  }
1652
+ cur = line;
1653
+ while (merged = collapsedSpanAtEnd(cur)) {
1654
+ var found$1 = merged.find(0, true);
1655
+ len -= cur.text.length - found$1.from.ch;
1656
+ cur = found$1.to.line;
1657
+ len += cur.text.length - found$1.to.ch;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1658
  }
1659
+ return len
1660
  }
1661
 
1662
+ // Find the longest line in the document.
1663
+ function findMaxLine(cm) {
1664
+ var d = cm.display, doc = cm.doc;
1665
+ d.maxLine = getLine(doc, doc.first);
1666
+ d.maxLineLength = lineLength(d.maxLine);
1667
+ d.maxLineChanged = true;
1668
+ doc.iter(function (line) {
1669
+ var len = lineLength(line);
1670
+ if (len > d.maxLineLength) {
1671
+ d.maxLineLength = len;
1672
+ d.maxLine = line;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1673
  }
1674
+ });
 
 
 
 
 
 
1675
  }
1676
 
1677
+ // LINE DATA STRUCTURE
 
 
 
 
 
 
 
 
 
 
 
 
1678
 
1679
+ // Line objects. These hold state related to a line, including
1680
+ // highlighting info (the styles array).
1681
+ var Line = function(text, markedSpans, estimateHeight) {
1682
+ this.text = text;
1683
+ attachMarkedSpans(this, markedSpans);
1684
+ this.height = estimateHeight ? estimateHeight(this) : 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1685
  };
1686
 
1687
+ Line.prototype.lineNo = function () { return lineNo(this) };
1688
+ eventMixin(Line);
 
 
 
 
 
 
 
 
 
1689
 
1690
+ // Change the content (text, markers) of a line. Automatically
1691
+ // invalidates cached information and tries to re-estimate the
1692
+ // line's height.
1693
+ function updateLine(line, text, markedSpans, estimateHeight) {
1694
+ line.text = text;
1695
+ if (line.stateAfter) { line.stateAfter = null; }
1696
+ if (line.styles) { line.styles = null; }
1697
+ if (line.order != null) { line.order = null; }
1698
+ detachMarkedSpans(line);
1699
+ attachMarkedSpans(line, markedSpans);
1700
+ var estHeight = estimateHeight ? estimateHeight(line) : 1;
1701
+ if (estHeight != line.height) { updateLineHeight(line, estHeight); }
 
 
 
 
 
1702
  }
1703
 
1704
+ // Detach a line from the document tree and its markers.
1705
+ function cleanUpLine(line) {
1706
+ line.parent = null;
1707
+ detachMarkedSpans(line);
1708
  }
1709
 
1710
+ // Convert a style as returned by a mode (either null, or a string
1711
+ // containing one or more styles) to a CSS style. This is cached,
1712
+ // and also looks for line-wide styles.
1713
+ var styleToClassCache = {}, styleToClassCacheWithMode = {};
1714
+ function interpretTokenStyle(style, options) {
1715
+ if (!style || /^\s*$/.test(style)) { return null }
1716
+ var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
1717
+ return cache[style] ||
1718
+ (cache[style] = style.replace(/\S+/g, "cm-$&"))
 
 
 
 
 
 
 
 
 
 
1719
  }
1720
 
1721
+ // Render the DOM representation of the text of a line. Also builds
1722
+ // up a 'line map', which points at the DOM nodes that represent
1723
+ // specific stretches of text, and is used by the measuring code.
1724
+ // The returned object contains the DOM node, this map, and
1725
+ // information about line-wide styles that were set by the mode.
1726
+ function buildLineContent(cm, lineView) {
1727
+ // The padding-right forces the element to have a 'border', which
1728
+ // is needed on Webkit to be able to get line-level bounding
1729
+ // rectangles for it (in measureChar).
1730
+ var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null);
1731
+ var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content,
1732
+ col: 0, pos: 0, cm: cm,
1733
+ trailingSpace: false,
1734
+ splitSpaces: cm.getOption("lineWrapping")};
1735
+ lineView.measure = {};
1736
+
1737
+ // Iterate over the logical lines that make up this visual line.
1738
+ for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
1739
+ var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0);
1740
+ builder.pos = 0;
1741
+ builder.addToken = buildToken;
1742
+ // Optionally wire in some hacks into the token-rendering
1743
+ // algorithm, to deal with browser quirks.
1744
+ if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction)))
1745
+ { builder.addToken = buildTokenBadBidi(builder.addToken, order); }
1746
+ builder.map = [];
1747
+ var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
1748
+ insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
1749
+ if (line.styleClasses) {
1750
+ if (line.styleClasses.bgClass)
1751
+ { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); }
1752
+ if (line.styleClasses.textClass)
1753
+ { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); }
1754
+ }
1755
 
1756
+ // Ensure at least a single node is present, for measuring.
1757
+ if (builder.map.length == 0)
1758
+ { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); }
1759
 
1760
+ // Store the map and a cache object for the current logical line
1761
+ if (i == 0) {
1762
+ lineView.measure.map = builder.map;
1763
+ lineView.measure.cache = {};
1764
+ } else {
1765
+ (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)
1766
+ ;(lineView.measure.caches || (lineView.measure.caches = [])).push({});
 
 
 
 
 
 
 
 
1767
  }
 
 
 
1768
  }
 
 
 
 
 
 
1769
 
1770
+ // See issue #2901
1771
+ if (webkit) {
1772
+ var last = builder.content.lastChild;
1773
+ if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
1774
+ { builder.content.className = "cm-tab-wrap-hack"; }
1775
+ }
 
 
1776
 
1777
+ signal(cm, "renderLine", cm, lineView.line, builder.pre);
1778
+ if (builder.pre.className)
1779
+ { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); }
 
 
 
1780
 
1781
+ return builder
 
 
1782
  }
1783
 
1784
+ function defaultSpecialCharPlaceholder(ch) {
1785
+ var token = elt("span", "\u2022", "cm-invalidchar");
1786
+ token.title = "\\u" + ch.charCodeAt(0).toString(16);
1787
+ token.setAttribute("aria-label", token.title);
1788
+ return token
 
 
 
 
 
 
 
 
 
 
 
1789
  }
1790
 
1791
+ // Build up the DOM representation for a single token, and add it to
1792
+ // the line map. Takes care to render special characters separately.
1793
+ function buildToken(builder, text, style, startStyle, endStyle, css, attributes) {
1794
+ if (!text) { return }
1795
+ var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text;
1796
+ var special = builder.cm.state.specialChars, mustWrap = false;
1797
+ var content;
1798
+ if (!special.test(text)) {
1799
+ builder.col += text.length;
1800
+ content = document.createTextNode(displayText);
1801
+ builder.map.push(builder.pos, builder.pos + text.length, content);
1802
+ if (ie && ie_version < 9) { mustWrap = true; }
1803
+ builder.pos += text.length;
1804
  } else {
1805
+ content = document.createDocumentFragment();
1806
+ var pos = 0;
1807
+ while (true) {
1808
+ special.lastIndex = pos;
1809
+ var m = special.exec(text);
1810
+ var skipped = m ? m.index - pos : text.length - pos;
1811
+ if (skipped) {
1812
+ var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
1813
+ if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); }
1814
+ else { content.appendChild(txt); }
1815
+ builder.map.push(builder.pos, builder.pos + skipped, txt);
1816
+ builder.col += skipped;
1817
+ builder.pos += skipped;
1818
+ }
1819
+ if (!m) { break }
1820
+ pos += skipped + 1;
1821
+ var txt$1 = (void 0);
1822
+ if (m[0] == "\t") {
1823
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
1824
+ txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
1825
+ txt$1.setAttribute("role", "presentation");
1826
+ txt$1.setAttribute("cm-text", "\t");
1827
+ builder.col += tabWidth;
1828
+ } else if (m[0] == "\r" || m[0] == "\n") {
1829
+ txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
1830
+ txt$1.setAttribute("cm-text", m[0]);
1831
+ builder.col += 1;
1832
+ } else {
1833
+ txt$1 = builder.cm.options.specialCharPlaceholder(m[0]);
1834
+ txt$1.setAttribute("cm-text", m[0]);
1835
+ if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); }
1836
+ else { content.appendChild(txt$1); }
1837
+ builder.col += 1;
1838
+ }
1839
+ builder.map.push(builder.pos, builder.pos + 1, txt$1);
1840
+ builder.pos++;
1841
+ }
1842
+ }
1843
+ builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;
1844
+ if (style || startStyle || endStyle || mustWrap || css || attributes) {
1845
+ var fullStyle = style || "";
1846
+ if (startStyle) { fullStyle += startStyle; }
1847
+ if (endStyle) { fullStyle += endStyle; }
1848
+ var token = elt("span", [content], fullStyle, css);
1849
+ if (attributes) {
1850
+ for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class")
1851
+ { token.setAttribute(attr, attributes[attr]); } }
1852
+ }
1853
+ return builder.content.appendChild(token)
1854
  }
1855
+ builder.content.appendChild(content);
1856
  }
1857
 
1858
+ // Change some spaces to NBSP to prevent the browser from collapsing
1859
+ // trailing spaces at the end of a line when rendering text (issue #1362).
1860
+ function splitSpaces(text, trailingBefore) {
1861
+ if (text.length > 1 && !/ /.test(text)) { return text }
1862
+ var spaceBefore = trailingBefore, result = "";
1863
+ for (var i = 0; i < text.length; i++) {
1864
+ var ch = text.charAt(i);
1865
+ if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
1866
+ { ch = "\u00a0"; }
1867
+ result += ch;
1868
+ spaceBefore = ch == " ";
1869
+ }
1870
+ return result
1871
  }
1872
 
1873
+ // Work around nonsense dimensions being reported for stretches of
1874
+ // right-to-left text.
1875
+ function buildTokenBadBidi(inner, order) {
1876
+ return function (builder, text, style, startStyle, endStyle, css, attributes) {
1877
+ style = style ? style + " cm-force-border" : "cm-force-border";
1878
+ var start = builder.pos, end = start + text.length;
1879
+ for (;;) {
1880
+ // Find the part that overlaps with the start of this text
1881
+ var part = (void 0);
1882
+ for (var i = 0; i < order.length; i++) {
1883
+ part = order[i];
1884
+ if (part.to > start && part.from <= start) { break }
1885
+ }
1886
+ if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) }
1887
+ inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes);
1888
+ startStyle = null;
1889
+ text = text.slice(part.to - start);
1890
+ start = part.to;
1891
+ }
 
1892
  }
 
1893
  }
1894
 
1895
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
1896
+ var widget = !ignoreWidget && marker.widgetNode;
1897
+ if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); }
1898
+ if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
1899
+ if (!widget)
1900
+ { widget = builder.content.appendChild(document.createElement("span")); }
1901
+ widget.setAttribute("cm-marker", marker.id);
1902
+ }
1903
+ if (widget) {
1904
+ builder.cm.display.input.setUneditable(widget);
1905
+ builder.content.appendChild(widget);
1906
+ }
1907
+ builder.pos += size;
1908
+ builder.trailingSpace = false;
1909
  }
1910
 
1911
+ // Outputs a number of spans to make up a line, taking highlighting
1912
+ // and marked text into account.
1913
+ function insertLineContent(line, builder, styles) {
1914
+ var spans = line.markedSpans, allText = line.text, at = 0;
1915
+ if (!spans) {
1916
+ for (var i$1 = 1; i$1 < styles.length; i$1+=2)
1917
+ { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); }
1918
+ return
 
 
 
 
1919
  }
 
 
1920
 
1921
+ var len = allText.length, pos = 0, i = 1, text = "", style, css;
1922
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes;
1923
+ for (;;) {
1924
+ if (nextChange == pos) { // Update current marker set
1925
+ spanStyle = spanEndStyle = spanStartStyle = css = "";
1926
+ attributes = null;
1927
+ collapsed = null; nextChange = Infinity;
1928
+ var foundBookmarks = [], endStyles = (void 0);
1929
+ for (var j = 0; j < spans.length; ++j) {
1930
+ var sp = spans[j], m = sp.marker;
1931
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
1932
+ foundBookmarks.push(m);
1933
+ } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
1934
+ if (sp.to != null && sp.to != pos && nextChange > sp.to) {
1935
+ nextChange = sp.to;
1936
+ spanEndStyle = "";
 
 
1937
  }
1938
+ if (m.className) { spanStyle += " " + m.className; }
1939
+ if (m.css) { css = (css ? css + ";" : "") + m.css; }
1940
+ if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; }
1941
+ if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); }
1942
+ // support for the old title property
1943
+ // https://github.com/codemirror/CodeMirror/pull/5673
1944
+ if (m.title) { (attributes || (attributes = {})).title = m.title; }
1945
+ if (m.attributes) {
1946
+ for (var attr in m.attributes)
1947
+ { (attributes || (attributes = {}))[attr] = m.attributes[attr]; }
 
 
 
 
 
 
 
 
 
 
 
 
1948
  }
1949
+ if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
1950
+ { collapsed = sp; }
1951
+ } else if (sp.from > pos && nextChange > sp.from) {
1952
+ nextChange = sp.from;
1953
  }
1954
  }
1955
+ if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)
1956
+ { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } }
1957
+
1958
+ if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)
1959
+ { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } }
1960
+ if (collapsed && (collapsed.from || 0) == pos) {
1961
+ buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
1962
+ collapsed.marker, collapsed.from == null);
1963
+ if (collapsed.to == null) { return }
1964
+ if (collapsed.to == pos) { collapsed = false; }
1965
+ }
1966
+ }
1967
+ if (pos >= len) { break }
1968
+
1969
+ var upto = Math.min(len, nextChange);
1970
+ while (true) {
1971
+ if (text) {
1972
+ var end = pos + text.length;
1973
+ if (!collapsed) {
1974
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text;
1975
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
1976
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes);
1977
+ }
1978
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
1979
+ pos = end;
1980
+ spanStartStyle = "";
1981
+ }
1982
+ text = allText.slice(at, at = styles[i++]);
1983
+ style = interpretTokenStyle(styles[i++], builder.cm.options);
1984
  }
 
1985
  }
1986
  }
1987
 
 
1988
 
1989
+ // These objects are used to represent the visible (currently drawn)
1990
+ // part of the document. A LineView may correspond to multiple
1991
+ // logical lines, if those are connected by collapsed ranges.
1992
+ function LineView(doc, line, lineN) {
1993
+ // The starting line
1994
+ this.line = line;
1995
+ // Continuing lines, if any
1996
+ this.rest = visualLineContinued(line);
1997
+ // Number of logical lines in this visual line
1998
+ this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
1999
+ this.node = this.text = null;
2000
+ this.hidden = lineIsHidden(doc, line);
2001
  }
2002
 
2003
+ // Create a range of LineView objects for the given lines.
2004
+ function buildViewArray(cm, from, to) {
2005
+ var array = [], nextPos;
2006
+ for (var pos = from; pos < to; pos = nextPos) {
2007
+ var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
2008
+ nextPos = pos + view.size;
2009
+ array.push(view);
 
 
 
 
 
 
2010
  }
2011
+ return array
2012
  }
2013
 
2014
+ var operationGroup = null;
 
 
 
 
 
 
 
2015
 
2016
+ function pushOperation(op) {
2017
+ if (operationGroup) {
2018
+ operationGroup.ops.push(op);
2019
+ } else {
2020
+ op.ownsGroup = operationGroup = {
2021
+ ops: [op],
2022
+ delayedCallbacks: []
2023
+ };
2024
  }
2025
  }
2026
 
2027
+ function fireCallbacksForOps(group) {
2028
+ // Calls delayed callbacks and cursorActivity handlers until no
2029
+ // new ones appear
2030
+ var callbacks = group.delayedCallbacks, i = 0;
2031
+ do {
2032
+ for (; i < callbacks.length; i++)
2033
+ { callbacks[i].call(null); }
2034
+ for (var j = 0; j < group.ops.length; j++) {
2035
+ var op = group.ops[j];
2036
+ if (op.cursorActivityHandlers)
2037
+ { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
2038
+ { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } }
 
 
 
 
 
 
 
 
 
 
2039
  }
2040
+ } while (i < callbacks.length)
2041
+ }
2042
 
2043
+ function finishOperation(op, endCb) {
2044
+ var group = op.ownsGroup;
2045
+ if (!group) { return }
2046
+
2047
+ try { fireCallbacksForOps(group); }
2048
+ finally {
2049
+ operationGroup = null;
2050
+ endCb(group);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2051
  }
2052
+ }
2053
 
2054
+ var orphanDelayedCallbacks = null;
2055
+
2056
+ // Often, we want to signal events at a point where we are in the
2057
+ // middle of some work, but don't want the handler to start calling
2058
+ // other methods on the editor, which might be in an inconsistent
2059
+ // state or simply not expect any other events to happen.
2060
+ // signalLater looks whether there are any handlers, and schedules
2061
+ // them to be executed when the last operation ends, or, if no
2062
+ // operation is active, when a timeout fires.
2063
+ function signalLater(emitter, type /*, values...*/) {
2064
+ var arr = getHandlers(emitter, type);
2065
+ if (!arr.length) { return }
2066
+ var args = Array.prototype.slice.call(arguments, 2), list;
2067
+ if (operationGroup) {
2068
+ list = operationGroup.delayedCallbacks;
2069
+ } else if (orphanDelayedCallbacks) {
2070
+ list = orphanDelayedCallbacks;
2071
  } else {
2072
+ list = orphanDelayedCallbacks = [];
2073
+ setTimeout(fireOrphanDelayed, 0);
 
 
 
 
 
 
 
 
 
 
 
 
2074
  }
2075
+ var loop = function ( i ) {
2076
+ list.push(function () { return arr[i].apply(null, args); });
2077
+ };
2078
 
2079
+ for (var i = 0; i < arr.length; ++i)
2080
+ loop( i );
2081
  }
2082
 
2083
+ function fireOrphanDelayed() {
2084
+ var delayed = orphanDelayedCallbacks;
2085
+ orphanDelayedCallbacks = null;
2086
+ for (var i = 0; i < delayed.length; ++i) { delayed[i](); }
 
 
 
 
 
 
 
 
 
2087
  }
2088
 
2089
+ // When an aspect of a line changes, a string is added to
2090
+ // lineView.changes. This updates the relevant part of the line's
2091
+ // DOM structure.
2092
+ function updateLineForChanges(cm, lineView, lineN, dims) {
2093
+ for (var j = 0; j < lineView.changes.length; j++) {
2094
+ var type = lineView.changes[j];
2095
+ if (type == "text") { updateLineText(cm, lineView); }
2096
+ else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); }
2097
+ else if (type == "class") { updateLineClasses(cm, lineView); }
2098
+ else if (type == "widget") { updateLineWidgets(cm, lineView, dims); }
2099
+ }
2100
+ lineView.changes = null;
2101
  }
2102
 
2103
+ // Lines with gutter elements, widgets or a background class need to
2104
+ // be wrapped, and have the extra elements added to the wrapper div
2105
+ function ensureLineWrapped(lineView) {
2106
+ if (lineView.node == lineView.text) {
2107
+ lineView.node = elt("div", null, null, "position: relative");
2108
+ if (lineView.text.parentNode)
2109
+ { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); }
2110
+ lineView.node.appendChild(lineView.text);
2111
+ if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; }
2112
+ }
2113
+ return lineView.node
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2114
  }
2115
 
2116
+ function updateLineBackground(cm, lineView) {
2117
+ var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
2118
+ if (cls) { cls += " CodeMirror-linebackground"; }
2119
+ if (lineView.background) {
2120
+ if (cls) { lineView.background.className = cls; }
2121
+ else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
2122
+ } else if (cls) {
2123
+ var wrap = ensureLineWrapped(lineView);
2124
+ lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
2125
+ cm.display.input.setUneditable(lineView.background);
2126
+ }
2127
+ }
2128
+
2129
+ // Wrapper around buildLineContent which will reuse the structure
2130
+ // in display.externalMeasured when possible.
2131
+ function getLineContent(cm, lineView) {
2132
+ var ext = cm.display.externalMeasured;
2133
+ if (ext && ext.line == lineView.line) {
2134
+ cm.display.externalMeasured = null;
2135
+ lineView.measure = ext.measure;
2136
+ return ext.built
2137
+ }
2138
+ return buildLineContent(cm, lineView)
2139
+ }
2140
+
2141
+ // Redraw the line's text. Interacts with the background and text
2142
+ // classes because the mode may output tokens that influence these
2143
+ // classes.
2144
+ function updateLineText(cm, lineView) {
2145
+ var cls = lineView.text.className;
2146
+ var built = getLineContent(cm, lineView);
2147
+ if (lineView.text == lineView.node) { lineView.node = built.pre; }
2148
+ lineView.text.parentNode.replaceChild(built.pre, lineView.text);
2149
+ lineView.text = built.pre;
2150
+ if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
2151
+ lineView.bgClass = built.bgClass;
2152
+ lineView.textClass = built.textClass;
2153
+ updateLineClasses(cm, lineView);
2154
+ } else if (cls) {
2155
+ lineView.text.className = cls;
2156
+ }
2157
+ }
2158
+
2159
+ function updateLineClasses(cm, lineView) {
2160
+ updateLineBackground(cm, lineView);
2161
+ if (lineView.line.wrapClass)
2162
+ { ensureLineWrapped(lineView).className = lineView.line.wrapClass; }
2163
+ else if (lineView.node != lineView.text)
2164
+ { lineView.node.className = ""; }
2165
+ var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
2166
+ lineView.text.className = textClass || "";
2167
+ }
2168
+
2169
+ function updateLineGutter(cm, lineView, lineN, dims) {
2170
+ if (lineView.gutter) {
2171
+ lineView.node.removeChild(lineView.gutter);
2172
+ lineView.gutter = null;
2173
+ }
2174
+ if (lineView.gutterBackground) {
2175
+ lineView.node.removeChild(lineView.gutterBackground);
2176
+ lineView.gutterBackground = null;
2177
+ }
2178
+ if (lineView.line.gutterClass) {
2179
+ var wrap = ensureLineWrapped(lineView);
2180
+ lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
2181
+ ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px"));
2182
+ cm.display.input.setUneditable(lineView.gutterBackground);
2183
+ wrap.insertBefore(lineView.gutterBackground, lineView.text);
2184
+ }
2185
+ var markers = lineView.line.gutterMarkers;
2186
+ if (cm.options.lineNumbers || markers) {
2187
+ var wrap$1 = ensureLineWrapped(lineView);
2188
+ var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"));
2189
+ cm.display.input.setUneditable(gutterWrap);
2190
+ wrap$1.insertBefore(gutterWrap, lineView.text);
2191
+ if (lineView.line.gutterClass)
2192
+ { gutterWrap.className += " " + lineView.line.gutterClass; }
2193
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
2194
+ { lineView.lineNumber = gutterWrap.appendChild(
2195
+ elt("div", lineNumberFor(cm.options, lineN),
2196
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
2197
+ ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); }
2198
+ if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) {
2199
+ var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id];
2200
+ if (found)
2201
+ { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt",
2202
+ ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); }
2203
+ } }
2204
+ }
2205
+ }
2206
+
2207
+ function updateLineWidgets(cm, lineView, dims) {
2208
+ if (lineView.alignable) { lineView.alignable = null; }
2209
+ var isWidget = classTest("CodeMirror-linewidget");
2210
+ for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {
2211
+ next = node.nextSibling;
2212
+ if (isWidget.test(node.className)) { lineView.node.removeChild(node); }
2213
+ }
2214
+ insertLineWidgets(cm, lineView, dims);
2215
+ }
2216
+
2217
+ // Build a line's DOM representation from scratch
2218
+ function buildLineElement(cm, lineView, lineN, dims) {
2219
+ var built = getLineContent(cm, lineView);
2220
+ lineView.text = lineView.node = built.pre;
2221
+ if (built.bgClass) { lineView.bgClass = built.bgClass; }
2222
+ if (built.textClass) { lineView.textClass = built.textClass; }
2223
+
2224
+ updateLineClasses(cm, lineView);
2225
+ updateLineGutter(cm, lineView, lineN, dims);
2226
+ insertLineWidgets(cm, lineView, dims);
2227
+ return lineView.node
2228
+ }
2229
+
2230
+ // A lineView may contain multiple logical lines (when merged by
2231
+ // collapsed spans). The widgets for all of them need to be drawn.
2232
+ function insertLineWidgets(cm, lineView, dims) {
2233
+ insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
2234
+ if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
2235
+ { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } }
2236
+ }
2237
+
2238
+ function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
2239
+ if (!line.widgets) { return }
2240
+ var wrap = ensureLineWrapped(lineView);
2241
+ for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
2242
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : ""));
2243
+ if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); }
2244
+ positionLineWidget(widget, node, lineView, dims);
2245
+ cm.display.input.setUneditable(node);
2246
+ if (allowAbove && widget.above)
2247
+ { wrap.insertBefore(node, lineView.gutter || lineView.text); }
2248
+ else
2249
+ { wrap.appendChild(node); }
2250
+ signalLater(widget, "redraw");
2251
+ }
2252
+ }
2253
+
2254
+ function positionLineWidget(widget, node, lineView, dims) {
2255
+ if (widget.noHScroll) {
2256
+ (lineView.alignable || (lineView.alignable = [])).push(node);
2257
+ var width = dims.wrapperWidth;
2258
+ node.style.left = dims.fixedPos + "px";
2259
+ if (!widget.coverGutter) {
2260
+ width -= dims.gutterTotalWidth;
2261
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
2262
  }
2263
+ node.style.width = width + "px";
2264
+ }
2265
+ if (widget.coverGutter) {
2266
+ node.style.zIndex = 5;
2267
+ node.style.position = "relative";
2268
+ if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; }
2269
  }
 
2270
  }
2271
 
2272
+ function widgetHeight(widget) {
2273
+ if (widget.height != null) { return widget.height }
2274
+ var cm = widget.doc.cm;
2275
+ if (!cm) { return 0 }
2276
+ if (!contains(document.body, widget.node)) {
2277
+ var parentStyle = "position: relative;";
2278
+ if (widget.coverGutter)
2279
+ { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; }
2280
+ if (widget.noHScroll)
2281
+ { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; }
2282
+ removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
2283
+ }
2284
+ return widget.height = widget.node.parentNode.offsetHeight
2285
+ }
2286
+
2287
+ // Return true when the given mouse event happened in a widget
2288
+ function eventInWidget(display, e) {
2289
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
2290
+ if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
2291
+ (n.parentNode == display.sizer && n != display.mover))
2292
+ { return true }
2293
+ }
2294
  }
2295
 
2296
  // POSITION MEASUREMENT
2297
 
2298
+ function paddingTop(display) {return display.lineSpace.offsetTop}
2299
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}
2300
  function paddingH(display) {
2301
+ if (display.cachedPaddingH) { return display.cachedPaddingH }
2302
+ var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like"));
2303
  var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
2304
  var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
2305
+ if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; }
2306
+ return data
2307
  }
2308
 
2309
+ function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }
2310
  function displayWidth(cm) {
2311
+ return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth
2312
  }
2313
  function displayHeight(cm) {
2314
+ return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight
2315
  }
2316
 
2317
  // Ensure the lineView.wrapping.heights array is populated. This is
2329
  for (var i = 0; i < rects.length - 1; i++) {
2330
  var cur = rects[i], next = rects[i + 1];
2331
  if (Math.abs(cur.bottom - next.bottom) > 2)
2332
+ { heights.push((cur.bottom + next.top) / 2 - rect.top); }
2333
  }
2334
  }
2335
  heights.push(rect.bottom - rect.top);
2341
  // contain multiple lines when collapsed ranges are present.)
2342
  function mapFromLineView(lineView, line, lineN) {
2343
  if (lineView.line == line)
2344
+ { return {map: lineView.measure.map, cache: lineView.measure.cache} }
2345
  for (var i = 0; i < lineView.rest.length; i++)
2346
+ { if (lineView.rest[i] == line)
2347
+ { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
2348
+ for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
2349
+ { if (lineNo(lineView.rest[i$1]) > lineN)
2350
+ { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
2351
  }
2352
 
2353
  // Render a line into the hidden node display.externalMeasured. Used
2360
  var built = view.built = buildLineContent(cm, view);
2361
  view.text = built.pre;
2362
  removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
2363
+ return view
2364
  }
2365
 
2366
  // Get a {top, bottom, left, right} box (in line-local coordinates)
2367
  // for a given character.
2368
  function measureChar(cm, line, ch, bias) {
2369
+ return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)
2370
  }
2371
 
2372
  // Find a line view that corresponds to the given line number.
2373
  function findViewForLine(cm, lineN) {
2374
  if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
2375
+ { return cm.display.view[findViewIndex(cm, lineN)] }
2376
  var ext = cm.display.externalMeasured;
2377
  if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
2378
+ { return ext }
2379
  }
2380
 
2381
  // Measurement can be split in two steps, the set-up work that
2386
  function prepareMeasureForLine(cm, line) {
2387
  var lineN = lineNo(line);
2388
  var view = findViewForLine(cm, lineN);
2389
+ if (view && !view.text) {
2390
  view = null;
2391
+ } else if (view && view.changes) {
2392
  updateLineForChanges(cm, view, lineN, getDimensions(cm));
2393
+ cm.curOp.forceUpdate = true;
2394
+ }
2395
  if (!view)
2396
+ { view = updateExternalMeasurement(cm, line); }
2397
 
2398
  var info = mapFromLineView(view, line, lineN);
2399
  return {
2400
  line: line, view: view, rect: null,
2401
  map: info.map, cache: info.cache, before: info.before,
2402
  hasHeights: false
2403
+ }
2404
  }
2405
 
2406
  // Given a prepared measurement object, measures the position of an
2407
  // actual character (or fetches it from the cache).
2408
  function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
2409
+ if (prepared.before) { ch = -1; }
2410
  var key = ch + (bias || ""), found;
2411
  if (prepared.cache.hasOwnProperty(key)) {
2412
  found = prepared.cache[key];
2413
  } else {
2414
  if (!prepared.rect)
2415
+ { prepared.rect = prepared.view.text.getBoundingClientRect(); }
2416
  if (!prepared.hasHeights) {
2417
  ensureLineHeights(cm, prepared.view, prepared.rect);
2418
  prepared.hasHeights = true;
2419
  }
2420
  found = measureCharInner(cm, prepared, ch, bias);
2421
+ if (!found.bogus) { prepared.cache[key] = found; }
2422
  }
2423
  return {left: found.left, right: found.right,
2424
  top: varHeight ? found.rtop : found.top,
2425
+ bottom: varHeight ? found.rbottom : found.bottom}
2426
  }
2427
 
2428
  var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
2429
 
2430
  function nodeAndOffsetInLineMap(map, ch, bias) {
2431
+ var node, start, end, collapse, mStart, mEnd;
2432
  // First, search the line map for the text node corresponding to,
2433
  // or closest to, the target character.
2434
  for (var i = 0; i < map.length; i += 3) {
2435
+ mStart = map[i];
2436
+ mEnd = map[i + 1];
2437
  if (ch < mStart) {
2438
  start = 0; end = 1;
2439
  collapse = "left";
2443
  } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
2444
  end = mEnd - mStart;
2445
  start = end - 1;
2446
+ if (ch >= mEnd) { collapse = "right"; }
2447
  }
2448
  if (start != null) {
2449
  node = map[i + 2];
2450
  if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
2451
+ { collapse = bias; }
2452
  if (bias == "left" && start == 0)
2453
+ { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
2454
  node = map[(i -= 3) + 2];
2455
  collapse = "left";
2456
+ } }
2457
  if (bias == "right" && start == mEnd - mStart)
2458
+ { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
2459
  node = map[(i += 3) + 2];
2460
  collapse = "right";
2461
+ } }
2462
+ break
2463
  }
2464
  }
2465
+ return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}
2466
+ }
2467
+
2468
+ function getUsefulRect(rects, bias) {
2469
+ var rect = nullRect;
2470
+ if (bias == "left") { for (var i = 0; i < rects.length; i++) {
2471
+ if ((rect = rects[i]).left != rect.right) { break }
2472
+ } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {
2473
+ if ((rect = rects[i$1]).left != rect.right) { break }
2474
+ } }
2475
+ return rect
2476
  }
2477
 
2478
  function measureCharInner(cm, prepared, ch, bias) {
2481
 
2482
  var rect;
2483
  if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
2484
+ for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned
2485
+ while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; }
2486
+ while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; }
2487
+ if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
2488
+ { rect = node.parentNode.getBoundingClientRect(); }
2489
+ else
2490
+ { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); }
2491
+ if (rect.left || rect.right || start == 0) { break }
 
 
 
 
 
 
 
2492
  end = start;
2493
  start = start - 1;
2494
  collapse = "right";
2495
  }
2496
+ if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); }
2497
  } else { // If it is a widget, simply get the box for the whole widget.
2498
+ if (start > 0) { collapse = bias = "right"; }
2499
  var rects;
2500
  if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
2501
+ { rect = rects[bias == "right" ? rects.length - 1 : 0]; }
2502
  else
2503
+ { rect = node.getBoundingClientRect(); }
2504
  }
2505
  if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
2506
  var rSpan = node.parentNode.getClientRects()[0];
2507
  if (rSpan)
2508
+ { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; }
2509
  else
2510
+ { rect = nullRect; }
2511
  }
2512
 
2513
  var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
2514
  var mid = (rtop + rbot) / 2;
2515
  var heights = prepared.view.measure.heights;
2516
+ var i = 0;
2517
+ for (; i < heights.length - 1; i++)
2518
+ { if (mid < heights[i]) { break } }
2519
  var top = i ? heights[i - 1] : 0, bot = heights[i];
2520
  var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
2521
  right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
2522
  top: top, bottom: bot};
2523
+ if (!rect.left && !rect.right) { result.bogus = true; }
2524
  if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
2525
 
2526
+ return result
2527
  }
2528
 
2529
  // Work around problem with bounding client rects on ranges being
2531
  function maybeUpdateRectForZooming(measure, rect) {
2532
  if (!window.screen || screen.logicalXDPI == null ||
2533
  screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
2534
+ { return rect }
2535
  var scaleX = screen.logicalXDPI / screen.deviceXDPI;
2536
  var scaleY = screen.logicalYDPI / screen.deviceYDPI;
2537
  return {left: rect.left * scaleX, right: rect.right * scaleX,
2538
+ top: rect.top * scaleY, bottom: rect.bottom * scaleY}
2539
  }
2540
 
2541
  function clearLineMeasurementCacheFor(lineView) {
2542
  if (lineView.measure) {
2543
  lineView.measure.cache = {};
2544
  lineView.measure.heights = null;
2545
+ if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
2546
+ { lineView.measure.caches[i] = {}; } }
2547
  }
2548
  }
2549
 
2551
  cm.display.externalMeasure = null;
2552
  removeChildren(cm.display.lineMeasure);
2553
  for (var i = 0; i < cm.display.view.length; i++)
2554
+ { clearLineMeasurementCacheFor(cm.display.view[i]); }
2555
  }
2556
 
2557
  function clearCaches(cm) {
2558
  clearLineMeasurementCache(cm);
2559
  cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
2560
+ if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; }
2561
  cm.display.lineNumChars = null;
2562
  }
2563
 
2564
+ function pageScrollX() {
2565
+ // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206
2566
+ // which causes page_Offset and bounding client rects to use
2567
+ // different reference viewports and invalidate our calculations.
2568
+ if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) }
2569
+ return window.pageXOffset || (document.documentElement || document.body).scrollLeft
2570
+ }
2571
+ function pageScrollY() {
2572
+ if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) }
2573
+ return window.pageYOffset || (document.documentElement || document.body).scrollTop
2574
+ }
2575
+
2576
+ function widgetTopHeight(lineObj) {
2577
+ var height = 0;
2578
+ if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above)
2579
+ { height += widgetHeight(lineObj.widgets[i]); } } }
2580
+ return height
2581
+ }
2582
 
2583
  // Converts a {top, bottom, left, right} box from line-local
2584
  // coordinates into another coordinate system. Context may be one of
2585
+ // "line", "div" (display.lineDiv), "local"./null (editor), "window",
2586
  // or "page".
2587
+ function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
2588
+ if (!includeWidgets) {
2589
+ var height = widgetTopHeight(lineObj);
2590
+ rect.top += height; rect.bottom += height;
2591
  }
2592
+ if (context == "line") { return rect }
2593
+ if (!context) { context = "local"; }
2594
  var yOff = heightAtLine(lineObj);
2595
+ if (context == "local") { yOff += paddingTop(cm.display); }
2596
+ else { yOff -= cm.display.viewOffset; }
2597
  if (context == "page" || context == "window") {
2598
  var lOff = cm.display.lineSpace.getBoundingClientRect();
2599
  yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
2601
  rect.left += xOff; rect.right += xOff;
2602
  }
2603
  rect.top += yOff; rect.bottom += yOff;
2604
+ return rect
2605
  }
2606
 
2607
  // Coverts a box from "div" coords to another coordinate system.
2608
+ // Context may be "window", "page", "div", or "local"./null.
2609
  function fromCoordSystem(cm, coords, context) {
2610
+ if (context == "div") { return coords }
2611
  var left = coords.left, top = coords.top;
2612
  // First move into "page" coordinate system
2613
  if (context == "page") {
2620
  }
2621
 
2622
  var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
2623
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}
2624
  }
2625
 
2626
  function charCoords(cm, pos, context, lineObj, bias) {
2627
+ if (!lineObj) { lineObj = getLine(cm.doc, pos.line); }
2628
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)
2629
  }
2630
 
2631
  // Returns a box for a given cursor position, which may have an
2632
  // 'other' property containing the position of the secondary cursor
2633
  // on a bidi boundary.
2634
+ // A cursor Pos(line, char, "before") is on the same visual line as `char - 1`
2635
+ // and after `char - 1` in writing order of `char - 1`
2636
+ // A cursor Pos(line, char, "after") is on the same visual line as `char`
2637
+ // and before `char` in writing order of `char`
2638
+ // Examples (upper-case letters are RTL, lower-case are LTR):
2639
+ // Pos(0, 1, ...)
2640
+ // before after
2641
+ // ab a|b a|b
2642
+ // aB a|B aB|
2643
+ // Ab |Ab A|b
2644
+ // AB B|A B|A
2645
+ // Every position after the last character on a line is considered to stick
2646
+ // to the last character on the line.
2647
  function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
2648
  lineObj = lineObj || getLine(cm.doc, pos.line);
2649
+ if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
2650
  function get(ch, right) {
2651
  var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
2652
+ if (right) { m.left = m.right; } else { m.right = m.left; }
2653
+ return intoCoordSystem(cm, lineObj, m, context)
2654
+ }
2655
+ var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky;
2656
+ if (ch >= lineObj.text.length) {
2657
+ ch = lineObj.text.length;
2658
+ sticky = "before";
2659
+ } else if (ch <= 0) {
2660
+ ch = 0;
2661
+ sticky = "after";
2662
+ }
2663
+ if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") }
2664
+
2665
+ function getBidi(ch, partPos, invert) {
2666
+ var part = order[partPos], right = part.level == 1;
2667
+ return get(invert ? ch - 1 : ch, right != invert)
2668
+ }
2669
+ var partPos = getBidiPartAt(order, ch, sticky);
2670
+ var other = bidiOther;
2671
+ var val = getBidi(ch, partPos, sticky == "before");
2672
+ if (other != null) { val.other = getBidi(ch, other, sticky != "before"); }
2673
+ return val
 
2674
  }
2675
 
2676
  // Used to cheaply estimate the coordinates for a position. Used for
2677
  // intermediate scroll updates.
2678
  function estimateCoords(cm, pos) {
2679
+ var left = 0;
2680
+ pos = clipPos(cm.doc, pos);
2681
+ if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; }
2682
  var lineObj = getLine(cm.doc, pos.line);
2683
  var top = heightAtLine(lineObj) + paddingTop(cm.display);
2684
+ return {left: left, right: left, top: top, bottom: top + lineObj.height}
2685
  }
2686
 
2687
  // Positions returned by coordsChar contain some extra information.
2690
  // the right of the character position, for example). When outside
2691
  // is true, that means the coordinates lie outside the line's
2692
  // vertical range.
2693
+ function PosWithInfo(line, ch, sticky, outside, xRel) {
2694
+ var pos = Pos(line, ch, sticky);
2695
  pos.xRel = xRel;
2696
+ if (outside) { pos.outside = outside; }
2697
+ return pos
2698
  }
2699
 
2700
  // Compute the character position closest to the given coordinates.
2702
  function coordsChar(cm, x, y) {
2703
  var doc = cm.doc;
2704
  y += cm.display.viewOffset;
2705
+ if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) }
2706
  var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
2707
  if (lineN > last)
2708
+ { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) }
2709
+ if (x < 0) { x = 0; }
2710
 
2711
  var lineObj = getLine(doc, lineN);
2712
  for (;;) {
2713
  var found = coordsCharInner(cm, lineObj, lineN, x, y);
2714
+ var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0));
2715
+ if (!collapsed) { return found }
2716
+ var rangeEnd = collapsed.find(1);
2717
+ if (rangeEnd.line == lineN) { return rangeEnd }
2718
+ lineObj = getLine(doc, lineN = rangeEnd.line);
 
2719
  }
2720
  }
2721
 
2722
+ function wrappedLineExtent(cm, lineObj, preparedMeasure, y) {
2723
+ y -= widgetTopHeight(lineObj);
2724
+ var end = lineObj.text.length;
2725
+ var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0);
2726
+ end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end);
2727
+ return {begin: begin, end: end}
2728
+ }
2729
 
2730
+ function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) {
2731
+ if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
2732
+ var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top;
2733
+ return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop)
2734
+ }
 
 
 
2735
 
2736
+ // Returns true if the given side of a box is after the given
2737
+ // coordinates, in top-to-bottom, left-to-right order.
2738
+ function boxIsAfter(box, x, y, left) {
2739
+ return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x
2740
+ }
2741
 
2742
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
2743
+ // Move y into line-local coordinate space
2744
+ y -= heightAtLine(lineObj);
2745
+ var preparedMeasure = prepareMeasureForLine(cm, lineObj);
2746
+ // When directly calling `measureCharPrepared`, we have to adjust
2747
+ // for the widgets at this line.
2748
+ var widgetHeight = widgetTopHeight(lineObj);
2749
+ var begin = 0, end = lineObj.text.length, ltr = true;
2750
+
2751
+ var order = getOrder(lineObj, cm.doc.direction);
2752
+ // If the line isn't plain left-to-right text, first figure out
2753
+ // which bidi section the coordinates fall into.
2754
+ if (order) {
2755
+ var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart)
2756
+ (cm, lineObj, lineNo, preparedMeasure, order, x, y);
2757
+ ltr = part.level != 1;
2758
+ // The awkward -1 offsets are needed because findFirst (called
2759
+ // on these below) will treat its first bound as inclusive,
2760
+ // second as exclusive, but we want to actually address the
2761
+ // characters in the part's range
2762
+ begin = ltr ? part.from : part.to - 1;
2763
+ end = ltr ? part.to : part.from - 1;
2764
+ }
2765
+
2766
+ // A binary search to find the first character whose bounding box
2767
+ // starts after the coordinates. If we run across any whose box wrap
2768
+ // the coordinates, store that.
2769
+ var chAround = null, boxAround = null;
2770
+ var ch = findFirst(function (ch) {
2771
+ var box = measureCharPrepared(cm, preparedMeasure, ch);
2772
+ box.top += widgetHeight; box.bottom += widgetHeight;
2773
+ if (!boxIsAfter(box, x, y, false)) { return false }
2774
+ if (box.top <= y && box.left <= x) {
2775
+ chAround = ch;
2776
+ boxAround = box;
2777
+ }
2778
+ return true
2779
+ }, begin, end);
2780
+
2781
+ var baseX, sticky, outside = false;
2782
+ // If a box around the coordinates was found, use that
2783
+ if (boxAround) {
2784
+ // Distinguish coordinates nearer to the left or right side of the box
2785
+ var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr;
2786
+ ch = chAround + (atStart ? 0 : 1);
2787
+ sticky = atStart ? "after" : "before";
2788
+ baseX = atLeft ? boxAround.left : boxAround.right;
2789
+ } else {
2790
+ // (Adjust for extended bound, if necessary.)
2791
+ if (!ltr && (ch == end || ch == begin)) { ch++; }
2792
+ // To determine which side to associate with, get the box to the
2793
+ // left of the character and compare it's vertical position to the
2794
+ // coordinates
2795
+ sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" :
2796
+ (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ?
2797
+ "after" : "before";
2798
+ // Now get accurate coordinates for this place, in order to get a
2799
+ // base X position
2800
+ var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure);
2801
+ baseX = coords.left;
2802
+ outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0;
2803
+ }
2804
+
2805
+ ch = skipExtendingChars(lineObj.text, ch, 1);
2806
+ return PosWithInfo(lineNo, ch, sticky, outside, x - baseX)
2807
+ }
2808
+
2809
+ function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) {
2810
+ // Bidi parts are sorted left-to-right, and in a non-line-wrapping
2811
+ // situation, we can take this ordering to correspond to the visual
2812
+ // ordering. This finds the first part whose end is after the given
2813
+ // coordinates.
2814
+ var index = findFirst(function (i) {
2815
+ var part = order[i], ltr = part.level != 1;
2816
+ return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"),
2817
+ "line", lineObj, preparedMeasure), x, y, true)
2818
+ }, 0, order.length - 1);
2819
+ var part = order[index];
2820
+ // If this isn't the first part, the part's start is also after
2821
+ // the coordinates, and the coordinates aren't on the same line as
2822
+ // that start, move one part back.
2823
+ if (index > 0) {
2824
+ var ltr = part.level != 1;
2825
+ var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"),
2826
+ "line", lineObj, preparedMeasure);
2827
+ if (boxIsAfter(start, x, y, true) && start.top > y)
2828
+ { part = order[index - 1]; }
2829
+ }
2830
+ return part
2831
+ }
2832
+
2833
+ function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) {
2834
+ // In a wrapped line, rtl text on wrapping boundaries can do things
2835
+ // that don't correspond to the ordering in our `order` array at
2836
+ // all, so a binary search doesn't work, and we want to return a
2837
+ // part that only spans one line so that the binary search in
2838
+ // coordsCharInner is safe. As such, we first find the extent of the
2839
+ // wrapped line, and then do a flat search in which we discard any
2840
+ // spans that aren't on the line.
2841
+ var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y);
2842
+ var begin = ref.begin;
2843
+ var end = ref.end;
2844
+ if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; }
2845
+ var part = null, closestDist = null;
2846
+ for (var i = 0; i < order.length; i++) {
2847
+ var p = order[i];
2848
+ if (p.from >= end || p.to <= begin) { continue }
2849
+ var ltr = p.level != 1;
2850
+ var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right;
2851
+ // Weigh against spans ending before this, so that they are only
2852
+ // picked if nothing ends after
2853
+ var dist = endX < x ? x - endX + 1e9 : endX - x;
2854
+ if (!part || closestDist > dist) {
2855
+ part = p;
2856
+ closestDist = dist;
2857
+ }
2858
+ }
2859
+ if (!part) { part = order[order.length - 1]; }
2860
+ // Clip the part to the wrapped line.
2861
+ if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; }
2862
+ if (part.to > end) { part = {from: part.from, to: end, level: part.level}; }
2863
+ return part
2864
  }
2865
 
2866
  var measureText;
2867
  // Compute the default text height.
2868
  function textHeight(display) {
2869
+ if (display.cachedTextHeight != null) { return display.cachedTextHeight }
2870
  if (measureText == null) {
2871
+ measureText = elt("pre", null, "CodeMirror-line-like");
2872
  // Measure a bunch of lines, for browsers that compute
2873
  // fractional heights.
2874
  for (var i = 0; i < 49; ++i) {
2879
  }
2880
  removeChildrenAndAdd(display.measure, measureText);
2881
  var height = measureText.offsetHeight / 50;
2882
+ if (height > 3) { display.cachedTextHeight = height; }
2883
  removeChildren(display.measure);
2884
+ return height || 1
2885
  }
2886
 
2887
  // Compute the default character width.
2888
  function charWidth(display) {
2889
+ if (display.cachedCharWidth != null) { return display.cachedCharWidth }
2890
  var anchor = elt("span", "xxxxxxxxxx");
2891
+ var pre = elt("pre", [anchor], "CodeMirror-line-like");
2892
  removeChildrenAndAdd(display.measure, pre);
2893
  var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
2894
+ if (width > 2) { display.cachedCharWidth = width; }
2895
+ return width || 10
2896
  }
2897
 
2898
+ // Do a bulk-read of the DOM positions and sizes needed to draw the
2899
+ // view, so that we don't interleave reading and writing to the DOM.
2900
+ function getDimensions(cm) {
2901
+ var d = cm.display, left = {}, width = {};
2902
+ var gutterLeft = d.gutters.clientLeft;
2903
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
2904
+ var id = cm.display.gutterSpecs[i].className;
2905
+ left[id] = n.offsetLeft + n.clientLeft + gutterLeft;
2906
+ width[id] = n.clientWidth;
2907
+ }
2908
+ return {fixedPos: compensateForHScroll(d),
2909
+ gutterTotalWidth: d.gutters.offsetWidth,
2910
+ gutterLeft: left,
2911
+ gutterWidth: width,
2912
+ wrapperWidth: d.wrapper.clientWidth}
2913
+ }
2914
 
2915
+ // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
2916
+ // but using getBoundingClientRect to get a sub-pixel-accurate
2917
+ // result.
2918
+ function compensateForHScroll(display) {
2919
+ return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left
2920
+ }
2921
 
2922
+ // Returns a function that estimates the height of a line, to use as
2923
+ // first approximation until the line becomes visible (and is thus
2924
+ // properly measurable).
2925
+ function estimateHeight(cm) {
2926
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
2927
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
2928
+ return function (line) {
2929
+ if (lineIsHidden(cm.doc, line)) { return 0 }
2930
 
2931
+ var widgetsHeight = 0;
2932
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {
2933
+ if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; }
2934
+ } }
2935
+
2936
+ if (wrapping)
2937
+ { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }
2938
+ else
2939
+ { return widgetsHeight + th }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2940
  }
2941
  }
2942
 
2943
+ function estimateLineHeights(cm) {
2944
+ var doc = cm.doc, est = estimateHeight(cm);
2945
+ doc.iter(function (line) {
2946
+ var estHeight = est(line);
2947
+ if (estHeight != line.height) { updateLineHeight(line, estHeight); }
2948
+ });
 
 
 
 
 
 
 
 
2949
  }
2950
 
2951
+ // Given a mouse event, find the corresponding position. If liberal
2952
+ // is false, it checks whether a gutter or scrollbar was clicked,
2953
+ // and returns null if it was. forRect is used by rectangular
2954
+ // selections, and tries to estimate a character position even for
2955
+ // coordinates beyond the right of the text.
2956
+ function posFromMouse(cm, e, liberal, forRect) {
2957
+ var display = cm.display;
2958
+ if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null }
2959
 
2960
+ var x, y, space = display.lineSpace.getBoundingClientRect();
2961
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
2962
+ try { x = e.clientX - space.left; y = e.clientY - space.top; }
2963
+ catch (e$1) { return null }
2964
+ var coords = coordsChar(cm, x, y), line;
2965
+ if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
2966
+ var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
2967
+ coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
2968
  }
2969
+ return coords
2970
  }
2971
 
2972
+ // Find the view element corresponding to a given line. Return null
2973
+ // when the line isn't visible.
2974
+ function findViewIndex(cm, n) {
2975
+ if (n >= cm.display.viewTo) { return null }
2976
+ n -= cm.display.viewFrom;
2977
+ if (n < 0) { return null }
2978
+ var view = cm.display.view;
2979
+ for (var i = 0; i < view.length; i++) {
2980
+ n -= view[i].size;
2981
+ if (n < 0) { return i }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2982
  }
 
2983
  }
2984
 
2985
  // Updates the display.view data structure for a given change to the
2989
  // lines are divided into visual lines. regLineChange (below)
2990
  // registers single-line changes.
2991
  function regChange(cm, from, to, lendiff) {
2992
+ if (from == null) { from = cm.doc.first; }
2993
+ if (to == null) { to = cm.doc.first + cm.doc.size; }
2994
+ if (!lendiff) { lendiff = 0; }
2995
 
2996
  var display = cm.display;
2997
  if (lendiff && to < display.viewTo &&
2998
  (display.updateLineNumbers == null || display.updateLineNumbers > from))
2999
+ { display.updateLineNumbers = from; }
3000
 
3001
  cm.curOp.viewChanged = true;
3002
 
3003
  if (from >= display.viewTo) { // Change after
3004
  if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
3005
+ { resetView(cm); }
3006
  } else if (to <= display.viewFrom) { // Change before
3007
  if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
3008
  resetView(cm);
3022
  resetView(cm);
3023
  }
3024
  } else if (to >= display.viewTo) { // Bottom overlap
3025
+ var cut$1 = viewCuttingPoint(cm, from, from, -1);
3026
+ if (cut$1) {
3027
+ display.view = display.view.slice(0, cut$1.index);
3028
+ display.viewTo = cut$1.lineN;
3029
  } else {
3030
  resetView(cm);
3031
  }
3045
  var ext = display.externalMeasured;
3046
  if (ext) {
3047
  if (to < ext.lineN)
3048
+ { ext.lineN += lendiff; }
3049
  else if (from < ext.lineN + ext.size)
3050
+ { display.externalMeasured = null; }
3051
  }
3052
  }
3053
 
3057
  cm.curOp.viewChanged = true;
3058
  var display = cm.display, ext = cm.display.externalMeasured;
3059
  if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
3060
+ { display.externalMeasured = null; }
3061
 
3062
+ if (line < display.viewFrom || line >= display.viewTo) { return }
3063
  var lineView = display.view[findViewIndex(cm, line)];
3064
+ if (lineView.node == null) { return }
3065
  var arr = lineView.changes || (lineView.changes = []);
3066
+ if (indexOf(arr, type) == -1) { arr.push(type); }
3067
  }
3068
 
3069
  // Clear the view.
3073
  cm.display.viewOffset = 0;
3074
  }
3075
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3076
  function viewCuttingPoint(cm, oldN, newN, dir) {
3077
  var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
3078
  if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
3079
+ { return {index: index, lineN: newN} }
3080
+ var n = cm.display.viewFrom;
3081
+ for (var i = 0; i < index; i++)
3082
+ { n += view[i].size; }
3083
  if (n != oldN) {
3084
  if (dir > 0) {
3085
+ if (index == view.length - 1) { return null }
3086
  diff = (n + view[index].size) - oldN;
3087
  index++;
3088
  } else {
3091
  oldN += diff; newN += diff;
3092
  }
3093
  while (visualLineNo(cm.doc, newN) != newN) {
3094
+ if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
3095
  newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
3096
  index += dir;
3097
  }
3098
+ return {index: index, lineN: newN}
3099
  }
3100
 
3101
  // Force the view to cover a given range, adding empty view element
3107
  display.viewFrom = from;
3108
  } else {
3109
  if (display.viewFrom > from)
3110
+ { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); }
3111
  else if (display.viewFrom < from)
3112
+ { display.view = display.view.slice(findViewIndex(cm, from)); }
3113
  display.viewFrom = from;
3114
  if (display.viewTo < to)
3115
+ { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); }
3116
  else if (display.viewTo > to)
3117
+ { display.view = display.view.slice(0, findViewIndex(cm, to)); }
3118
  }
3119
  display.viewTo = to;
3120
  }
3125
  var view = cm.display.view, dirty = 0;
3126
  for (var i = 0; i < view.length; i++) {
3127
  var lineView = view[i];
3128
+ if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; }
3129
  }
3130
+ return dirty
3131
  }
3132
 
3133
+ function updateSelection(cm) {
3134
+ cm.display.input.showSelection(cm.display.input.prepareSelection());
3135
+ }
3136
 
3137
+ function prepareSelection(cm, primary) {
3138
+ if ( primary === void 0 ) primary = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3139
 
3140
+ var doc = cm.doc, result = {};
3141
+ var curFragment = result.cursors = document.createDocumentFragment();
3142
+ var selFragment = result.selection = document.createDocumentFragment();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3143
 
3144
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
3145
+ if (!primary && i == doc.sel.primIndex) { continue }
3146
+ var range = doc.sel.ranges[i];
3147
+ if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
3148
+ var collapsed = range.empty();
3149
+ if (collapsed || cm.options.showCursorWhenSelecting)
3150
+ { drawSelectionCursor(cm, range.head, curFragment); }
3151
+ if (!collapsed)
3152
+ { drawSelectionRange(cm, range, selFragment); }
3153
+ }
3154
+ return result
3155
+ }
3156
 
3157
+ // Draws a cursor for the given range
3158
+ function drawSelectionCursor(cm, head, output) {
3159
+ var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);
3160
 
3161
+ var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
3162
+ cursor.style.left = pos.left + "px";
3163
+ cursor.style.top = pos.top + "px";
3164
+ cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
3165
 
3166
+ if (pos.other) {
3167
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
3168
+ var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
3169
+ otherCursor.style.display = "";
3170
+ otherCursor.style.left = pos.other.left + "px";
3171
+ otherCursor.style.top = pos.other.top + "px";
3172
+ otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
 
3173
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3174
  }
3175
 
3176
+ function cmpCoords(a, b) { return a.top - b.top || a.left - b.left }
3177
 
3178
+ // Draws the given range as a highlighted selection
3179
+ function drawSelectionRange(cm, range, output) {
3180
+ var display = cm.display, doc = cm.doc;
3181
+ var fragment = document.createDocumentFragment();
3182
+ var padding = paddingH(cm.display), leftSide = padding.left;
3183
+ var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
3184
+ var docLTR = doc.direction == "ltr";
 
 
 
 
 
 
 
 
 
 
3185
 
3186
+ function add(left, top, width, bottom) {
3187
+ if (top < 0) { top = 0; }
3188
+ top = Math.round(top);
3189
+ bottom = Math.round(bottom);
3190
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px")));
 
 
 
3191
  }
 
 
 
 
 
 
 
 
 
 
 
 
3192
 
3193
+ function drawForLine(line, fromArg, toArg) {
3194
+ var lineObj = getLine(doc, line);
3195
+ var lineLen = lineObj.text.length;
3196
+ var start, end;
3197
+ function coords(ch, bias) {
3198
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
3199
+ }
3200
+
3201
+ function wrapX(pos, dir, side) {
3202
+ var extent = wrappedLineExtentChar(cm, lineObj, null, pos);
3203
+ var prop = (dir == "ltr") == (side == "after") ? "left" : "right";
3204
+ var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1);
3205
+ return coords(ch, prop)[prop]
3206
+ }
3207
+
3208
+ var order = getOrder(lineObj, doc.direction);
3209
+ iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) {
3210
+ var ltr = dir == "ltr";
3211
+ var fromPos = coords(from, ltr ? "left" : "right");
3212
+ var toPos = coords(to - 1, ltr ? "right" : "left");
3213
+
3214
+ var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen;
3215
+ var first = i == 0, last = !order || i == order.length - 1;
3216
+ if (toPos.top - fromPos.top <= 3) { // Single line
3217
+ var openLeft = (docLTR ? openStart : openEnd) && first;
3218
+ var openRight = (docLTR ? openEnd : openStart) && last;
3219
+ var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left;
3220
+ var right = openRight ? rightSide : (ltr ? toPos : fromPos).right;
3221
+ add(left, fromPos.top, right - left, fromPos.bottom);
3222
+ } else { // Multiple lines
3223
+ var topLeft, topRight, botLeft, botRight;
3224
+ if (ltr) {
3225
+ topLeft = docLTR && openStart && first ? leftSide : fromPos.left;
3226
+ topRight = docLTR ? rightSide : wrapX(from, dir, "before");
3227
+ botLeft = docLTR ? leftSide : wrapX(to, dir, "after");
3228
+ botRight = docLTR && openEnd && last ? rightSide : toPos.right;
3229
+ } else {
3230
+ topLeft = !docLTR ? leftSide : wrapX(from, dir, "before");
3231
+ topRight = !docLTR && openStart && first ? rightSide : fromPos.right;
3232
+ botLeft = !docLTR && openEnd && last ? leftSide : toPos.left;
3233
+ botRight = !docLTR ? rightSide : wrapX(to, dir, "after");
3234
+ }
3235
+ add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom);
3236
+ if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); }
3237
+ add(botLeft, toPos.top, botRight - botLeft, toPos.bottom);
3238
+ }
3239
 
3240
+ if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; }
3241
+ if (cmpCoords(toPos, start) < 0) { start = toPos; }
3242
+ if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; }
3243
+ if (cmpCoords(toPos, end) < 0) { end = toPos; }
3244
+ });
3245
+ return {start: start, end: end}
 
 
 
 
 
 
 
 
 
 
3246
  }
 
3247
 
3248
+ var sFrom = range.from(), sTo = range.to();
3249
+ if (sFrom.line == sTo.line) {
3250
+ drawForLine(sFrom.line, sFrom.ch, sTo.ch);
 
 
 
 
 
 
 
 
3251
  } else {
3252
+ var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
3253
+ var singleVLine = visualLine(fromLine) == visualLine(toLine);
3254
+ var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
3255
+ var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
3256
+ if (singleVLine) {
3257
+ if (leftEnd.top < rightStart.top - 2) {
3258
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
3259
+ add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
3260
+ } else {
3261
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
3262
+ }
3263
+ }
3264
+ if (leftEnd.bottom < rightStart.top)
3265
+ { add(leftSide, leftEnd.bottom, null, rightStart.top); }
3266
  }
3267
 
3268
+ output.appendChild(fragment);
 
 
 
 
 
 
3269
  }
3270
 
3271
+ // Cursor-blinking
3272
+ function restartBlink(cm) {
3273
+ if (!cm.state.focused) { return }
3274
  var display = cm.display;
3275
+ clearInterval(display.blinker);
3276
+ var on = true;
3277
+ display.cursorDiv.style.visibility = "";
3278
+ if (cm.options.cursorBlinkRate > 0)
3279
+ { display.blinker = setInterval(function () {
3280
+ if (!cm.hasFocus()) { onBlur(cm); }
3281
+ display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
3282
+ }, cm.options.cursorBlinkRate); }
3283
+ else if (cm.options.cursorBlinkRate < 0)
3284
+ { display.cursorDiv.style.visibility = "hidden"; }
 
 
 
 
 
 
 
 
 
 
 
 
 
3285
  }
3286
 
3287
+ function ensureFocus(cm) {
3288
+ if (!cm.hasFocus()) {
3289
+ cm.display.input.focus();
3290
+ if (!cm.state.focused) { onFocus(cm); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3291
  }
3292
+ }
3293
 
3294
+ function delayBlurEvent(cm) {
3295
+ cm.state.delayingBlurEvent = true;
3296
+ setTimeout(function () { if (cm.state.delayingBlurEvent) {
3297
+ cm.state.delayingBlurEvent = false;
3298
+ if (cm.state.focused) { onBlur(cm); }
3299
+ } }, 100);
3300
+ }
 
 
 
 
 
 
 
3301
 
3302
+ function onFocus(cm, e) {
3303
+ if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; }
 
 
3304
 
3305
+ if (cm.options.readOnly == "nocursor") { return }
3306
+ if (!cm.state.focused) {
3307
+ signal(cm, "focus", cm, e);
3308
+ cm.state.focused = true;
3309
+ addClass(cm.display.wrapper, "CodeMirror-focused");
3310
+ // This test prevents this from firing when a context
3311
+ // menu is closed (since the input reset would kill the
3312
+ // select-all detection hack)
3313
+ if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
3314
+ cm.display.input.reset();
3315
+ if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3316
  }
3317
+ cm.display.input.receivedFocus();
3318
  }
3319
+ restartBlink(cm);
3320
+ }
3321
+ function onBlur(cm, e) {
3322
+ if (cm.state.delayingBlurEvent) { return }
3323
 
3324
+ if (cm.state.focused) {
3325
+ signal(cm, "blur", cm, e);
3326
+ cm.state.focused = false;
3327
+ rmClass(cm.display.wrapper, "CodeMirror-focused");
3328
+ }
3329
+ clearInterval(cm.display.blinker);
3330
+ setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150);
3331
+ }
3332
 
3333
+ // Read the actual heights of the rendered lines, and update their
3334
+ // stored heights to match.
3335
+ function updateHeightsInViewport(cm) {
3336
+ var display = cm.display;
3337
+ var prevBottom = display.lineDiv.offsetTop;
3338
+ for (var i = 0; i < display.view.length; i++) {
3339
+ var cur = display.view[i], wrapping = cm.options.lineWrapping;
3340
+ var height = (void 0), width = 0;
3341
+ if (cur.hidden) { continue }
3342
+ if (ie && ie_version < 8) {
3343
+ var bot = cur.node.offsetTop + cur.node.offsetHeight;
3344
+ height = bot - prevBottom;
3345
+ prevBottom = bot;
3346
  } else {
3347
+ var box = cur.node.getBoundingClientRect();
3348
+ height = box.bottom - box.top;
3349
+ // Check that lines don't extend past the right of the current
3350
+ // editor width
3351
+ if (!wrapping && cur.text.firstChild)
3352
+ { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; }
3353
+ }
3354
+ var diff = cur.line.height - height;
3355
+ if (diff > .005 || diff < -.005) {
3356
+ updateLineHeight(cur.line, height);
3357
+ updateWidgetHeight(cur.line);
3358
+ if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
3359
+ { updateWidgetHeight(cur.rest[j]); } }
3360
+ }
3361
+ if (width > cm.display.sizerWidth) {
3362
+ var chWidth = Math.ceil(width / charWidth(cm.display));
3363
+ if (chWidth > cm.display.maxLineLength) {
3364
+ cm.display.maxLineLength = chWidth;
3365
+ cm.display.maxLine = cur.line;
3366
+ cm.display.maxLineChanged = true;
3367
+ }
3368
  }
3369
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3370
  }
3371
 
3372
+ // Read and store the height of line widgets associated with the
3373
+ // given line.
3374
+ function updateWidgetHeight(line) {
3375
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) {
3376
+ var w = line.widgets[i], parent = w.node.parentNode;
3377
+ if (parent) { w.height = parent.offsetHeight; }
3378
+ } }
3379
+ }
 
 
3380
 
3381
+ // Compute the lines that are visible in a given viewport (defaults
3382
+ // the the current scroll position). viewport may contain top,
3383
+ // height, and ensure (see op.scrollToPos) properties.
3384
+ function visibleLines(display, doc, viewport) {
3385
+ var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
3386
+ top = Math.floor(top - paddingTop(display));
3387
+ var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
3388
 
3389
+ var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
3390
+ // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
3391
+ // forces those lines into the viewport (if possible).
3392
+ if (viewport && viewport.ensure) {
3393
+ var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
3394
+ if (ensureFrom < from) {
3395
+ from = ensureFrom;
3396
+ to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
3397
+ } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
3398
+ from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
3399
+ to = ensureTo;
3400
  }
3401
  }
3402
+ return {from: from, to: Math.max(to, from + 1)}
3403
  }
3404
 
3405
+ // SCROLLING THINGS INTO VIEW
 
 
3406
 
3407
+ // If an editor sits on the top or bottom of the window, partially
3408
+ // scrolled out of view, this ensures that the cursor is visible.
3409
+ function maybeScrollWindow(cm, rect) {
3410
+ if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
3411
 
3412
+ var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
3413
+ if (rect.top + box.top < 0) { doScroll = true; }
3414
+ else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; }
3415
+ if (doScroll != null && !phantom) {
3416
+ var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;"));
3417
+ cm.display.lineSpace.appendChild(scrollNode);
3418
+ scrollNode.scrollIntoView(doScroll);
3419
+ cm.display.lineSpace.removeChild(scrollNode);
3420
+ }
3421
+ }
3422
+
3423
+ // Scroll a given position into view (immediately), verifying that
3424
+ // it actually became visible (as line heights are accurately
3425
+ // measured, the position of something may 'drift' during drawing).
3426
+ function scrollPosIntoView(cm, pos, end, margin) {
3427
+ if (margin == null) { margin = 0; }
3428
+ var rect;
3429
+ if (!cm.options.lineWrapping && pos == end) {
3430
+ // Set pos and end to the cursor positions around the character pos sticks to
3431
+ // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch
3432
+ // If pos == Pos(_, 0, "before"), pos and end are unchanged
3433
+ pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
3434
+ end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos;
3435
+ }
3436
+ for (var limit = 0; limit < 5; limit++) {
3437
+ var changed = false;
3438
+ var coords = cursorCoords(cm, pos);
3439
+ var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
3440
+ rect = {left: Math.min(coords.left, endCoords.left),
3441
+ top: Math.min(coords.top, endCoords.top) - margin,
3442
+ right: Math.max(coords.left, endCoords.left),
3443
+ bottom: Math.max(coords.bottom, endCoords.bottom) + margin};
3444
+ var scrollPos = calculateScrollPos(cm, rect);
3445
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
3446
+ if (scrollPos.scrollTop != null) {
3447
+ updateScrollTop(cm, scrollPos.scrollTop);
3448
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; }
3449
  }
3450
+ if (scrollPos.scrollLeft != null) {
3451
+ setScrollLeft(cm, scrollPos.scrollLeft);
3452
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; }
 
 
 
 
 
 
 
 
3453
  }
3454
+ if (!changed) { break }
3455
  }
3456
+ return rect
3457
  }
3458
 
3459
+ // Scroll a given set of coordinates into view (immediately).
3460
+ function scrollIntoView(cm, rect) {
3461
+ var scrollPos = calculateScrollPos(cm, rect);
3462
+ if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); }
3463
+ if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); }
3464
+ }
3465
 
3466
+ // Calculate a new scroll position needed to scroll the given
3467
+ // rectangle into view. Returns an object with scrollTop and
3468
+ // scrollLeft properties. When these are undefined, the
3469
+ // vertical/horizontal position does not need to be adjusted.
3470
+ function calculateScrollPos(cm, rect) {
3471
+ var display = cm.display, snapMargin = textHeight(cm.display);
3472
+ if (rect.top < 0) { rect.top = 0; }
3473
+ var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
3474
+ var screen = displayHeight(cm), result = {};
3475
+ if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; }
3476
+ var docBottom = cm.doc.height + paddingVert(display);
3477
+ var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin;
3478
+ if (rect.top < screentop) {
3479
+ result.scrollTop = atTop ? 0 : rect.top;
3480
+ } else if (rect.bottom > screentop + screen) {
3481
+ var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
3482
+ if (newTop != screentop) { result.scrollTop = newTop; }
3483
+ }
3484
+
3485
+ var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth;
3486
+ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace;
3487
+ var screenw = displayWidth(cm) - display.gutters.offsetWidth;
3488
+ var tooWide = rect.right - rect.left > screenw;
3489
+ if (tooWide) { rect.right = rect.left + screenw; }
3490
+ if (rect.left < 10)
3491
+ { result.scrollLeft = 0; }
3492
+ else if (rect.left < screenleft)
3493
+ { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); }
3494
+ else if (rect.right > screenw + screenleft - 3)
3495
+ { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
3496
+ return result
3497
+ }
3498
 
3499
+ // Store a relative adjustment to the scroll position in the current
3500
+ // operation (to be applied when the operation finishes).
3501
+ function addToScrollTop(cm, top) {
3502
+ if (top == null) { return }
3503
+ resolveScrollToPos(cm);
3504
+ cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
3505
+ }
3506
+
3507
+ // Make sure that at the end of the operation the current cursor is
3508
+ // shown.
3509
+ function ensureCursorVisible(cm) {
3510
+ resolveScrollToPos(cm);
3511
+ var cur = cm.getCursor();
3512
+ cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin};
3513
+ }
3514
+
3515
+ function scrollToCoords(cm, x, y) {
3516
+ if (x != null || y != null) { resolveScrollToPos(cm); }
3517
+ if (x != null) { cm.curOp.scrollLeft = x; }
3518
+ if (y != null) { cm.curOp.scrollTop = y; }
3519
+ }
3520
+
3521
+ function scrollToRange(cm, range) {
3522
+ resolveScrollToPos(cm);
3523
+ cm.curOp.scrollToPos = range;
3524
+ }
3525
+
3526
+ // When an operation has its scrollToPos property set, and another
3527
+ // scroll action is applied before the end of the operation, this
3528
+ // 'simulates' scrolling that position into view in a cheap way, so
3529
+ // that the effect of intermediate scroll commands is not ignored.
3530
+ function resolveScrollToPos(cm) {
3531
+ var range = cm.curOp.scrollToPos;
3532
+ if (range) {
3533
+ cm.curOp.scrollToPos = null;
3534
+ var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
3535
+ scrollToCoordsRange(cm, from, to, range.margin);
3536
  }
3537
  }
3538
 
3539
+ function scrollToCoordsRange(cm, from, to, margin) {
3540
+ var sPos = calculateScrollPos(cm, {
3541
+ left: Math.min(from.left, to.left),
3542
+ top: Math.min(from.top, to.top) - margin,
3543
+ right: Math.max(from.right, to.right),
3544
+ bottom: Math.max(from.bottom, to.bottom) + margin
3545
+ });
3546
+ scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop);
3547
+ }
3548
 
3549
  // Sync the scrollable area and scrollbars, ensure the viewport
3550
  // covers the visible area.
3551
+ function updateScrollTop(cm, val) {
3552
+ if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
3553
+ if (!gecko) { updateDisplaySimple(cm, {top: val}); }
3554
+ setScrollTop(cm, val, true);
3555
+ if (gecko) { updateDisplaySimple(cm); }
3556
+ startWorker(cm, 100);
3557
+ }
3558
+
3559
+ function setScrollTop(cm, val, forceScroll) {
3560
+ val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val));
3561
+ if (cm.display.scroller.scrollTop == val && !forceScroll) { return }
3562
  cm.doc.scrollTop = val;
 
 
3563
  cm.display.scrollbars.setScrollTop(val);
3564
+ if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; }
 
3565
  }
3566
+
3567
  // Sync scroller and scrollbar, ensure the gutter elements are
3568
  // aligned.
3569
+ function setScrollLeft(cm, val, isScroller, forceScroll) {
3570
+ val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth));
3571
+ if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return }
3572
  cm.doc.scrollLeft = val;
3573
  alignHorizontally(cm);
3574
+ if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; }
3575
  cm.display.scrollbars.setScrollLeft(val);
3576
  }
3577
 
3578
+ // SCROLLBARS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3579
 
3580
+ // Prepare DOM reads needed to update the scrollbars. Done in one
3581
+ // shot to minimize update/measure roundtrips.
3582
+ function measureForScrollbars(cm) {
3583
+ var d = cm.display, gutterW = d.gutters.offsetWidth;
3584
+ var docH = Math.round(cm.doc.height + paddingVert(cm.display));
3585
+ return {
3586
+ clientHeight: d.scroller.clientHeight,
3587
+ viewHeight: d.wrapper.clientHeight,
3588
+ scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
3589
+ viewWidth: d.wrapper.clientWidth,
3590
+ barLeft: cm.options.fixedGutter ? gutterW : 0,
3591
+ docHeight: docH,
3592
+ scrollHeight: docH + scrollGap(cm) + d.barHeight,
3593
+ nativeBarWidth: d.nativeBarWidth,
3594
+ gutterWidth: gutterW
3595
+ }
3596
+ }
3597
 
3598
+ var NativeScrollbars = function(place, scroll, cm) {
3599
+ this.cm = cm;
3600
+ var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
3601
+ var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
3602
+ vert.tabIndex = horiz.tabIndex = -1;
3603
+ place(vert); place(horiz);
3604
 
3605
+ on(vert, "scroll", function () {
3606
+ if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); }
3607
+ });
3608
+ on(horiz, "scroll", function () {
3609
+ if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); }
3610
+ });
3611
 
3612
+ this.checkedZeroWidth = false;
3613
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
3614
+ if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; }
3615
+ };
 
 
 
 
 
 
 
 
 
 
3616
 
3617
+ NativeScrollbars.prototype.update = function (measure) {
3618
+ var needsH = measure.scrollWidth > measure.clientWidth + 1;
3619
+ var needsV = measure.scrollHeight > measure.clientHeight + 1;
3620
+ var sWidth = measure.nativeBarWidth;
3621
+
3622
+ if (needsV) {
3623
+ this.vert.style.display = "block";
3624
+ this.vert.style.bottom = needsH ? sWidth + "px" : "0";
3625
+ var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
3626
+ // A bug in IE8 can cause this value to be negative, so guard it.
3627
+ this.vert.firstChild.style.height =
3628
+ Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
3629
+ } else {
3630
+ this.vert.style.display = "";
3631
+ this.vert.firstChild.style.height = "0";
3632
  }
3633
 
3634
+ if (needsH) {
3635
+ this.horiz.style.display = "block";
3636
+ this.horiz.style.right = needsV ? sWidth + "px" : "0";
3637
+ this.horiz.style.left = measure.barLeft + "px";
3638
+ var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
3639
+ this.horiz.firstChild.style.width =
3640
+ Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
3641
+ } else {
3642
+ this.horiz.style.display = "";
3643
+ this.horiz.firstChild.style.width = "0";
3644
  }
3645
 
3646
+ if (!this.checkedZeroWidth && measure.clientHeight > 0) {
3647
+ if (sWidth == 0) { this.zeroWidthHack(); }
3648
+ this.checkedZeroWidth = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3649
  }
 
3650
 
3651
+ return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}
3652
+ };
3653
 
3654
+ NativeScrollbars.prototype.setScrollLeft = function (pos) {
3655
+ if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; }
3656
+ if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); }
3657
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3658
 
3659
+ NativeScrollbars.prototype.setScrollTop = function (pos) {
3660
+ if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; }
3661
+ if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); }
3662
+ };
 
 
 
 
3663
 
3664
+ NativeScrollbars.prototype.zeroWidthHack = function () {
3665
+ var w = mac && !mac_geMountainLion ? "12px" : "18px";
3666
+ this.horiz.style.height = this.vert.style.width = w;
3667
+ this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none";
3668
+ this.disableHoriz = new Delayed;
3669
+ this.disableVert = new Delayed;
3670
+ };
 
 
 
 
 
 
 
3671
 
3672
+ NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) {
3673
+ bar.style.pointerEvents = "auto";
3674
+ function maybeDisable() {
3675
+ // To find out whether the scrollbar is still visible, we
3676
+ // check whether the element under the pixel in the bottom
3677
+ // right corner of the scrollbar box is the scrollbar box
3678
+ // itself (when the bar is still visible) or its filler child
3679
+ // (when the bar is hidden). If it is still visible, we keep
3680
+ // it enabled, if it's hidden, we disable pointer events.
3681
+ var box = bar.getBoundingClientRect();
3682
+ var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2)
3683
+ : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1);
3684
+ if (elt != bar) { bar.style.pointerEvents = "none"; }
3685
+ else { delay.set(1000, maybeDisable); }
3686
+ }
3687
+ delay.set(1000, maybeDisable);
3688
+ };
3689
 
3690
+ NativeScrollbars.prototype.clear = function () {
3691
+ var parent = this.horiz.parentNode;
3692
+ parent.removeChild(this.horiz);
3693
+ parent.removeChild(this.vert);
3694
+ };
3695
 
3696
+ var NullScrollbars = function () {};
 
 
 
 
 
3697
 
3698
+ NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };
3699
+ NullScrollbars.prototype.setScrollLeft = function () {};
3700
+ NullScrollbars.prototype.setScrollTop = function () {};
3701
+ NullScrollbars.prototype.clear = function () {};
3702
 
3703
+ function updateScrollbars(cm, measure) {
3704
+ if (!measure) { measure = measureForScrollbars(cm); }
3705
+ var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
3706
+ updateScrollbarsInner(cm, measure);
3707
+ for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
3708
+ if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
3709
+ { updateHeightsInViewport(cm); }
3710
+ updateScrollbarsInner(cm, measureForScrollbars(cm));
3711
+ startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
 
 
3712
  }
3713
  }
3714
 
3715
+ // Re-synchronize the fake scrollbars with the actual size of the
3716
+ // content.
3717
+ function updateScrollbarsInner(cm, measure) {
3718
+ var d = cm.display;
3719
+ var sizes = d.scrollbars.update(measure);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3720
 
3721
+ d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
3722
+ d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
3723
+ d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent";
3724
+
3725
+ if (sizes.right && sizes.bottom) {
3726
+ d.scrollbarFiller.style.display = "block";
3727
+ d.scrollbarFiller.style.height = sizes.bottom + "px";
3728
+ d.scrollbarFiller.style.width = sizes.right + "px";
3729
+ } else { d.scrollbarFiller.style.display = ""; }
3730
+ if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
3731
+ d.gutterFiller.style.display = "block";
3732
+ d.gutterFiller.style.height = sizes.bottom + "px";
3733
+ d.gutterFiller.style.width = measure.gutterWidth + "px";
3734
+ } else { d.gutterFiller.style.display = ""; }
3735
  }
3736
 
3737
+ var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
 
 
3738
 
3739
+ function initScrollbars(cm) {
3740
+ if (cm.display.scrollbars) {
3741
+ cm.display.scrollbars.clear();
3742
+ if (cm.display.scrollbars.addClass)
3743
+ { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
 
3744
  }
 
 
 
3745
 
3746
+ cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {
3747
+ cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
3748
+ // Prevent clicks in the scrollbars from killing focus
3749
+ on(node, "mousedown", function () {
3750
+ if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); }
3751
+ });
3752
+ node.setAttribute("cm-not-content", "true");
3753
+ }, function (pos, axis) {
3754
+ if (axis == "horizontal") { setScrollLeft(cm, pos); }
3755
+ else { updateScrollTop(cm, pos); }
3756
+ }, cm);
3757
+ if (cm.display.scrollbars.addClass)
3758
+ { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
3759
  }
3760
 
3761
+ // Operations are used to wrap a series of changes to the editor
3762
+ // state in such a way that each change won't have to update the
3763
+ // cursor and display (which would be awkward, slow, and
3764
+ // error-prone). Instead, display updates are batched and then all
3765
+ // combined and executed at once.
 
 
 
 
 
3766
 
3767
+ var nextOpId = 0;
3768
+ // Start a new operation.
3769
+ function startOperation(cm) {
3770
+ cm.curOp = {
3771
+ cm: cm,
3772
+ viewChanged: false, // Flag that indicates that lines might need to be redrawn
3773
+ startHeight: cm.doc.height, // Used to detect need to update scrollbar
3774
+ forceUpdate: false, // Used to force a redraw
3775
+ updateInput: 0, // Whether to reset the input textarea
3776
+ typing: false, // Whether this reset should be careful to leave existing text (for compositing)
3777
+ changeObjs: null, // Accumulated changes, for firing change events
3778
+ cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
3779
+ cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
3780
+ selectionChanged: false, // Whether the selection needs to be redrawn
3781
+ updateMaxLine: false, // Set when the widest line needs to be determined anew
3782
+ scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
3783
+ scrollToPos: null, // Used to scroll to a specific position
3784
+ focus: false,
3785
+ id: ++nextOpId // Unique ID
3786
+ };
3787
+ pushOperation(cm.curOp);
3788
+ }
3789
 
3790
+ // Finish an operation, updating the display and signalling delayed events
3791
+ function endOperation(cm) {
3792
+ var op = cm.curOp;
3793
+ if (op) { finishOperation(op, function (group) {
3794
+ for (var i = 0; i < group.ops.length; i++)
3795
+ { group.ops[i].cm.curOp = null; }
3796
+ endOperations(group);
3797
+ }); }
 
 
 
 
 
 
 
 
3798
  }
3799
+
3800
+ // The DOM updates done when an operation finishes are batched so
3801
+ // that the minimum number of relayouts are required.
3802
+ function endOperations(group) {
3803
+ var ops = group.ops;
3804
+ for (var i = 0; i < ops.length; i++) // Read DOM
3805
+ { endOperation_R1(ops[i]); }
3806
+ for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)
3807
+ { endOperation_W1(ops[i$1]); }
3808
+ for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM
3809
+ { endOperation_R2(ops[i$2]); }
3810
+ for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)
3811
+ { endOperation_W2(ops[i$3]); }
3812
+ for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM
3813
+ { endOperation_finish(ops[i$4]); }
3814
  }
3815
 
3816
+ function endOperation_R1(op) {
3817
+ var cm = op.cm, display = cm.display;
3818
+ maybeClipScrollbars(cm);
3819
+ if (op.updateMaxLine) { findMaxLine(cm); }
3820
 
3821
+ op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
3822
+ op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
3823
+ op.scrollToPos.to.line >= display.viewTo) ||
3824
+ display.maxLineChanged && cm.options.lineWrapping;
3825
+ op.update = op.mustUpdate &&
3826
+ new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
3827
  }
3828
 
3829
+ function endOperation_W1(op) {
3830
+ op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
 
3831
  }
3832
 
3833
+ function endOperation_R2(op) {
3834
+ var cm = op.cm, display = cm.display;
3835
+ if (op.updatedDisplay) { updateHeightsInViewport(cm); }
3836
 
3837
+ op.barMeasure = measureForScrollbars(cm);
 
 
 
 
 
 
3838
 
3839
+ // If the max line changed since it was last measured, measure it,
3840
+ // and ensure the document's width matches it.
3841
+ // updateDisplay_W2 will use these properties to do the actual resizing
3842
+ if (display.maxLineChanged && !cm.options.lineWrapping) {
3843
+ op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
3844
+ cm.display.sizerWidth = op.adjustWidthTo;
3845
+ op.barMeasure.scrollWidth =
3846
+ Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
3847
+ op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
3848
+ }
3849
 
3850
+ if (op.updatedDisplay || op.selectionChanged)
3851
+ { op.preparedSelection = display.input.prepareSelection(); }
 
3852
  }
3853
 
3854
+ function endOperation_W2(op) {
3855
+ var cm = op.cm;
3856
+
3857
+ if (op.adjustWidthTo != null) {
3858
+ cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
3859
+ if (op.maxScrollLeft < cm.doc.scrollLeft)
3860
+ { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); }
3861
+ cm.display.maxLineChanged = false;
3862
  }
 
 
3863
 
3864
+ var takeFocus = op.focus && op.focus == activeElt();
3865
+ if (op.preparedSelection)
3866
+ { cm.display.input.showSelection(op.preparedSelection, takeFocus); }
3867
+ if (op.updatedDisplay || op.startHeight != cm.doc.height)
3868
+ { updateScrollbars(cm, op.barMeasure); }
3869
+ if (op.updatedDisplay)
3870
+ { setDocumentHeight(cm, op.barMeasure); }
3871
 
3872
+ if (op.selectionChanged) { restartBlink(cm); }
3873
+
3874
+ if (cm.state.focused && op.updateInput)
3875
+ { cm.display.input.reset(op.typing); }
3876
+ if (takeFocus) { ensureFocus(op.cm); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3877
  }
3878
 
3879
+ function endOperation_finish(op) {
3880
+ var cm = op.cm, display = cm.display, doc = cm.doc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3881
 
3882
+ if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); }
 
 
3883
 
3884
+ // Abort mouse wheel delta measurement, when scrolling explicitly
3885
+ if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
3886
+ { display.wheelStartX = display.wheelStartY = null; }
 
 
 
 
3887
 
3888
+ // Propagate the scroll position to the actual DOM scroller
3889
+ if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); }
 
 
3890
 
3891
+ if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); }
3892
+ // If we need to scroll a specific position into view, do so.
3893
+ if (op.scrollToPos) {
3894
+ var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
3895
+ clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
3896
+ maybeScrollWindow(cm, rect);
 
 
3897
  }
 
3898
 
3899
+ // Fire events for markers that are hidden/unidden by editing or
3900
+ // undoing
3901
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
3902
+ if (hidden) { for (var i = 0; i < hidden.length; ++i)
3903
+ { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } }
3904
+ if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)
3905
+ { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } }
3906
 
3907
+ if (display.wrapper.offsetHeight)
3908
+ { doc.scrollTop = cm.display.scroller.scrollTop; }
3909
 
3910
+ // Fire change events, and delayed event handlers
3911
+ if (op.changeObjs)
3912
+ { signal(cm, "changes", cm, op.changeObjs); }
3913
+ if (op.update)
3914
+ { op.update.finish(); }
 
 
3915
  }
3916
 
3917
+ // Run the given function in an operation
3918
+ function runInOp(cm, f) {
3919
+ if (cm.curOp) { return f() }
3920
+ startOperation(cm);
3921
+ try { return f() }
3922
+ finally { endOperation(cm); }
3923
+ }
3924
+ // Wraps a function in an operation. Returns the wrapped function.
3925
+ function operation(cm, f) {
3926
+ return function() {
3927
+ if (cm.curOp) { return f.apply(cm, arguments) }
3928
+ startOperation(cm);
3929
+ try { return f.apply(cm, arguments) }
3930
+ finally { endOperation(cm); }
3931
+ }
3932
+ }
3933
+ // Used to add methods to editor and doc instances, wrapping them in
3934
+ // operations.
3935
+ function methodOp(f) {
3936
+ return function() {
3937
+ if (this.curOp) { return f.apply(this, arguments) }
3938
+ startOperation(this);
3939
+ try { return f.apply(this, arguments) }
3940
+ finally { endOperation(this); }
3941
+ }
3942
+ }
3943
+ function docMethodOp(f) {
3944
+ return function() {
3945
+ var cm = this.cm;
3946
+ if (!cm || cm.curOp) { return f.apply(this, arguments) }
3947
+ startOperation(cm);
3948
+ try { return f.apply(this, arguments) }
3949
+ finally { endOperation(cm); }
3950
  }
3951
+ }
3952
 
3953
+ // HIGHLIGHT WORKER
 
 
 
 
 
3954
 
3955
+ function startWorker(cm, time) {
3956
+ if (cm.doc.highlightFrontier < cm.display.viewTo)
3957
+ { cm.state.highlight.set(time, bind(highlightWorker, cm)); }
3958
+ }
3959
 
3960
+ function highlightWorker(cm) {
3961
+ var doc = cm.doc;
3962
+ if (doc.highlightFrontier >= cm.display.viewTo) { return }
3963
+ var end = +new Date + cm.options.workTime;
3964
+ var context = getContextBefore(cm, doc.highlightFrontier);
3965
+ var changedLines = [];
3966
+
3967
+ doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
3968
+ if (context.line >= cm.display.viewFrom) { // Visible
3969
+ var oldStyles = line.styles;
3970
+ var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null;
3971
+ var highlighted = highlightLine(cm, line, context, true);
3972
+ if (resetState) { context.state = resetState; }
3973
+ line.styles = highlighted.styles;
3974
+ var oldCls = line.styleClasses, newCls = highlighted.classes;
3975
+ if (newCls) { line.styleClasses = newCls; }
3976
+ else if (oldCls) { line.styleClasses = null; }
3977
+ var ischange = !oldStyles || oldStyles.length != line.styles.length ||
3978
+ oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
3979
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; }
3980
+ if (ischange) { changedLines.push(context.line); }
3981
+ line.stateAfter = context.save();
3982
+ context.nextLine();
3983
+ } else {
3984
+ if (line.text.length <= cm.options.maxHighlightLength)
3985
+ { processLine(cm, line.text, context); }
3986
+ line.stateAfter = context.line % 5 == 0 ? context.save() : null;
3987
+ context.nextLine();
3988
+ }
3989
+ if (+new Date > end) {
3990
+ startWorker(cm, cm.options.workDelay);
3991
+ return true
3992
  }
3993
+ });
3994
+ doc.highlightFrontier = context.line;
3995
+ doc.modeFrontier = Math.max(doc.modeFrontier, context.line);
3996
+ if (changedLines.length) { runInOp(cm, function () {
3997
+ for (var i = 0; i < changedLines.length; i++)
3998
+ { regLineChange(cm, changedLines[i], "text"); }
3999
+ }); }
4000
+ }
4001
 
4002
+ // DISPLAY DRAWING
4003
 
4004
+ var DisplayUpdate = function(cm, viewport, force) {
4005
+ var display = cm.display;
 
 
4006
 
4007
+ this.viewport = viewport;
4008
+ // Store some values that we'll need later (but don't want to force a relayout for)
4009
+ this.visible = visibleLines(display, cm.doc, viewport);
4010
+ this.editorIsHidden = !display.wrapper.offsetWidth;
4011
+ this.wrapperHeight = display.wrapper.clientHeight;
4012
+ this.wrapperWidth = display.wrapper.clientWidth;
4013
+ this.oldDisplayWidth = displayWidth(cm);
4014
+ this.force = force;
4015
+ this.dims = getDimensions(cm);
4016
+ this.events = [];
4017
+ };
4018
 
4019
+ DisplayUpdate.prototype.signal = function (emitter, type) {
4020
+ if (hasHandler(emitter, type))
4021
+ { this.events.push(arguments); }
4022
+ };
4023
+ DisplayUpdate.prototype.finish = function () {
4024
+ for (var i = 0; i < this.events.length; i++)
4025
+ { signal.apply(null, this.events[i]); }
4026
+ };
4027
+
4028
+ function maybeClipScrollbars(cm) {
4029
+ var display = cm.display;
4030
+ if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
4031
+ display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
4032
+ display.heightForcer.style.height = scrollGap(cm) + "px";
4033
+ display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
4034
+ display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
4035
+ display.scrollbarsClipped = true;
4036
  }
4037
  }
4038
 
4039
+ function selectionSnapshot(cm) {
4040
+ if (cm.hasFocus()) { return null }
4041
+ var active = activeElt();
4042
+ if (!active || !contains(cm.display.lineDiv, active)) { return null }
4043
+ var result = {activeElt: active};
4044
+ if (window.getSelection) {
4045
+ var sel = window.getSelection();
4046
+ if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) {
4047
+ result.anchorNode = sel.anchorNode;
4048
+ result.anchorOffset = sel.anchorOffset;
4049
+ result.focusNode = sel.focusNode;
4050
+ result.focusOffset = sel.focusOffset;
4051
+ }
4052
  }
4053
+ return result
4054
+ }
4055
 
4056
+ function restoreSelection(snapshot) {
4057
+ if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return }
4058
+ snapshot.activeElt.focus();
4059
+ if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) &&
4060
+ snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {
4061
+ var sel = window.getSelection(), range = document.createRange();
4062
+ range.setEnd(snapshot.anchorNode, snapshot.anchorOffset);
4063
+ range.collapse(false);
4064
+ sel.removeAllRanges();
4065
+ sel.addRange(range);
4066
+ sel.extend(snapshot.focusNode, snapshot.focusOffset);
4067
  }
 
 
 
 
 
 
 
4068
  }
4069
 
4070
+ // Does the actual updating of the line display. Bails out
4071
+ // (returning false) when there is nothing to be done and forced is
4072
+ // false.
4073
+ function updateDisplayIfNeeded(cm, update) {
4074
+ var display = cm.display, doc = cm.doc;
4075
 
4076
+ if (update.editorIsHidden) {
4077
+ resetView(cm);
4078
+ return false
 
 
 
 
 
 
4079
  }
4080
 
4081
+ // Bail out if the visible area is already rendered and nothing changed.
4082
+ if (!update.force &&
4083
+ update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
4084
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
4085
+ display.renderedView == display.view && countDirtyView(cm) == 0)
4086
+ { return false }
4087
 
4088
+ if (maybeUpdateLineNumberWidth(cm)) {
4089
+ resetView(cm);
4090
+ update.dims = getDimensions(cm);
 
 
 
 
 
 
 
 
4091
  }
4092
 
4093
+ // Compute a suitable new viewport (from & to)
4094
+ var end = doc.first + doc.size;
4095
+ var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
4096
+ var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
4097
+ if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); }
4098
+ if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); }
4099
+ if (sawCollapsedSpans) {
4100
+ from = visualLineNo(cm.doc, from);
4101
+ to = visualLineEndNo(cm.doc, to);
4102
+ }
4103
 
4104
+ var different = from != display.viewFrom || to != display.viewTo ||
4105
+ display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
4106
+ adjustView(cm, from, to);
 
 
 
 
 
4107
 
4108
+ display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
4109
+ // Position the mover div to align with the current scroll position
4110
+ cm.display.mover.style.top = display.viewOffset + "px";
 
 
 
 
 
 
 
 
 
 
4111
 
4112
+ var toUpdate = countDirtyView(cm);
4113
+ if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
4114
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
4115
+ { return false }
 
 
4116
 
4117
+ // For big changes, we hide the enclosing element during the
4118
+ // update, since that speeds up the operations on most browsers.
4119
+ var selSnapshot = selectionSnapshot(cm);
4120
+ if (toUpdate > 4) { display.lineDiv.style.display = "none"; }
4121
+ patchDisplay(cm, display.updateLineNumbers, update.dims);
4122
+ if (toUpdate > 4) { display.lineDiv.style.display = ""; }
4123
+ display.renderedView = display.view;
4124
+ // There might have been a widget with a focused element that got
4125
+ // hidden or updated, if so re-focus it.
4126
+ restoreSelection(selSnapshot);
4127
 
4128
+ // Prevent selection and cursors from interfering with the scroll
4129
+ // width and height.
4130
+ removeChildren(display.cursorDiv);
4131
+ removeChildren(display.selectionDiv);
4132
+ display.gutters.style.height = display.sizer.style.minHeight = 0;
4133
 
4134
+ if (different) {
4135
+ display.lastWrapHeight = update.wrapperHeight;
4136
+ display.lastWrapWidth = update.wrapperWidth;
4137
+ startWorker(cm, 400);
 
 
 
 
 
 
 
4138
  }
 
4139
 
4140
+ display.updateLineNumbers = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4141
 
4142
+ return true
 
 
 
 
4143
  }
4144
 
4145
+ function postUpdateDisplay(cm, update) {
4146
+ var viewport = update.viewport;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4147
 
4148
+ for (var first = true;; first = false) {
4149
+ if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
4150
+ // Clip forced viewport to actual scrollable area.
4151
+ if (viewport && viewport.top != null)
4152
+ { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; }
4153
+ // Updated line heights might result in the drawn area not
4154
+ // actually covering the viewport. Keep looping until it does.
4155
+ update.visible = visibleLines(cm.display, cm.doc, viewport);
4156
+ if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
4157
+ { break }
4158
+ } else if (first) {
4159
+ update.visible = visibleLines(cm.display, cm.doc, viewport);
4160
+ }
4161
+ if (!updateDisplayIfNeeded(cm, update)) { break }
4162
+ updateHeightsInViewport(cm);
4163
+ var barMeasure = measureForScrollbars(cm);
4164
+ updateSelection(cm);
4165
+ updateScrollbars(cm, barMeasure);
4166
+ setDocumentHeight(cm, barMeasure);
4167
+ update.force = false;
4168
+ }
4169
 
4170
+ update.signal(cm, "update", cm);
4171
+ if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
4172
+ update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
4173
+ cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
 
 
 
 
4174
  }
 
4175
  }
4176
 
4177
+ function updateDisplaySimple(cm, viewport) {
4178
+ var update = new DisplayUpdate(cm, viewport);
4179
+ if (updateDisplayIfNeeded(cm, update)) {
4180
+ updateHeightsInViewport(cm);
4181
+ postUpdateDisplay(cm, update);
4182
+ var barMeasure = measureForScrollbars(cm);
4183
+ updateSelection(cm);
4184
+ updateScrollbars(cm, barMeasure);
4185
+ setDocumentHeight(cm, barMeasure);
4186
+ update.finish();
 
 
 
 
4187
  }
4188
  }
4189
 
4190
+ // Sync the actual display DOM structure with display.view, removing
4191
+ // nodes for lines that are no longer in view, and creating the ones
4192
+ // that are not there yet, and updating the ones that are out of
4193
+ // date.
4194
+ function patchDisplay(cm, updateNumbersFrom, dims) {
4195
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
4196
+ var container = display.lineDiv, cur = container.firstChild;
 
 
 
 
 
 
 
 
 
4197
 
4198
+ function rm(node) {
4199
+ var next = node.nextSibling;
4200
+ // Works around a throw-scroll bug in OS X Webkit
4201
+ if (webkit && mac && cm.display.currentWheelTarget == node)
4202
+ { node.style.display = "none"; }
4203
+ else
4204
+ { node.parentNode.removeChild(node); }
4205
+ return next
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4206
  }
 
 
 
 
 
 
4207
 
4208
+ var view = display.view, lineN = display.viewFrom;
4209
+ // Loop over the elements in the view, syncing cur (the DOM nodes
4210
+ // in display.lineDiv) with the view as we go.
4211
+ for (var i = 0; i < view.length; i++) {
4212
+ var lineView = view[i];
4213
+ if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
4214
+ var node = buildLineElement(cm, lineView, lineN, dims);
4215
+ container.insertBefore(node, cur);
4216
+ } else { // Already drawn
4217
+ while (cur != lineView.node) { cur = rm(cur); }
4218
+ var updateNumber = lineNumbers && updateNumbersFrom != null &&
4219
+ updateNumbersFrom <= lineN && lineView.lineNumber;
4220
+ if (lineView.changes) {
4221
+ if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; }
4222
+ updateLineForChanges(cm, lineView, lineN, dims);
4223
+ }
4224
+ if (updateNumber) {
4225
+ removeChildren(lineView.lineNumber);
4226
+ lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
4227
  }
4228
+ cur = lineView.node.nextSibling;
4229
  }
4230
+ lineN += lineView.size;
4231
  }
4232
+ while (cur) { cur = rm(cur); }
4233
  }
4234
 
4235
+ function updateGutterSpace(display) {
4236
+ var width = display.gutters.offsetWidth;
4237
+ display.sizer.style.marginLeft = width + "px";
 
 
 
 
 
 
 
4238
  }
4239
 
4240
+ function setDocumentHeight(cm, measure) {
4241
+ cm.display.sizer.style.minHeight = measure.docHeight + "px";
4242
+ cm.display.heightForcer.style.top = measure.docHeight + "px";
4243
+ cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4244
  }
4245
 
4246
+ // Re-align line numbers and gutter marks to compensate for
4247
+ // horizontal scrolling.
4248
+ function alignHorizontally(cm) {
4249
+ var display = cm.display, view = display.view;
4250
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
4251
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
4252
+ var gutterW = display.gutters.offsetWidth, left = comp + "px";
4253
+ for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
4254
+ if (cm.options.fixedGutter) {
4255
+ if (view[i].gutter)
4256
+ { view[i].gutter.style.left = left; }
4257
+ if (view[i].gutterBackground)
4258
+ { view[i].gutterBackground.style.left = left; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4259
  }
4260
+ var align = view[i].alignable;
4261
+ if (align) { for (var j = 0; j < align.length; j++)
4262
+ { align[j].style.left = left; } }
4263
+ } }
4264
+ if (cm.options.fixedGutter)
4265
+ { display.gutters.style.left = (comp + gutterW) + "px"; }
4266
  }
4267
 
4268
+ // Used to ensure that the line number gutter is still the right
4269
+ // size for the current document size. Returns true when an update
4270
+ // is needed.
4271
+ function maybeUpdateLineNumberWidth(cm) {
4272
+ if (!cm.options.lineNumbers) { return false }
4273
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
4274
+ if (last.length != display.lineNumChars) {
4275
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
4276
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
4277
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
4278
+ display.lineGutter.style.width = "";
4279
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
4280
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
4281
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
4282
+ display.lineGutter.style.width = display.lineNumWidth + "px";
4283
+ updateGutterSpace(cm.display);
4284
+ return true
4285
  }
4286
+ return false
4287
  }
4288
 
4289
+ function getGutters(gutters, lineNumbers) {
4290
+ var result = [], sawLineNumbers = false;
4291
+ for (var i = 0; i < gutters.length; i++) {
4292
+ var name = gutters[i], style = null;
4293
+ if (typeof name != "string") { style = name.style; name = name.className; }
4294
+ if (name == "CodeMirror-linenumbers") {
4295
+ if (!lineNumbers) { continue }
4296
+ else { sawLineNumbers = true; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4297
  }
4298
+ result.push({className: name, style: style});
4299
+ }
4300
+ if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); }
4301
+ return result
4302
+ }
4303
 
4304
+ // Rebuild the gutter elements, ensure the margin to the left of the
4305
+ // code matches their width.
4306
+ function renderGutters(display) {
4307
+ var gutters = display.gutters, specs = display.gutterSpecs;
4308
+ removeChildren(gutters);
4309
+ display.lineGutter = null;
4310
+ for (var i = 0; i < specs.length; ++i) {
4311
+ var ref = specs[i];
4312
+ var className = ref.className;
4313
+ var style = ref.style;
4314
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className));
4315
+ if (style) { gElt.style.cssText = style; }
4316
+ if (className == "CodeMirror-linenumbers") {
4317
+ display.lineGutter = gElt;
4318
+ gElt.style.width = (display.lineNumWidth || 1) + "px";
 
 
 
 
 
 
 
 
 
 
4319
  }
4320
+ }
4321
+ gutters.style.display = specs.length ? "" : "none";
4322
+ updateGutterSpace(display);
4323
+ }
 
 
 
 
 
 
 
4324
 
4325
+ function updateGutters(cm) {
4326
+ renderGutters(cm.display);
4327
+ regChange(cm);
4328
+ alignHorizontally(cm);
4329
+ }
 
 
 
 
 
 
 
 
 
 
4330
 
4331
+ // The display handles the DOM integration, both for input reading
4332
+ // and content drawing. It holds references to DOM nodes and
4333
+ // display-related state.
 
 
4334
 
4335
+ function Display(place, doc, input, options) {
4336
+ var d = this;
4337
+ this.input = input;
4338
 
4339
+ // Covers bottom-right square when both scrollbars are present.
4340
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
4341
+ d.scrollbarFiller.setAttribute("cm-not-content", "true");
4342
+ // Covers bottom of gutter when coverGutterNextToScrollbar is on
4343
+ // and h scrollbar is present.
4344
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
4345
+ d.gutterFiller.setAttribute("cm-not-content", "true");
4346
+ // Will contain the actual code, positioned to cover the viewport.
4347
+ d.lineDiv = eltP("div", null, "CodeMirror-code");
4348
+ // Elements are added to these to represent selection and cursors.
4349
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
4350
+ d.cursorDiv = elt("div", null, "CodeMirror-cursors");
4351
+ // A visibility: hidden element used to find the size of things.
4352
+ d.measure = elt("div", null, "CodeMirror-measure");
4353
+ // When lines outside of the viewport are measured, they are drawn in this.
4354
+ d.lineMeasure = elt("div", null, "CodeMirror-measure");
4355
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
4356
+ d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
4357
+ null, "position: relative; outline: none");
4358
+ var lines = eltP("div", [d.lineSpace], "CodeMirror-lines");
4359
+ // Moved around its parent to cover visible view.
4360
+ d.mover = elt("div", [lines], null, "position: relative");
4361
+ // Set to the height of the document, allowing scrolling.
4362
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
4363
+ d.sizerWidth = null;
4364
+ // Behavior of elts with overflow: auto and padding is
4365
+ // inconsistent across browsers. This is used to ensure the
4366
+ // scrollable area is big enough.
4367
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
4368
+ // Will contain the gutters, if any.
4369
+ d.gutters = elt("div", null, "CodeMirror-gutters");
4370
+ d.lineGutter = null;
4371
+ // Actual scrollable element.
4372
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
4373
+ d.scroller.setAttribute("tabIndex", "-1");
4374
+ // The element in which the editor lives.
4375
+ d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
4376
 
4377
+ // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
4378
+ if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
4379
+ if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; }
4380
 
4381
+ if (place) {
4382
+ if (place.appendChild) { place.appendChild(d.wrapper); }
4383
+ else { place(d.wrapper); }
4384
+ }
4385
 
4386
+ // Current rendered range (may be bigger than the view window).
4387
+ d.viewFrom = d.viewTo = doc.first;
4388
+ d.reportedViewFrom = d.reportedViewTo = doc.first;
4389
+ // Information about the rendered lines.
4390
+ d.view = [];
4391
+ d.renderedView = null;
4392
+ // Holds info about a single rendered line when it was rendered
4393
+ // for measurement, while not in view.
4394
+ d.externalMeasured = null;
4395
+ // Empty space (in pixels) above the view
4396
+ d.viewOffset = 0;
4397
+ d.lastWrapHeight = d.lastWrapWidth = 0;
4398
+ d.updateLineNumbers = null;
4399
 
4400
+ d.nativeBarWidth = d.barHeight = d.barWidth = 0;
4401
+ d.scrollbarsClipped = false;
4402
 
4403
+ // Used to only resize the line number gutter when necessary (when
4404
+ // the amount of lines crosses a boundary that makes its width change)
4405
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
4406
+ // Set to true when a non-horizontal-scrolling line widget is
4407
+ // added. As an optimization, line widget aligning is skipped when
4408
+ // this is false.
4409
+ d.alignWidgets = false;
 
4410
 
4411
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
 
 
 
 
 
 
 
 
 
 
4412
 
4413
+ // Tracks the maximum line length so that the horizontal scrollbar
4414
+ // can be kept static when scrolling.
4415
+ d.maxLine = null;
4416
+ d.maxLineLength = 0;
4417
+ d.maxLineChanged = false;
4418
 
4419
+ // Used for measuring wheel scrolling granularity
4420
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
4421
 
4422
+ // True when shift is held down.
4423
+ d.shift = false;
 
 
 
 
 
 
 
 
 
 
 
 
4424
 
4425
+ // Used to track whether anything happened since the context menu
4426
+ // was opened.
4427
+ d.selForContextMenu = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4428
 
4429
+ d.activeTouch = null;
 
 
4430
 
4431
+ d.gutterSpecs = getGutters(options.gutters, options.lineNumbers);
4432
+ renderGutters(d);
 
 
4433
 
4434
+ input.init(d);
4435
+ }
 
 
 
 
 
 
 
4436
 
4437
+ // Since the delta values reported on mouse wheel events are
4438
+ // unstandardized between browsers and even browser versions, and
4439
+ // generally horribly unpredictable, this code starts by measuring
4440
+ // the scroll effect that the first few mouse wheel events have,
4441
+ // and, from that, detects the way it can convert deltas to pixel
4442
+ // offsets afterwards.
4443
+ //
4444
+ // The reason we want to know the amount a wheel event will scroll
4445
+ // is that it gives us a chance to update the display before the
4446
+ // actual scrolling happens, reducing flickering.
4447
 
4448
+ var wheelSamples = 0, wheelPixelsPerUnit = null;
4449
+ // Fill in a browser-detected starting value on browsers where we
4450
+ // know one. These don't have to be accurate -- the result of them
4451
+ // being wrong would just be a slight flicker on the first wheel
4452
+ // scroll (if it is large enough).
4453
+ if (ie) { wheelPixelsPerUnit = -.53; }
4454
+ else if (gecko) { wheelPixelsPerUnit = 15; }
4455
+ else if (chrome) { wheelPixelsPerUnit = -.7; }
4456
+ else if (safari) { wheelPixelsPerUnit = -1/3; }
 
4457
 
4458
+ function wheelEventDelta(e) {
4459
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
4460
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; }
4461
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; }
4462
+ else if (dy == null) { dy = e.wheelDelta; }
4463
+ return {x: dx, y: dy}
4464
+ }
4465
+ function wheelEventPixels(e) {
4466
+ var delta = wheelEventDelta(e);
4467
+ delta.x *= wheelPixelsPerUnit;
4468
+ delta.y *= wheelPixelsPerUnit;
4469
+ return delta
4470
+ }
4471
 
4472
+ function onScrollWheel(cm, e) {
4473
+ var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4474
 
4475
+ var display = cm.display, scroll = display.scroller;
4476
+ // Quit if there's nothing to scroll here
4477
+ var canScrollX = scroll.scrollWidth > scroll.clientWidth;
4478
+ var canScrollY = scroll.scrollHeight > scroll.clientHeight;
4479
+ if (!(dx && canScrollX || dy && canScrollY)) { return }
 
 
 
 
 
 
 
 
 
 
 
 
4480
 
4481
+ // Webkit browsers on OS X abort momentum scrolls when the target
4482
+ // of the scroll event is removed from the scrollable element.
4483
+ // This hack (see related code in patchDisplay) makes sure the
4484
+ // element is kept around.
4485
+ if (dy && mac && webkit) {
4486
+ outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
4487
+ for (var i = 0; i < view.length; i++) {
4488
+ if (view[i].node == cur) {
4489
+ cm.display.currentWheelTarget = cur;
4490
+ break outer
4491
+ }
4492
+ }
4493
+ }
4494
+ }
4495
 
4496
+ // On some browsers, horizontal scrolling will cause redraws to
4497
+ // happen before the gutter has been realigned, causing it to
4498
+ // wriggle around in a most unseemly way. When we have an
4499
+ // estimated pixels/delta value, we just handle horizontal
4500
+ // scrolling entirely here. It'll be slightly off from native, but
4501
+ // better than glitching out.
4502
+ if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
4503
+ if (dy && canScrollY)
4504
+ { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); }
4505
+ setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit));
4506
+ // Only prevent default scrolling if vertical scrolling is
4507
+ // actually possible. Otherwise, it causes vertical scroll
4508
+ // jitter on OSX trackpads when deltaX is small and deltaY
4509
+ // is large (issue #3579)
4510
+ if (!dy || (dy && canScrollY))
4511
+ { e_preventDefault(e); }
4512
+ display.wheelStartX = null; // Abort measurement, if in progress
4513
+ return
4514
+ }
4515
 
4516
+ // 'Project' the visible viewport to cover the area that is being
4517
+ // scrolled into view (if we know enough to estimate it).
4518
+ if (dy && wheelPixelsPerUnit != null) {
4519
+ var pixels = dy * wheelPixelsPerUnit;
4520
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
4521
+ if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
4522
+ else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
4523
+ updateDisplaySimple(cm, {top: top, bottom: bot});
4524
+ }
 
 
 
4525
 
4526
+ if (wheelSamples < 20) {
4527
+ if (display.wheelStartX == null) {
4528
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
4529
+ display.wheelDX = dx; display.wheelDY = dy;
4530
+ setTimeout(function () {
4531
+ if (display.wheelStartX == null) { return }
4532
+ var movedX = scroll.scrollLeft - display.wheelStartX;
4533
+ var movedY = scroll.scrollTop - display.wheelStartY;
4534
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
4535
+ (movedX && display.wheelDX && movedX / display.wheelDX);
4536
+ display.wheelStartX = display.wheelStartY = null;
4537
+ if (!sample) { return }
4538
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
4539
+ ++wheelSamples;
4540
+ }, 200);
4541
  } else {
4542
+ display.wheelDX += dx; display.wheelDY += dy;
 
 
 
 
4543
  }
4544
+ }
4545
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4546
 
4547
+ // Selection objects are immutable. A new one is created every time
4548
+ // the selection changes. A selection is one or more non-overlapping
4549
+ // (and non-touching) ranges, sorted, and an integer that indicates
4550
+ // which one is the primary selection (the one that's scrolled into
4551
+ // view, that getCursor returns, etc).
4552
+ var Selection = function(ranges, primIndex) {
4553
+ this.ranges = ranges;
4554
+ this.primIndex = primIndex;
4555
+ };
 
 
 
 
4556
 
4557
+ Selection.prototype.primary = function () { return this.ranges[this.primIndex] };
 
 
 
 
 
 
 
 
 
 
4558
 
4559
+ Selection.prototype.equals = function (other) {
4560
+ if (other == this) { return true }
4561
+ if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
4562
+ for (var i = 0; i < this.ranges.length; i++) {
4563
+ var here = this.ranges[i], there = other.ranges[i];
4564
+ if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false }
4565
+ }
4566
+ return true
4567
  };
 
4568
 
4569
+ Selection.prototype.deepCopy = function () {
4570
+ var out = [];
4571
+ for (var i = 0; i < this.ranges.length; i++)
4572
+ { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); }
4573
+ return new Selection(out, this.primIndex)
4574
+ };
4575
 
4576
+ Selection.prototype.somethingSelected = function () {
4577
+ for (var i = 0; i < this.ranges.length; i++)
4578
+ { if (!this.ranges[i].empty()) { return true } }
4579
+ return false
4580
+ };
4581
 
4582
+ Selection.prototype.contains = function (pos, end) {
4583
+ if (!end) { end = pos; }
4584
+ for (var i = 0; i < this.ranges.length; i++) {
4585
+ var range = this.ranges[i];
4586
+ if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
4587
+ { return i }
4588
+ }
4589
+ return -1
4590
+ };
4591
 
4592
+ var Range = function(anchor, head) {
4593
+ this.anchor = anchor; this.head = head;
4594
+ };
4595
 
4596
+ Range.prototype.from = function () { return minPos(this.anchor, this.head) };
4597
+ Range.prototype.to = function () { return maxPos(this.anchor, this.head) };
4598
+ Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch };
 
 
 
 
 
 
4599
 
4600
+ // Take an unsorted, potentially overlapping set of ranges, and
4601
+ // build a selection out of it. 'Consumes' ranges array (modifying
4602
+ // it).
4603
+ function normalizeSelection(cm, ranges, primIndex) {
4604
+ var mayTouch = cm && cm.options.selectionsMayTouch;
4605
+ var prim = ranges[primIndex];
4606
+ ranges.sort(function (a, b) { return cmp(a.from(), b.from()); });
4607
+ primIndex = indexOf(ranges, prim);
4608
+ for (var i = 1; i < ranges.length; i++) {
4609
+ var cur = ranges[i], prev = ranges[i - 1];
4610
+ var diff = cmp(prev.to(), cur.from());
4611
+ if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) {
4612
+ var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
4613
+ var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
4614
+ if (i <= primIndex) { --primIndex; }
4615
+ ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
4616
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4617
  }
4618
+ return new Selection(ranges, primIndex)
4619
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4620
 
4621
+ function simpleSelection(anchor, head) {
4622
+ return new Selection([new Range(anchor, head || anchor)], 0)
4623
+ }
4624
 
4625
+ // Compute the position of the end of a change (its 'to' property
4626
+ // refers to the pre-change end).
4627
+ function changeEnd(change) {
4628
+ if (!change.text) { return change.to }
4629
+ return Pos(change.from.line + change.text.length - 1,
4630
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))
4631
+ }
4632
 
4633
+ // Adjust a position to refer to the post-change position of the
4634
+ // same text, or the end of the change if the change covers it.
4635
+ function adjustForChange(pos, change) {
4636
+ if (cmp(pos, change.from) < 0) { return pos }
4637
+ if (cmp(pos, change.to) <= 0) { return changeEnd(change) }
 
 
 
 
4638
 
4639
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
4640
+ if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; }
4641
+ return Pos(line, ch)
4642
+ }
4643
 
4644
+ function computeSelAfterChange(doc, change) {
4645
+ var out = [];
4646
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
4647
+ var range = doc.sel.ranges[i];
4648
+ out.push(new Range(adjustForChange(range.anchor, change),
4649
+ adjustForChange(range.head, change)));
 
 
 
 
 
 
4650
  }
4651
+ return normalizeSelection(doc.cm, out, doc.sel.primIndex)
4652
+ }
 
4653
 
4654
+ function offsetPos(pos, old, nw) {
4655
+ if (pos.line == old.line)
4656
+ { return Pos(nw.line, pos.ch - old.ch + nw.ch) }
4657
+ else
4658
+ { return Pos(nw.line + (pos.line - old.line), pos.ch) }
4659
+ }
4660
+
4661
+ // Used by replaceSelections to allow moving the selection to the
4662
+ // start or around the replaced test. Hint may be "start" or "around".
4663
+ function computeReplacedSel(doc, changes, hint) {
4664
+ var out = [];
4665
+ var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
4666
+ for (var i = 0; i < changes.length; i++) {
4667
+ var change = changes[i];
4668
+ var from = offsetPos(change.from, oldPrev, newPrev);
4669
+ var to = offsetPos(changeEnd(change), oldPrev, newPrev);
4670
+ oldPrev = change.to;
4671
+ newPrev = to;
4672
+ if (hint == "around") {
4673
+ var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
4674
+ out[i] = new Range(inv ? to : from, inv ? from : to);
4675
+ } else {
4676
+ out[i] = new Range(from, from);
4677
  }
4678
  }
4679
+ return new Selection(out, doc.sel.primIndex)
4680
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4681
 
4682
+ // Used to get the editor into a consistent state again when options change.
 
 
 
 
 
 
4683
 
4684
+ function loadMode(cm) {
4685
+ cm.doc.mode = getMode(cm.options, cm.doc.modeOption);
4686
+ resetModeState(cm);
4687
+ }
4688
 
4689
+ function resetModeState(cm) {
4690
+ cm.doc.iter(function (line) {
4691
+ if (line.stateAfter) { line.stateAfter = null; }
4692
+ if (line.styles) { line.styles = null; }
4693
+ });
4694
+ cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first;
4695
+ startWorker(cm, 100);
4696
+ cm.state.modeGen++;
4697
+ if (cm.curOp) { regChange(cm); }
4698
+ }
4699
 
4700
+ // DOCUMENT DATA STRUCTURE
4701
 
4702
+ // By default, updates that start and end at the beginning of a line
4703
+ // are treated specially, in order to make the association of line
4704
+ // widgets and marker elements with the text behave more intuitive.
4705
+ function isWholeLineUpdate(doc, change) {
4706
+ return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
4707
+ (!doc.cm || doc.cm.options.wholeLineUpdateBefore)
4708
+ }
4709
 
4710
+ // Perform a change on the document data structure.
4711
+ function updateDoc(doc, change, markedSpans, estimateHeight) {
4712
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null}
4713
+ function update(line, text, spans) {
4714
+ updateLine(line, text, spans, estimateHeight);
4715
+ signalLater(line, "change", line, change);
 
 
4716
  }
4717
+ function linesFor(start, end) {
4718
+ var result = [];
4719
+ for (var i = start; i < end; ++i)
4720
+ { result.push(new Line(text[i], spansFor(i), estimateHeight)); }
4721
+ return result
 
 
 
 
 
 
 
 
 
 
4722
  }
 
 
4723
 
4724
+ var from = change.from, to = change.to, text = change.text;
4725
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
4726
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
4727
 
4728
+ // Adjust the line structure
4729
+ if (change.full) {
4730
+ doc.insert(0, linesFor(0, text.length));
4731
+ doc.remove(text.length, doc.size - text.length);
4732
+ } else if (isWholeLineUpdate(doc, change)) {
4733
+ // This is a whole-line replace. Treated specially to make
4734
+ // sure line objects move the way they are supposed to.
4735
+ var added = linesFor(0, text.length - 1);
4736
+ update(lastLine, lastLine.text, lastSpans);
4737
+ if (nlines) { doc.remove(from.line, nlines); }
4738
+ if (added.length) { doc.insert(from.line, added); }
4739
+ } else if (firstLine == lastLine) {
4740
+ if (text.length == 1) {
4741
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
4742
+ } else {
4743
+ var added$1 = linesFor(1, text.length - 1);
4744
+ added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
4745
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4746
+ doc.insert(from.line + 1, added$1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4747
  }
4748
+ } else if (text.length == 1) {
4749
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
4750
+ doc.remove(from.line + 1, nlines);
4751
+ } else {
4752
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
4753
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
4754
+ var added$2 = linesFor(1, text.length - 1);
4755
+ if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); }
4756
+ doc.insert(from.line + 1, added$2);
4757
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4758
 
4759
+ signalLater(doc, "change", doc, change);
4760
+ }
4761
 
4762
+ // Call f for all linked documents.
4763
+ function linkedDocs(doc, f, sharedHistOnly) {
4764
+ function propagate(doc, skip, sharedHist) {
4765
+ if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {
4766
+ var rel = doc.linked[i];
4767
+ if (rel.doc == skip) { continue }
4768
+ var shared = sharedHist && rel.sharedHist;
4769
+ if (sharedHistOnly && !shared) { continue }
4770
+ f(rel.doc, shared);
4771
+ propagate(rel.doc, doc, shared);
4772
+ } }
4773
+ }
4774
+ propagate(doc, null, true);
4775
+ }
4776
 
4777
+ // Attach a document to an editor.
4778
+ function attachDoc(cm, doc) {
4779
+ if (doc.cm) { throw new Error("This document is already in use.") }
4780
+ cm.doc = doc;
4781
+ doc.cm = cm;
4782
+ estimateLineHeights(cm);
4783
+ loadMode(cm);
4784
+ setDirectionClass(cm);
4785
+ if (!cm.options.lineWrapping) { findMaxLine(cm); }
4786
+ cm.options.mode = doc.modeOption;
4787
+ regChange(cm);
4788
+ }
4789
 
4790
+ function setDirectionClass(cm) {
4791
+ (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl");
4792
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4793
 
4794
+ function directionChanged(cm) {
4795
+ runInOp(cm, function () {
4796
+ setDirectionClass(cm);
4797
+ regChange(cm);
4798
+ });
4799
+ }
4800
 
4801
+ function History(startGen) {
4802
+ // Arrays of change events and selections. Doing something adds an
4803
+ // event to done and clears undo. Undoing moves events from done
4804
+ // to undone, redoing moves them in the other direction.
4805
+ this.done = []; this.undone = [];
4806
+ this.undoDepth = Infinity;
4807
+ // Used to track when changes can be merged into a single undo
4808
+ // event
4809
+ this.lastModTime = this.lastSelTime = 0;
4810
+ this.lastOp = this.lastSelOp = null;
4811
+ this.lastOrigin = this.lastSelOrigin = null;
4812
+ // Used by the isClean() method
4813
+ this.generation = this.maxGeneration = startGen || 1;
 
 
 
4814
  }
4815
 
4816
+ // Create a history change event from an updateDoc-style change
4817
+ // object.
4818
+ function historyChangeFromChange(doc, change) {
4819
+ var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
4820
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
4821
+ linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true);
4822
+ return histChange
4823
+ }
 
 
 
4824
 
4825
+ // Pop all selection events off the end of a history array. Stop at
4826
+ // a change event.
4827
+ function clearSelectionEvents(array) {
4828
+ while (array.length) {
4829
+ var last = lst(array);
4830
+ if (last.ranges) { array.pop(); }
4831
+ else { break }
 
 
 
 
 
 
 
 
4832
  }
4833
+ }
 
 
4834
 
4835
+ // Find the top change event in the history. Pop off selection
4836
+ // events that are in the way.
4837
+ function lastChangeEvent(hist, force) {
4838
+ if (force) {
4839
+ clearSelectionEvents(hist.done);
4840
+ return lst(hist.done)
4841
+ } else if (hist.done.length && !lst(hist.done).ranges) {
4842
+ return lst(hist.done)
4843
+ } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
4844
+ hist.done.pop();
4845
+ return lst(hist.done)
4846
+ }
4847
+ }
4848
 
4849
+ // Register a change in the history. Merges changes that are within
4850
+ // a single operation, or are close together with an origin that
4851
+ // allows merging (starting with "+") into a single event.
4852
+ function addChangeToHistory(doc, change, selAfter, opId) {
4853
+ var hist = doc.history;
4854
+ hist.undone.length = 0;
4855
+ var time = +new Date, cur;
4856
+ var last;
4857
+
4858
+ if ((hist.lastOp == opId ||
4859
+ hist.lastOrigin == change.origin && change.origin &&
4860
+ ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
4861
+ change.origin.charAt(0) == "*")) &&
4862
+ (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
4863
+ // Merge this change into the last event
4864
+ last = lst(cur.changes);
4865
+ if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
4866
+ // Optimized case for simple insertion -- don't want to add
4867
+ // new changesets for every character typed
4868
+ last.to = changeEnd(change);
4869
+ } else {
4870
+ // Add new sub-event
4871
+ cur.changes.push(historyChangeFromChange(doc, change));
4872
+ }
4873
+ } else {
4874
+ // Can not be merged, start a new event.
4875
+ var before = lst(hist.done);
4876
+ if (!before || !before.ranges)
4877
+ { pushSelectionToHistory(doc.sel, hist.done); }
4878
+ cur = {changes: [historyChangeFromChange(doc, change)],
4879
+ generation: hist.generation};
4880
+ hist.done.push(cur);
4881
+ while (hist.done.length > hist.undoDepth) {
4882
+ hist.done.shift();
4883
+ if (!hist.done[0].ranges) { hist.done.shift(); }
4884
  }
4885
  }
4886
+ hist.done.push(selAfter);
4887
+ hist.generation = ++hist.maxGeneration;
4888
+ hist.lastModTime = hist.lastSelTime = time;
4889
+ hist.lastOp = hist.lastSelOp = opId;
4890
+ hist.lastOrigin = hist.lastSelOrigin = change.origin;
4891
 
4892
+ if (!last) { signal(doc, "historyAdded"); }
4893
+ }
 
 
 
 
4894
 
4895
+ function selectionEventCanBeMerged(doc, origin, prev, sel) {
4896
+ var ch = origin.charAt(0);
4897
+ return ch == "*" ||
4898
+ ch == "+" &&
4899
+ prev.ranges.length == sel.ranges.length &&
4900
+ prev.somethingSelected() == sel.somethingSelected() &&
4901
+ new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
4902
+ }
 
 
 
4903
 
4904
+ // Called whenever the selection changes, sets the new selection as
4905
+ // the pending selection in the history, and pushes the old pending
4906
+ // selection into the 'done' array when it was significantly
4907
+ // different (in number of selected ranges, emptiness, or time).
4908
+ function addSelectionToHistory(doc, sel, opId, options) {
4909
+ var hist = doc.history, origin = options && options.origin;
4910
+
4911
+ // A new event is started when the previous origin does not match
4912
+ // the current, or the origins don't allow matching. Origins
4913
+ // starting with * are always merged, those starting with + are
4914
+ // merged when similar and close together in time.
4915
+ if (opId == hist.lastSelOp ||
4916
+ (origin && hist.lastSelOrigin == origin &&
4917
+ (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
4918
+ selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
4919
+ { hist.done[hist.done.length - 1] = sel; }
4920
+ else
4921
+ { pushSelectionToHistory(sel, hist.done); }
4922
+
4923
+ hist.lastSelTime = +new Date;
4924
+ hist.lastSelOrigin = origin;
4925
+ hist.lastSelOp = opId;
4926
+ if (options && options.clearRedo !== false)
4927
+ { clearSelectionEvents(hist.undone); }
4928
  }
4929
 
4930
+ function pushSelectionToHistory(sel, dest) {
4931
+ var top = lst(dest);
4932
+ if (!(top && top.ranges && top.equals(sel)))
4933
+ { dest.push(sel); }
4934
+ }
4935
 
4936
+ // Used to store marked span information in the history.
4937
+ function attachLocalSpans(doc, change, from, to) {
4938
+ var existing = change["spans_" + doc.id], n = 0;
4939
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {
4940
+ if (line.markedSpans)
4941
+ { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; }
4942
+ ++n;
4943
+ });
4944
+ }
 
 
 
 
 
4945
 
4946
+ // When un/re-doing restores text containing marked spans, those
4947
+ // that have been explicitly cleared should not be restored.
4948
+ function removeClearedSpans(spans) {
4949
+ if (!spans) { return null }
4950
+ var out;
4951
+ for (var i = 0; i < spans.length; ++i) {
4952
+ if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } }
4953
+ else if (out) { out.push(spans[i]); }
 
 
 
 
 
 
 
4954
  }
4955
+ return !out ? spans : out.length ? out : null
4956
+ }
4957
 
4958
+ // Retrieve and filter the old marked spans stored in a change event.
4959
+ function getOldSpans(doc, change) {
4960
+ var found = change["spans_" + doc.id];
4961
+ if (!found) { return null }
4962
+ var nw = [];
4963
+ for (var i = 0; i < change.text.length; ++i)
4964
+ { nw.push(removeClearedSpans(found[i])); }
4965
+ return nw
4966
+ }
 
 
 
 
 
 
4967
 
4968
+ // Used for un/re-doing changes from the history. Combines the
4969
+ // result of computing the existing spans with the set of spans that
4970
+ // existed in the history (so that deleting around a span and then
4971
+ // undoing brings back the span).
4972
+ function mergeOldSpans(doc, change) {
4973
+ var old = getOldSpans(doc, change);
4974
+ var stretched = stretchSpansOverChange(doc, change);
4975
+ if (!old) { return stretched }
4976
+ if (!stretched) { return old }
4977
 
4978
+ for (var i = 0; i < old.length; ++i) {
4979
+ var oldCur = old[i], stretchCur = stretched[i];
4980
+ if (oldCur && stretchCur) {
4981
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
4982
+ var span = stretchCur[j];
4983
+ for (var k = 0; k < oldCur.length; ++k)
4984
+ { if (oldCur[k].marker == span.marker) { continue spans } }
4985
+ oldCur.push(span);
4986
+ }
4987
+ } else if (stretchCur) {
4988
+ old[i] = stretchCur;
4989
+ }
4990
+ }
4991
+ return old
4992
+ }
4993
 
4994
+ // Used both to provide a JSON-safe object in .getHistory, and, when
4995
+ // detaching a document, to split the history in two
4996
+ function copyHistoryArray(events, newGroup, instantiateSel) {
4997
+ var copy = [];
4998
+ for (var i = 0; i < events.length; ++i) {
4999
+ var event = events[i];
5000
+ if (event.ranges) {
5001
+ copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
5002
+ continue
5003
+ }
5004
+ var changes = event.changes, newChanges = [];
5005
+ copy.push({changes: newChanges});
5006
+ for (var j = 0; j < changes.length; ++j) {
5007
+ var change = changes[j], m = (void 0);
5008
+ newChanges.push({from: change.from, to: change.to, text: change.text});
5009
+ if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) {
5010
+ if (indexOf(newGroup, Number(m[1])) > -1) {
5011
+ lst(newChanges)[prop] = change[prop];
5012
+ delete change[prop];
5013
+ }
5014
+ } } }
5015
+ }
5016
+ }
5017
+ return copy
5018
+ }
5019
 
5020
+ // The 'scroll' parameter given to many of these indicated whether
5021
+ // the new cursor position should be scrolled into view after
5022
+ // modifying the selection.
 
 
 
 
5023
 
5024
+ // If shift is held or the extend flag is set, extends a range to
5025
+ // include a given position (and optionally a second position).
5026
+ // Otherwise, simply returns the range between the given positions.
5027
+ // Used for cursor motion and such.
5028
+ function extendRange(range, head, other, extend) {
5029
+ if (extend) {
5030
+ var anchor = range.anchor;
5031
+ if (other) {
5032
+ var posBefore = cmp(head, anchor) < 0;
5033
+ if (posBefore != (cmp(other, anchor) < 0)) {
5034
+ anchor = head;
5035
+ head = other;
5036
+ } else if (posBefore != (cmp(head, other) < 0)) {
5037
+ head = other;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5038
  }
 
 
 
 
 
5039
  }
5040
+ return new Range(anchor, head)
5041
+ } else {
5042
+ return new Range(other || head, head)
 
 
 
5043
  }
5044
+ }
5045
 
5046
+ // Extend the primary selection range, discard the rest.
5047
+ function extendSelection(doc, head, other, options, extend) {
5048
+ if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); }
5049
+ setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options);
5050
+ }
5051
 
5052
+ // Extend all selections (pos is an array of selections with length
5053
+ // equal the number of selections)
5054
+ function extendSelections(doc, heads, options) {
5055
+ var out = [];
5056
+ var extend = doc.cm && (doc.cm.display.shift || doc.extend);
5057
+ for (var i = 0; i < doc.sel.ranges.length; i++)
5058
+ { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); }
5059
+ var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex);
5060
+ setSelection(doc, newSel, options);
5061
+ }
 
5062
 
5063
+ // Updates a single range in the selection.
5064
+ function replaceOneSelection(doc, i, range, options) {
5065
+ var ranges = doc.sel.ranges.slice(0);
5066
+ ranges[i] = range;
5067
+ setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options);
5068
+ }
 
5069
 
5070
+ // Reset the selection to a single range.
5071
+ function setSimpleSelection(doc, anchor, head, options) {
5072
+ setSelection(doc, simpleSelection(anchor, head), options);
5073
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5074
 
5075
+ // Give beforeSelectionChange handlers a change to influence a
5076
+ // selection update.
5077
+ function filterSelectionChange(doc, sel, options) {
5078
+ var obj = {
5079
+ ranges: sel.ranges,
5080
+ update: function(ranges) {
5081
+ this.ranges = [];
5082
+ for (var i = 0; i < ranges.length; i++)
5083
+ { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
5084
+ clipPos(doc, ranges[i].head)); }
5085
+ },
5086
+ origin: options && options.origin
5087
+ };
5088
+ signal(doc, "beforeSelectionChange", doc, obj);
5089
+ if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); }
5090
+ if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) }
5091
+ else { return sel }
5092
+ }
5093
 
5094
+ function setSelectionReplaceHistory(doc, sel, options) {
5095
+ var done = doc.history.done, last = lst(done);
5096
+ if (last && last.ranges) {
5097
+ done[done.length - 1] = sel;
5098
+ setSelectionNoUndo(doc, sel, options);
5099
+ } else {
5100
+ setSelection(doc, sel, options);
 
 
 
 
 
 
 
 
 
 
 
 
5101
  }
5102
+ }
 
5103
 
5104
+ // Set a new selection.
5105
+ function setSelection(doc, sel, options) {
5106
+ setSelectionNoUndo(doc, sel, options);
5107
+ addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
5108
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5109
 
5110
+ function setSelectionNoUndo(doc, sel, options) {
5111
+ if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
5112
+ { sel = filterSelectionChange(doc, sel, options); }
 
 
 
 
 
 
 
 
 
 
 
 
5113
 
5114
+ var bias = options && options.bias ||
5115
+ (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
5116
+ setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
 
5117
 
5118
+ if (!(options && options.scroll === false) && doc.cm && doc.cm.getOption("readOnly") != "nocursor")
5119
+ { ensureCursorVisible(doc.cm); }
5120
+ }
 
 
 
 
 
5121
 
5122
+ function setSelectionInner(doc, sel) {
5123
+ if (sel.equals(doc.sel)) { return }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5124
 
5125
+ doc.sel = sel;
 
5126
 
5127
+ if (doc.cm) {
5128
+ doc.cm.curOp.updateInput = 1;
5129
+ doc.cm.curOp.selectionChanged = true;
5130
+ signalCursorActivity(doc.cm);
5131
+ }
5132
+ signalLater(doc, "cursorActivity", doc);
5133
+ }
 
 
 
 
 
 
 
5134
 
5135
+ // Verify that the selection does not partially select any atomic
5136
+ // marked ranges.
5137
+ function reCheckSelection(doc) {
5138
+ setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false));
5139
+ }
5140
 
5141
+ // Return a selection that does not partially select any atomic
5142
+ // ranges.
5143
+ function skipAtomicInSelection(doc, sel, bias, mayClear) {
5144
+ var out;
5145
+ for (var i = 0; i < sel.ranges.length; i++) {
5146
+ var range = sel.ranges[i];
5147
+ var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
5148
+ var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
5149
+ var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);
5150
+ if (out || newAnchor != range.anchor || newHead != range.head) {
5151
+ if (!out) { out = sel.ranges.slice(0, i); }
5152
+ out[i] = new Range(newAnchor, newHead);
5153
+ }
 
 
 
 
 
5154
  }
5155
+ return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel
5156
  }
5157
 
5158
+ function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
5159
+ var line = getLine(doc, pos.line);
5160
+ if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
5161
+ var sp = line.markedSpans[i], m = sp.marker;
 
 
 
 
 
 
 
 
5162
 
5163
+ // Determine if we should prevent the cursor being placed to the left/right of an atomic marker
5164
+ // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it
5165
+ // is with selectLeft/Right
5166
+ var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft;
5167
+ var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight;
 
 
 
 
 
5168
 
5169
+ if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
5170
+ (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
5171
+ if (mayClear) {
5172
+ signal(m, "beforeCursorEnter");
5173
+ if (m.explicitlyCleared) {
5174
+ if (!line.markedSpans) { break }
5175
+ else {--i; continue}
5176
+ }
5177
+ }
5178
+ if (!m.atomic) { continue }
5179
+
5180
+ if (oldPos) {
5181
+ var near = m.find(dir < 0 ? 1 : -1), diff = (void 0);
5182
+ if (dir < 0 ? preventCursorRight : preventCursorLeft)
5183
+ { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); }
5184
+ if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
5185
+ { return skipAtomicInner(doc, near, pos, dir, mayClear) }
5186
+ }
5187
 
5188
+ var far = m.find(dir < 0 ? -1 : 1);
5189
+ if (dir < 0 ? preventCursorLeft : preventCursorRight)
5190
+ { far = movePos(doc, far, dir, far.line == pos.line ? line : null); }
5191
+ return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null
5192
+ }
5193
+ } }
5194
+ return pos
5195
  }
5196
 
5197
+ // Ensure a given position is not inside an atomic range.
5198
+ function skipAtomic(doc, pos, oldPos, bias, mayClear) {
5199
+ var dir = bias || 1;
5200
+ var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
5201
+ (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
5202
+ skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
5203
+ (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));
5204
+ if (!found) {
5205
+ doc.cantEdit = true;
5206
+ return Pos(doc.first, 0)
5207
+ }
5208
+ return found
5209
+ }
5210
+
5211
+ function movePos(doc, pos, dir, line) {
5212
+ if (dir < 0 && pos.ch == 0) {
5213
+ if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }
5214
+ else { return null }
5215
+ } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
5216
+ if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }
5217
+ else { return null }
5218
+ } else {
5219
+ return new Pos(pos.line, pos.ch + dir)
5220
  }
5221
  }
5222
 
5223
+ function selectAll(cm) {
5224
+ cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);
 
 
 
 
 
 
 
 
 
 
5225
  }
5226
 
5227
+ // UPDATING
5228
 
5229
+ // Allow "beforeChange" event handlers to influence a change
5230
+ function filterChange(doc, change, update) {
5231
+ var obj = {
5232
+ canceled: false,
5233
+ from: change.from,
5234
+ to: change.to,
5235
+ text: change.text,
5236
+ origin: change.origin,
5237
+ cancel: function () { return obj.canceled = true; }
5238
+ };
5239
+ if (update) { obj.update = function (from, to, text, origin) {
5240
+ if (from) { obj.from = clipPos(doc, from); }
5241
+ if (to) { obj.to = clipPos(doc, to); }
5242
+ if (text) { obj.text = text; }
5243
+ if (origin !== undefined) { obj.origin = origin; }
5244
+ }; }
5245
+ signal(doc, "beforeChange", doc, obj);
5246
+ if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); }
5247
+
5248
+ if (obj.canceled) {
5249
+ if (doc.cm) { doc.cm.curOp.updateInput = 2; }
5250
+ return null
5251
+ }
5252
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}
5253
  }
5254
 
5255
+ // Apply a change to a document, and add it to the document's
5256
+ // history, and propagating it to all linked documents.
5257
+ function makeChange(doc, change, ignoreReadOnly) {
5258
+ if (doc.cm) {
5259
+ if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }
5260
+ if (doc.cm.state.suppressEdits) { return }
5261
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
5262
 
5263
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
5264
+ change = filterChange(doc, change, true);
5265
+ if (!change) { return }
 
 
 
 
 
 
 
 
 
5266
  }
5267
+
5268
+ // Possibly split or suppress the update based on the presence
5269
+ // of read-only spans in its range.
5270
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
5271
+ if (split) {
5272
+ for (var i = split.length - 1; i >= 0; --i)
5273
+ { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); }
5274
+ } else {
5275
+ makeChangeInner(doc, change);
 
 
5276
  }
 
5277
  }
5278
 
5279
+ function makeChangeInner(doc, change) {
5280
+ if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return }
5281
+ var selAfter = computeSelAfterChange(doc, change);
5282
+ addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
 
 
 
 
 
 
 
5283
 
5284
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
5285
+ var rebased = [];
 
 
5286
 
5287
+ linkedDocs(doc, function (doc, sharedHist) {
5288
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
5289
+ rebaseHist(doc.history, change);
5290
+ rebased.push(doc.history);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5291
  }
5292
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
5293
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5294
  }
5295
 
5296
+ // Revert a change stored in a document's history.
5297
+ function makeChangeFromHistory(doc, type, allowSelectionOnly) {
5298
+ var suppress = doc.cm && doc.cm.state.suppressEdits;
5299
+ if (suppress && !allowSelectionOnly) { return }
 
 
 
 
 
 
 
5300
 
5301
+ var hist = doc.history, event, selAfter = doc.sel;
5302
+ var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
 
 
 
 
 
 
 
5303
 
5304
+ // Verify that there is a useable event (so that ctrl-z won't
5305
+ // needlessly clear selection events)
5306
+ var i = 0;
5307
+ for (; i < source.length; i++) {
5308
+ event = source[i];
5309
+ if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
5310
+ { break }
5311
+ }
5312
+ if (i == source.length) { return }
5313
+ hist.lastOrigin = hist.lastSelOrigin = null;
5314
+
5315
+ for (;;) {
5316
+ event = source.pop();
5317
+ if (event.ranges) {
5318
+ pushSelectionToHistory(event, dest);
5319
+ if (allowSelectionOnly && !event.equals(doc.sel)) {
5320
+ setSelection(doc, event, {clearRedo: false});
5321
+ return
5322
  }
5323
+ selAfter = event;
5324
+ } else if (suppress) {
5325
+ source.push(event);
5326
+ return
5327
+ } else { break }
5328
  }
 
 
5329
 
5330
+ // Build up a reverse change object to add to the opposite history
5331
+ // stack (redo when undoing, and vice versa).
5332
+ var antiChanges = [];
5333
+ pushSelectionToHistory(selAfter, dest);
5334
+ dest.push({changes: antiChanges, generation: hist.generation});
5335
+ hist.generation = event.generation || ++hist.maxGeneration;
5336
+
5337
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
5338
+
5339
+ var loop = function ( i ) {
5340
+ var change = event.changes[i];
5341
+ change.origin = type;
5342
+ if (filter && !filterChange(doc, change, false)) {
5343
+ source.length = 0;
5344
+ return {}
 
 
 
 
 
 
 
 
 
5345
  }
 
 
 
5346
 
5347
+ antiChanges.push(historyChangeFromChange(doc, change));
 
 
 
 
 
 
 
 
 
 
 
 
 
5348
 
5349
+ var after = i ? computeSelAfterChange(doc, change) : lst(source);
5350
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
5351
+ if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); }
5352
+ var rebased = [];
5353
 
5354
+ // Propagate to the linked documents
5355
+ linkedDocs(doc, function (doc, sharedHist) {
5356
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
5357
+ rebaseHist(doc.history, change);
5358
+ rebased.push(doc.history);
5359
+ }
5360
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
5361
+ });
5362
+ };
 
 
 
 
5363
 
5364
+ for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {
5365
+ var returned = loop( i$1 );
5366
+
5367
+ if ( returned ) return returned.v;
 
 
 
 
 
5368
  }
 
5369
  }
 
 
5370
 
5371
+ // Sub-views need their line numbers shifted when text is added
5372
+ // above or below them in the parent document.
5373
+ function shiftDoc(doc, distance) {
5374
+ if (distance == 0) { return }
5375
+ doc.first += distance;
5376
+ doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(
5377
+ Pos(range.anchor.line + distance, range.anchor.ch),
5378
+ Pos(range.head.line + distance, range.head.ch)
5379
+ ); }), doc.sel.primIndex);
5380
+ if (doc.cm) {
5381
+ regChange(doc.cm, doc.first, doc.first - distance, distance);
5382
+ for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
5383
+ { regLineChange(doc.cm, l, "gutter"); }
 
 
 
5384
  }
5385
  }
5386
 
5387
+ // More lower-level change function, handling only a single document
5388
+ // (not linked ones).
5389
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
5390
+ if (doc.cm && !doc.cm.curOp)
5391
+ { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }
 
 
 
 
 
5392
 
5393
+ if (change.to.line < doc.first) {
5394
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
5395
+ return
 
 
 
 
5396
  }
5397
+ if (change.from.line > doc.lastLine()) { return }
 
5398
 
5399
+ // Clip the change to the size of this doc
5400
+ if (change.from.line < doc.first) {
5401
+ var shift = change.text.length - 1 - (doc.first - change.from.line);
5402
+ shiftDoc(doc, shift);
5403
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
5404
+ text: [lst(change.text)], origin: change.origin};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5405
  }
5406
+ var last = doc.lastLine();
5407
+ if (change.to.line > last) {
5408
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
5409
+ text: [change.text[0]], origin: change.origin};
 
 
 
 
5410
  }
 
 
 
5411
 
5412
+ change.removed = getBetween(doc, change.from, change.to);
5413
 
5414
+ if (!selAfter) { selAfter = computeSelAfterChange(doc, change); }
5415
+ if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); }
5416
+ else { updateDoc(doc, change, spans); }
5417
+ setSelectionNoUndo(doc, selAfter, sel_dontScroll);
 
 
 
5418
 
5419
+ if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0)))
5420
+ { doc.cantEdit = false; }
 
5421
  }
5422
 
5423
+ // Handle the interaction of a change to a document with the editor
5424
+ // that this document is part of.
5425
+ function makeChangeSingleDocInEditor(cm, change, spans) {
5426
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5427
 
5428
+ var recomputeMaxLength = false, checkWidthStart = from.line;
5429
+ if (!cm.options.lineWrapping) {
5430
+ checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
5431
+ doc.iter(checkWidthStart, to.line + 1, function (line) {
5432
+ if (line == display.maxLine) {
5433
+ recomputeMaxLength = true;
5434
+ return true
5435
+ }
5436
+ });
5437
  }
 
 
5438
 
5439
+ if (doc.sel.contains(change.from, change.to) > -1)
5440
+ { signalCursorActivity(cm); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5441
 
5442
+ updateDoc(doc, change, spans, estimateHeight(cm));
5443
 
5444
+ if (!cm.options.lineWrapping) {
5445
+ doc.iter(checkWidthStart, from.line + change.text.length, function (line) {
5446
+ var len = lineLength(line);
5447
+ if (len > display.maxLineLength) {
5448
+ display.maxLine = line;
5449
+ display.maxLineLength = len;
5450
+ display.maxLineChanged = true;
5451
+ recomputeMaxLength = false;
5452
+ }
5453
+ });
5454
+ if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; }
5455
+ }
5456
 
5457
+ retreatFrontier(doc, from.line);
5458
+ startWorker(cm, 400);
 
 
 
 
 
 
 
 
 
 
 
5459
 
5460
+ var lendiff = change.text.length - (to.line - from.line) - 1;
5461
+ // Remember that these lines changed, for updating the display
5462
+ if (change.full)
5463
+ { regChange(cm); }
5464
+ else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
5465
+ { regLineChange(cm, from.line, "text"); }
5466
+ else
5467
+ { regChange(cm, from.line, to.line + 1, lendiff); }
5468
 
5469
+ var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
5470
+ if (changeHandler || changesHandler) {
5471
+ var obj = {
5472
+ from: from, to: to,
5473
+ text: change.text,
5474
+ removed: change.removed,
5475
+ origin: change.origin
5476
+ };
5477
+ if (changeHandler) { signalLater(cm, "change", cm, obj); }
5478
+ if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); }
5479
  }
5480
+ cm.display.selForContextMenu = null;
5481
  }
5482
 
5483
+ function replaceRange(doc, code, from, to, origin) {
5484
+ var assign;
 
 
 
 
5485
 
5486
+ if (!to) { to = from; }
5487
+ if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); }
5488
+ if (typeof code == "string") { code = doc.splitLines(code); }
5489
+ makeChange(doc, {from: from, to: to, text: code, origin: origin});
 
 
 
5490
  }
5491
 
5492
+ // Rebasing/resetting history to deal with externally-sourced changes
 
 
 
 
 
 
 
5493
 
5494
+ function rebaseHistSelSingle(pos, from, to, diff) {
5495
+ if (to < pos.line) {
5496
+ pos.line += diff;
5497
+ } else if (from < pos.line) {
5498
+ pos.line = from;
5499
+ pos.ch = 0;
 
 
 
5500
  }
 
5501
  }
5502
 
5503
+ // Tries to rebase an array of history events given a change in the
5504
+ // document. If the change touches the same lines as the event, the
5505
+ // event, and everything 'behind' it, is discarded. If the change is
5506
+ // before the event, the event's positions are updated. Uses a
5507
+ // copy-on-write scheme for the positions, to avoid having to
5508
+ // reallocate them all on every rebase, but also avoid problems with
5509
+ // shared position objects being unsafely updated.
5510
+ function rebaseHistArray(array, from, to, diff) {
5511
+ for (var i = 0; i < array.length; ++i) {
5512
+ var sub = array[i], ok = true;
5513
+ if (sub.ranges) {
5514
+ if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
5515
+ for (var j = 0; j < sub.ranges.length; j++) {
5516
+ rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
5517
+ rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
5518
+ }
5519
+ continue
 
 
 
5520
  }
5521
+ for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {
5522
+ var cur = sub.changes[j$1];
5523
+ if (to < cur.from.line) {
5524
+ cur.from = Pos(cur.from.line + diff, cur.from.ch);
5525
+ cur.to = Pos(cur.to.line + diff, cur.to.ch);
5526
+ } else if (from <= cur.to.line) {
5527
+ ok = false;
5528
+ break
5529
  }
 
5530
  }
5531
+ if (!ok) {
5532
+ array.splice(0, i + 1);
5533
+ i = 0;
5534
+ }
 
 
 
5535
  }
5536
  }
5537
 
5538
+ function rebaseHist(hist, change) {
5539
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
5540
+ rebaseHistArray(hist.done, from, to, diff);
5541
+ rebaseHistArray(hist.undone, from, to, diff);
5542
+ }
 
 
 
 
 
 
 
5543
 
5544
+ // Utility for applying a change to a line by handle or number,
5545
+ // returning the number and optionally registering the line as
5546
+ // changed.
5547
+ function changeLine(doc, handle, changeType, op) {
5548
+ var no = handle, line = handle;
5549
+ if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); }
5550
+ else { no = lineNo(handle); }
5551
+ if (no == null) { return null }
5552
+ if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); }
5553
+ return line
5554
+ }
5555
+
5556
+ // The document is represented as a BTree consisting of leaves, with
5557
+ // chunk of lines in them, and branches, with up to ten leaves or
5558
+ // other branch nodes below them. The top node is always a branch
5559
+ // node, and is the document object itself (meaning it has
5560
+ // additional methods and properties).
5561
+ //
5562
+ // All nodes have parent links. The tree is used both to go from
5563
+ // line numbers to line objects, and to go from objects to numbers.
5564
+ // It also indexes by height, and is used to convert between height
5565
+ // and line object, and to find the total height of the document.
5566
+ //
5567
+ // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
5568
+
5569
+ function LeafChunk(lines) {
5570
+ this.lines = lines;
5571
+ this.parent = null;
5572
+ var height = 0;
5573
+ for (var i = 0; i < lines.length; ++i) {
5574
+ lines[i].parent = this;
5575
+ height += lines[i].height;
5576
  }
5577
+ this.height = height;
5578
+ }
5579
 
5580
+ LeafChunk.prototype = {
5581
+ chunkSize: function() { return this.lines.length },
5582
+
5583
+ // Remove the n lines at offset 'at'.
5584
+ removeInner: function(at, n) {
5585
+ for (var i = at, e = at + n; i < e; ++i) {
5586
+ var line = this.lines[i];
5587
+ this.height -= line.height;
5588
+ cleanUpLine(line);
5589
+ signalLater(line, "delete");
5590
+ }
5591
+ this.lines.splice(at, n);
5592
+ },
5593
+
5594
+ // Helper used to collapse a small branch into a single leaf.
5595
+ collapse: function(lines) {
5596
+ lines.push.apply(lines, this.lines);
5597
+ },
5598
+
5599
+ // Insert the given array of lines at offset 'at', count them as
5600
+ // having the given height.
5601
+ insertInner: function(at, lines, height) {
5602
+ this.height += height;
5603
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
5604
+ for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; }
5605
+ },
5606
+
5607
+ // Used to iterate over a part of the tree.
5608
+ iterN: function(at, n, op) {
5609
+ for (var e = at + n; at < e; ++at)
5610
+ { if (op(this.lines[at])) { return true } }
5611
+ }
5612
+ };
5613
+
5614
+ function BranchChunk(children) {
5615
+ this.children = children;
5616
+ var size = 0, height = 0;
5617
+ for (var i = 0; i < children.length; ++i) {
5618
+ var ch = children[i];
5619
+ size += ch.chunkSize(); height += ch.height;
5620
+ ch.parent = this;
5621
+ }
5622
+ this.size = size;
5623
+ this.height = height;
5624
+ this.parent = null;
5625
+ }
5626
+
5627
+ BranchChunk.prototype = {
5628
+ chunkSize: function() { return this.size },
5629
+
5630
+ removeInner: function(at, n) {
5631
+ this.size -= n;
5632
+ for (var i = 0; i < this.children.length; ++i) {
5633
+ var child = this.children[i], sz = child.chunkSize();
5634
+ if (at < sz) {
5635
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
5636
+ child.removeInner(at, rm);
5637
+ this.height -= oldHeight - child.height;
5638
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
5639
+ if ((n -= rm) == 0) { break }
5640
+ at = 0;
5641
+ } else { at -= sz; }
5642
+ }
5643
+ // If the result is smaller than 25 lines, ensure that it is a
5644
+ // single leaf node.
5645
+ if (this.size - n < 25 &&
5646
+ (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
5647
+ var lines = [];
5648
+ this.collapse(lines);
5649
+ this.children = [new LeafChunk(lines)];
5650
+ this.children[0].parent = this;
5651
+ }
5652
+ },
5653
+
5654
+ collapse: function(lines) {
5655
+ for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); }
5656
+ },
5657
+
5658
+ insertInner: function(at, lines, height) {
5659
+ this.size += lines.length;
5660
+ this.height += height;
5661
+ for (var i = 0; i < this.children.length; ++i) {
5662
+ var child = this.children[i], sz = child.chunkSize();
5663
+ if (at <= sz) {
5664
+ child.insertInner(at, lines, height);
5665
+ if (child.lines && child.lines.length > 50) {
5666
+ // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
5667
+ // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
5668
+ var remaining = child.lines.length % 25 + 25;
5669
+ for (var pos = remaining; pos < child.lines.length;) {
5670
+ var leaf = new LeafChunk(child.lines.slice(pos, pos += 25));
5671
+ child.height -= leaf.height;
5672
+ this.children.splice(++i, 0, leaf);
5673
+ leaf.parent = this;
5674
+ }
5675
+ child.lines = child.lines.slice(0, remaining);
5676
+ this.maybeSpill();
5677
+ }
5678
+ break
5679
+ }
5680
+ at -= sz;
5681
+ }
5682
+ },
5683
+
5684
+ // When a node has grown, check whether it should be split.
5685
+ maybeSpill: function() {
5686
+ if (this.children.length <= 10) { return }
5687
+ var me = this;
5688
+ do {
5689
+ var spilled = me.children.splice(me.children.length - 5, 5);
5690
+ var sibling = new BranchChunk(spilled);
5691
+ if (!me.parent) { // Become the parent node
5692
+ var copy = new BranchChunk(me.children);
5693
+ copy.parent = me;
5694
+ me.children = [copy, sibling];
5695
+ me = copy;
5696
+ } else {
5697
+ me.size -= sibling.size;
5698
+ me.height -= sibling.height;
5699
+ var myIndex = indexOf(me.parent.children, me);
5700
+ me.parent.children.splice(myIndex + 1, 0, sibling);
5701
+ }
5702
+ sibling.parent = me.parent;
5703
+ } while (me.children.length > 10)
5704
+ me.parent.maybeSpill();
5705
+ },
5706
+
5707
+ iterN: function(at, n, op) {
5708
+ for (var i = 0; i < this.children.length; ++i) {
5709
+ var child = this.children[i], sz = child.chunkSize();
5710
+ if (at < sz) {
5711
+ var used = Math.min(n, sz - at);
5712
+ if (child.iterN(at, used, op)) { return true }
5713
+ if ((n -= used) == 0) { break }
5714
+ at = 0;
5715
+ } else { at -= sz; }
5716
+ }
5717
+ }
5718
+ };
5719
+
5720
+ // Line widgets are block elements displayed above or below a line.
5721
+
5722
+ var LineWidget = function(doc, node, options) {
5723
+ if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
5724
+ { this[opt] = options[opt]; } } }
5725
+ this.doc = doc;
5726
+ this.node = node;
5727
+ };
5728
+
5729
+ LineWidget.prototype.clear = function () {
5730
+ var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
5731
+ if (no == null || !ws) { return }
5732
+ for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } }
5733
+ if (!ws.length) { line.widgets = null; }
5734
+ var height = widgetHeight(this);
5735
+ updateLineHeight(line, Math.max(0, line.height - height));
5736
+ if (cm) {
5737
+ runInOp(cm, function () {
5738
+ adjustScrollWhenAboveVisible(cm, line, -height);
5739
+ regLineChange(cm, no, "widget");
5740
+ });
5741
+ signalLater(cm, "lineWidgetCleared", cm, this, no);
5742
+ }
5743
+ };
5744
+
5745
+ LineWidget.prototype.changed = function () {
5746
+ var this$1 = this;
5747
+
5748
+ var oldH = this.height, cm = this.doc.cm, line = this.line;
5749
+ this.height = null;
5750
+ var diff = widgetHeight(this) - oldH;
5751
+ if (!diff) { return }
5752
+ if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); }
5753
+ if (cm) {
5754
+ runInOp(cm, function () {
5755
+ cm.curOp.forceUpdate = true;
5756
+ adjustScrollWhenAboveVisible(cm, line, diff);
5757
+ signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line));
5758
+ });
5759
+ }
5760
+ };
5761
+ eventMixin(LineWidget);
5762
+
5763
+ function adjustScrollWhenAboveVisible(cm, line, diff) {
5764
+ if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
5765
+ { addToScrollTop(cm, diff); }
5766
+ }
5767
+
5768
+ function addLineWidget(doc, handle, node, options) {
5769
+ var widget = new LineWidget(doc, node, options);
5770
+ var cm = doc.cm;
5771
+ if (cm && widget.noHScroll) { cm.display.alignWidgets = true; }
5772
+ changeLine(doc, handle, "widget", function (line) {
5773
+ var widgets = line.widgets || (line.widgets = []);
5774
+ if (widget.insertAt == null) { widgets.push(widget); }
5775
+ else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); }
5776
+ widget.line = line;
5777
+ if (cm && !lineIsHidden(doc, line)) {
5778
+ var aboveVisible = heightAtLine(line) < doc.scrollTop;
5779
+ updateLineHeight(line, line.height + widgetHeight(widget));
5780
+ if (aboveVisible) { addToScrollTop(cm, widget.height); }
5781
+ cm.curOp.forceUpdate = true;
5782
+ }
5783
+ return true
5784
+ });
5785
+ if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); }
5786
+ return widget
5787
+ }
5788
+
5789
+ // TEXTMARKERS
5790
+
5791
+ // Created with markText and setBookmark methods. A TextMarker is a
5792
+ // handle that can be used to clear or find a marked position in the
5793
+ // document. Line objects hold arrays (markedSpans) containing
5794
+ // {from, to, marker} object pointing to such marker objects, and
5795
+ // indicating that such a marker is present on that line. Multiple
5796
+ // lines may point to the same marker when it spans across lines.
5797
+ // The spans will have null for their from/to properties when the
5798
+ // marker continues beyond the start/end of the line. Markers have
5799
+ // links back to the lines they currently touch.
5800
+
5801
+ // Collapsed markers have unique ids, in order to be able to order
5802
+ // them, which is needed for uniquely determining an outer marker
5803
+ // when they overlap (they may nest, but not partially overlap).
5804
+ var nextMarkerId = 0;
5805
+
5806
+ var TextMarker = function(doc, type) {
5807
+ this.lines = [];
5808
+ this.type = type;
5809
+ this.doc = doc;
5810
+ this.id = ++nextMarkerId;
5811
+ };
5812
+
5813
+ // Clear the marker.
5814
+ TextMarker.prototype.clear = function () {
5815
+ if (this.explicitlyCleared) { return }
5816
+ var cm = this.doc.cm, withOp = cm && !cm.curOp;
5817
+ if (withOp) { startOperation(cm); }
5818
+ if (hasHandler(this, "clear")) {
5819
+ var found = this.find();
5820
+ if (found) { signalLater(this, "clear", found.from, found.to); }
5821
+ }
5822
+ var min = null, max = null;
5823
+ for (var i = 0; i < this.lines.length; ++i) {
5824
+ var line = this.lines[i];
5825
+ var span = getMarkedSpanFor(line.markedSpans, this);
5826
+ if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); }
5827
+ else if (cm) {
5828
+ if (span.to != null) { max = lineNo(line); }
5829
+ if (span.from != null) { min = lineNo(line); }
5830
+ }
5831
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
5832
+ if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
5833
+ { updateLineHeight(line, textHeight(cm.display)); }
5834
+ }
5835
+ if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
5836
+ var visual = visualLine(this.lines[i$1]), len = lineLength(visual);
5837
+ if (len > cm.display.maxLineLength) {
5838
+ cm.display.maxLine = visual;
5839
+ cm.display.maxLineLength = len;
5840
+ cm.display.maxLineChanged = true;
5841
+ }
5842
+ } }
5843
+
5844
+ if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); }
5845
+ this.lines.length = 0;
5846
+ this.explicitlyCleared = true;
5847
+ if (this.atomic && this.doc.cantEdit) {
5848
+ this.doc.cantEdit = false;
5849
+ if (cm) { reCheckSelection(cm.doc); }
5850
+ }
5851
+ if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); }
5852
+ if (withOp) { endOperation(cm); }
5853
+ if (this.parent) { this.parent.clear(); }
5854
+ };
5855
+
5856
+ // Find the position of the marker in the document. Returns a {from,
5857
+ // to} object by default. Side can be passed to get a specific side
5858
+ // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
5859
+ // Pos objects returned contain a line object, rather than a line
5860
+ // number (used to prevent looking up the same line twice).
5861
+ TextMarker.prototype.find = function (side, lineObj) {
5862
+ if (side == null && this.type == "bookmark") { side = 1; }
5863
+ var from, to;
5864
+ for (var i = 0; i < this.lines.length; ++i) {
5865
+ var line = this.lines[i];
5866
+ var span = getMarkedSpanFor(line.markedSpans, this);
5867
+ if (span.from != null) {
5868
+ from = Pos(lineObj ? line : lineNo(line), span.from);
5869
+ if (side == -1) { return from }
5870
+ }
5871
+ if (span.to != null) {
5872
+ to = Pos(lineObj ? line : lineNo(line), span.to);
5873
+ if (side == 1) { return to }
5874
+ }
5875
+ }
5876
+ return from && {from: from, to: to}
5877
+ };
5878
+
5879
+ // Signals that the marker's widget changed, and surrounding layout
5880
+ // should be recomputed.
5881
+ TextMarker.prototype.changed = function () {
5882
+ var this$1 = this;
5883
+
5884
+ var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
5885
+ if (!pos || !cm) { return }
5886
+ runInOp(cm, function () {
5887
+ var line = pos.line, lineN = lineNo(pos.line);
5888
+ var view = findViewForLine(cm, lineN);
5889
+ if (view) {
5890
+ clearLineMeasurementCacheFor(view);
5891
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
5892
+ }
5893
+ cm.curOp.updateMaxLine = true;
5894
+ if (!lineIsHidden(widget.doc, line) && widget.height != null) {
5895
+ var oldHeight = widget.height;
5896
+ widget.height = null;
5897
+ var dHeight = widgetHeight(widget) - oldHeight;
5898
+ if (dHeight)
5899
+ { updateLineHeight(line, line.height + dHeight); }
5900
+ }
5901
+ signalLater(cm, "markerChanged", cm, this$1);
5902
+ });
5903
+ };
5904
+
5905
+ TextMarker.prototype.attachLine = function (line) {
5906
+ if (!this.lines.length && this.doc.cm) {
5907
+ var op = this.doc.cm.curOp;
5908
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
5909
+ { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); }
5910
+ }
5911
+ this.lines.push(line);
5912
+ };
5913
+
5914
+ TextMarker.prototype.detachLine = function (line) {
5915
+ this.lines.splice(indexOf(this.lines, line), 1);
5916
+ if (!this.lines.length && this.doc.cm) {
5917
+ var op = this.doc.cm.curOp
5918
+ ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
5919
+ }
5920
+ };
5921
+ eventMixin(TextMarker);
5922
+
5923
+ // Create a marker, wire it up to the right lines, and
5924
+ function markText(doc, from, to, options, type) {
5925
+ // Shared markers (across linked documents) are handled separately
5926
+ // (markTextShared will call out to this again, once per
5927
+ // document).
5928
+ if (options && options.shared) { return markTextShared(doc, from, to, options, type) }
5929
+ // Ensure we are in an operation.
5930
+ if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }
5931
+
5932
+ var marker = new TextMarker(doc, type), diff = cmp(from, to);
5933
+ if (options) { copyObj(options, marker, false); }
5934
+ // Don't connect empty markers unless clearWhenEmpty is false
5935
+ if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
5936
+ { return marker }
5937
+ if (marker.replacedWith) {
5938
+ // Showing up as a widget implies collapsed (widget replaces text)
5939
+ marker.collapsed = true;
5940
+ marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget");
5941
+ if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); }
5942
+ if (options.insertLeft) { marker.widgetNode.insertLeft = true; }
5943
+ }
5944
+ if (marker.collapsed) {
5945
+ if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
5946
+ from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
5947
+ { throw new Error("Inserting collapsed marker partially overlapping an existing one") }
5948
+ seeCollapsedSpans();
5949
+ }
5950
+
5951
+ if (marker.addToHistory)
5952
+ { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); }
5953
+
5954
+ var curLine = from.line, cm = doc.cm, updateMaxLine;
5955
+ doc.iter(curLine, to.line + 1, function (line) {
5956
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
5957
+ { updateMaxLine = true; }
5958
+ if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }
5959
+ addMarkedSpan(line, new MarkedSpan(marker,
5960
+ curLine == from.line ? from.ch : null,
5961
+ curLine == to.line ? to.ch : null));
5962
+ ++curLine;
5963
+ });
5964
+ // lineIsHidden depends on the presence of the spans, so needs a second pass
5965
+ if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
5966
+ if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); }
5967
+ }); }
5968
+
5969
+ if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); }
5970
+
5971
+ if (marker.readOnly) {
5972
+ seeReadOnlySpans();
5973
+ if (doc.history.done.length || doc.history.undone.length)
5974
+ { doc.clearHistory(); }
5975
+ }
5976
+ if (marker.collapsed) {
5977
+ marker.id = ++nextMarkerId;
5978
+ marker.atomic = true;
5979
+ }
5980
+ if (cm) {
5981
+ // Sync editor state
5982
+ if (updateMaxLine) { cm.curOp.updateMaxLine = true; }
5983
+ if (marker.collapsed)
5984
+ { regChange(cm, from.line, to.line + 1); }
5985
+ else if (marker.className || marker.startStyle || marker.endStyle || marker.css ||
5986
+ marker.attributes || marker.title)
5987
+ { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } }
5988
+ if (marker.atomic) { reCheckSelection(cm.doc); }
5989
+ signalLater(cm, "markerAdded", cm, marker);
5990
+ }
5991
+ return marker
5992
+ }
5993
+
5994
+ // SHARED TEXTMARKERS
5995
+
5996
+ // A shared marker spans multiple linked documents. It is
5997
+ // implemented as a meta-marker-object controlling multiple normal
5998
+ // markers.
5999
+ var SharedTextMarker = function(markers, primary) {
6000
+ this.markers = markers;
6001
+ this.primary = primary;
6002
+ for (var i = 0; i < markers.length; ++i)
6003
+ { markers[i].parent = this; }
6004
+ };
6005
+
6006
+ SharedTextMarker.prototype.clear = function () {
6007
+ if (this.explicitlyCleared) { return }
6008
+ this.explicitlyCleared = true;
6009
+ for (var i = 0; i < this.markers.length; ++i)
6010
+ { this.markers[i].clear(); }
6011
+ signalLater(this, "clear");
6012
+ };
6013
+
6014
+ SharedTextMarker.prototype.find = function (side, lineObj) {
6015
+ return this.primary.find(side, lineObj)
6016
+ };
6017
+ eventMixin(SharedTextMarker);
6018
+
6019
+ function markTextShared(doc, from, to, options, type) {
6020
+ options = copyObj(options);
6021
+ options.shared = false;
6022
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0];
6023
+ var widget = options.widgetNode;
6024
+ linkedDocs(doc, function (doc) {
6025
+ if (widget) { options.widgetNode = widget.cloneNode(true); }
6026
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
6027
+ for (var i = 0; i < doc.linked.length; ++i)
6028
+ { if (doc.linked[i].isParent) { return } }
6029
+ primary = lst(markers);
6030
+ });
6031
+ return new SharedTextMarker(markers, primary)
6032
+ }
6033
+
6034
+ function findSharedMarkers(doc) {
6035
+ return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })
6036
+ }
6037
+
6038
+ function copySharedMarkers(doc, markers) {
6039
+ for (var i = 0; i < markers.length; i++) {
6040
+ var marker = markers[i], pos = marker.find();
6041
+ var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
6042
+ if (cmp(mFrom, mTo)) {
6043
+ var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
6044
+ marker.markers.push(subMark);
6045
+ subMark.parent = marker;
6046
+ }
6047
+ }
6048
+ }
6049
+
6050
+ function detachSharedMarkers(markers) {
6051
+ var loop = function ( i ) {
6052
+ var marker = markers[i], linked = [marker.primary.doc];
6053
+ linkedDocs(marker.primary.doc, function (d) { return linked.push(d); });
6054
+ for (var j = 0; j < marker.markers.length; j++) {
6055
+ var subMarker = marker.markers[j];
6056
+ if (indexOf(linked, subMarker.doc) == -1) {
6057
+ subMarker.parent = null;
6058
+ marker.markers.splice(j--, 1);
6059
+ }
6060
+ }
6061
+ };
6062
+
6063
+ for (var i = 0; i < markers.length; i++) loop( i );
6064
+ }
6065
+
6066
+ var nextDocId = 0;
6067
+ var Doc = function(text, mode, firstLine, lineSep, direction) {
6068
+ if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) }
6069
+ if (firstLine == null) { firstLine = 0; }
6070
+
6071
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
6072
+ this.first = firstLine;
6073
+ this.scrollTop = this.scrollLeft = 0;
6074
+ this.cantEdit = false;
6075
+ this.cleanGeneration = 1;
6076
+ this.modeFrontier = this.highlightFrontier = firstLine;
6077
+ var start = Pos(firstLine, 0);
6078
+ this.sel = simpleSelection(start);
6079
+ this.history = new History(null);
6080
+ this.id = ++nextDocId;
6081
+ this.modeOption = mode;
6082
+ this.lineSep = lineSep;
6083
+ this.direction = (direction == "rtl") ? "rtl" : "ltr";
6084
+ this.extend = false;
6085
+
6086
+ if (typeof text == "string") { text = this.splitLines(text); }
6087
+ updateDoc(this, {from: start, to: start, text: text});
6088
+ setSelection(this, simpleSelection(start), sel_dontScroll);
6089
+ };
6090
+
6091
+ Doc.prototype = createObj(BranchChunk.prototype, {
6092
+ constructor: Doc,
6093
+ // Iterate over the document. Supports two forms -- with only one
6094
+ // argument, it calls that for each line in the document. With
6095
+ // three, it iterates over the range given by the first two (with
6096
+ // the second being non-inclusive).
6097
+ iter: function(from, to, op) {
6098
+ if (op) { this.iterN(from - this.first, to - from, op); }
6099
+ else { this.iterN(this.first, this.first + this.size, from); }
6100
+ },
6101
+
6102
+ // Non-public interface for adding and removing lines.
6103
+ insert: function(at, lines) {
6104
+ var height = 0;
6105
+ for (var i = 0; i < lines.length; ++i) { height += lines[i].height; }
6106
+ this.insertInner(at - this.first, lines, height);
6107
+ },
6108
+ remove: function(at, n) { this.removeInner(at - this.first, n); },
6109
+
6110
+ // From here, the methods are part of the public interface. Most
6111
+ // are also available from CodeMirror (editor) instances.
6112
+
6113
+ getValue: function(lineSep) {
6114
+ var lines = getLines(this, this.first, this.first + this.size);
6115
+ if (lineSep === false) { return lines }
6116
+ return lines.join(lineSep || this.lineSeparator())
6117
+ },
6118
+ setValue: docMethodOp(function(code) {
6119
+ var top = Pos(this.first, 0), last = this.first + this.size - 1;
6120
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
6121
+ text: this.splitLines(code), origin: "setValue", full: true}, true);
6122
+ if (this.cm) { scrollToCoords(this.cm, 0, 0); }
6123
+ setSelection(this, simpleSelection(top), sel_dontScroll);
6124
+ }),
6125
+ replaceRange: function(code, from, to, origin) {
6126
+ from = clipPos(this, from);
6127
+ to = to ? clipPos(this, to) : from;
6128
+ replaceRange(this, code, from, to, origin);
6129
+ },
6130
+ getRange: function(from, to, lineSep) {
6131
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
6132
+ if (lineSep === false) { return lines }
6133
+ return lines.join(lineSep || this.lineSeparator())
6134
+ },
6135
+
6136
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},
6137
+
6138
+ getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},
6139
+ getLineNumber: function(line) {return lineNo(line)},
6140
+
6141
+ getLineHandleVisualStart: function(line) {
6142
+ if (typeof line == "number") { line = getLine(this, line); }
6143
+ return visualLine(line)
6144
+ },
6145
+
6146
+ lineCount: function() {return this.size},
6147
+ firstLine: function() {return this.first},
6148
+ lastLine: function() {return this.first + this.size - 1},
6149
+
6150
+ clipPos: function(pos) {return clipPos(this, pos)},
6151
+
6152
+ getCursor: function(start) {
6153
+ var range = this.sel.primary(), pos;
6154
+ if (start == null || start == "head") { pos = range.head; }
6155
+ else if (start == "anchor") { pos = range.anchor; }
6156
+ else if (start == "end" || start == "to" || start === false) { pos = range.to(); }
6157
+ else { pos = range.from(); }
6158
+ return pos
6159
+ },
6160
+ listSelections: function() { return this.sel.ranges },
6161
+ somethingSelected: function() {return this.sel.somethingSelected()},
6162
+
6163
+ setCursor: docMethodOp(function(line, ch, options) {
6164
+ setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
6165
+ }),
6166
+ setSelection: docMethodOp(function(anchor, head, options) {
6167
+ setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
6168
+ }),
6169
+ extendSelection: docMethodOp(function(head, other, options) {
6170
+ extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
6171
+ }),
6172
+ extendSelections: docMethodOp(function(heads, options) {
6173
+ extendSelections(this, clipPosArray(this, heads), options);
6174
+ }),
6175
+ extendSelectionsBy: docMethodOp(function(f, options) {
6176
+ var heads = map(this.sel.ranges, f);
6177
+ extendSelections(this, clipPosArray(this, heads), options);
6178
+ }),
6179
+ setSelections: docMethodOp(function(ranges, primary, options) {
6180
+ if (!ranges.length) { return }
6181
+ var out = [];
6182
+ for (var i = 0; i < ranges.length; i++)
6183
+ { out[i] = new Range(clipPos(this, ranges[i].anchor),
6184
+ clipPos(this, ranges[i].head)); }
6185
+ if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }
6186
+ setSelection(this, normalizeSelection(this.cm, out, primary), options);
6187
+ }),
6188
+ addSelection: docMethodOp(function(anchor, head, options) {
6189
+ var ranges = this.sel.ranges.slice(0);
6190
+ ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
6191
+ setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options);
6192
+ }),
6193
+
6194
+ getSelection: function(lineSep) {
6195
+ var ranges = this.sel.ranges, lines;
6196
+ for (var i = 0; i < ranges.length; i++) {
6197
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
6198
+ lines = lines ? lines.concat(sel) : sel;
6199
+ }
6200
+ if (lineSep === false) { return lines }
6201
+ else { return lines.join(lineSep || this.lineSeparator()) }
6202
+ },
6203
+ getSelections: function(lineSep) {
6204
+ var parts = [], ranges = this.sel.ranges;
6205
+ for (var i = 0; i < ranges.length; i++) {
6206
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
6207
+ if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); }
6208
+ parts[i] = sel;
6209
+ }
6210
+ return parts
6211
+ },
6212
+ replaceSelection: function(code, collapse, origin) {
6213
+ var dup = [];
6214
+ for (var i = 0; i < this.sel.ranges.length; i++)
6215
+ { dup[i] = code; }
6216
+ this.replaceSelections(dup, collapse, origin || "+input");
6217
+ },
6218
+ replaceSelections: docMethodOp(function(code, collapse, origin) {
6219
+ var changes = [], sel = this.sel;
6220
+ for (var i = 0; i < sel.ranges.length; i++) {
6221
+ var range = sel.ranges[i];
6222
+ changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
6223
+ }
6224
+ var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
6225
+ for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
6226
+ { makeChange(this, changes[i$1]); }
6227
+ if (newSel) { setSelectionReplaceHistory(this, newSel); }
6228
+ else if (this.cm) { ensureCursorVisible(this.cm); }
6229
+ }),
6230
+ undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
6231
+ redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
6232
+ undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
6233
+ redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
6234
+
6235
+ setExtending: function(val) {this.extend = val;},
6236
+ getExtending: function() {return this.extend},
6237
+
6238
+ historySize: function() {
6239
+ var hist = this.history, done = 0, undone = 0;
6240
+ for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } }
6241
+ for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } }
6242
+ return {undo: done, redo: undone}
6243
+ },
6244
+ clearHistory: function() {
6245
+ var this$1 = this;
6246
+
6247
+ this.history = new History(this.history.maxGeneration);
6248
+ linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true);
6249
+ },
6250
+
6251
+ markClean: function() {
6252
+ this.cleanGeneration = this.changeGeneration(true);
6253
+ },
6254
+ changeGeneration: function(forceSplit) {
6255
+ if (forceSplit)
6256
+ { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; }
6257
+ return this.history.generation
6258
+ },
6259
+ isClean: function (gen) {
6260
+ return this.history.generation == (gen || this.cleanGeneration)
6261
+ },
6262
+
6263
+ getHistory: function() {
6264
+ return {done: copyHistoryArray(this.history.done),
6265
+ undone: copyHistoryArray(this.history.undone)}
6266
+ },
6267
+ setHistory: function(histData) {
6268
+ var hist = this.history = new History(this.history.maxGeneration);
6269
+ hist.done = copyHistoryArray(histData.done.slice(0), null, true);
6270
+ hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
6271
+ },
6272
+
6273
+ setGutterMarker: docMethodOp(function(line, gutterID, value) {
6274
+ return changeLine(this, line, "gutter", function (line) {
6275
+ var markers = line.gutterMarkers || (line.gutterMarkers = {});
6276
+ markers[gutterID] = value;
6277
+ if (!value && isEmpty(markers)) { line.gutterMarkers = null; }
6278
+ return true
6279
+ })
6280
+ }),
6281
+
6282
+ clearGutter: docMethodOp(function(gutterID) {
6283
+ var this$1 = this;
6284
+
6285
+ this.iter(function (line) {
6286
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
6287
+ changeLine(this$1, line, "gutter", function () {
6288
+ line.gutterMarkers[gutterID] = null;
6289
+ if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; }
6290
+ return true
6291
+ });
6292
+ }
6293
+ });
6294
+ }),
6295
+
6296
+ lineInfo: function(line) {
6297
+ var n;
6298
+ if (typeof line == "number") {
6299
+ if (!isLine(this, line)) { return null }
6300
+ n = line;
6301
+ line = getLine(this, line);
6302
+ if (!line) { return null }
6303
+ } else {
6304
+ n = lineNo(line);
6305
+ if (n == null) { return null }
6306
+ }
6307
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
6308
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
6309
+ widgets: line.widgets}
6310
+ },
6311
+
6312
+ addLineClass: docMethodOp(function(handle, where, cls) {
6313
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
6314
+ var prop = where == "text" ? "textClass"
6315
+ : where == "background" ? "bgClass"
6316
+ : where == "gutter" ? "gutterClass" : "wrapClass";
6317
+ if (!line[prop]) { line[prop] = cls; }
6318
+ else if (classTest(cls).test(line[prop])) { return false }
6319
+ else { line[prop] += " " + cls; }
6320
+ return true
6321
+ })
6322
+ }),
6323
+ removeLineClass: docMethodOp(function(handle, where, cls) {
6324
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
6325
+ var prop = where == "text" ? "textClass"
6326
+ : where == "background" ? "bgClass"
6327
+ : where == "gutter" ? "gutterClass" : "wrapClass";
6328
+ var cur = line[prop];
6329
+ if (!cur) { return false }
6330
+ else if (cls == null) { line[prop] = null; }
6331
+ else {
6332
+ var found = cur.match(classTest(cls));
6333
+ if (!found) { return false }
6334
+ var end = found.index + found[0].length;
6335
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
6336
+ }
6337
+ return true
6338
+ })
6339
+ }),
6340
+
6341
+ addLineWidget: docMethodOp(function(handle, node, options) {
6342
+ return addLineWidget(this, handle, node, options)
6343
+ }),
6344
+ removeLineWidget: function(widget) { widget.clear(); },
6345
+
6346
+ markText: function(from, to, options) {
6347
+ return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range")
6348
+ },
6349
+ setBookmark: function(pos, options) {
6350
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
6351
+ insertLeft: options && options.insertLeft,
6352
+ clearWhenEmpty: false, shared: options && options.shared,
6353
+ handleMouseEvents: options && options.handleMouseEvents};
6354
+ pos = clipPos(this, pos);
6355
+ return markText(this, pos, pos, realOpts, "bookmark")
6356
+ },
6357
+ findMarksAt: function(pos) {
6358
+ pos = clipPos(this, pos);
6359
+ var markers = [], spans = getLine(this, pos.line).markedSpans;
6360
+ if (spans) { for (var i = 0; i < spans.length; ++i) {
6361
+ var span = spans[i];
6362
+ if ((span.from == null || span.from <= pos.ch) &&
6363
+ (span.to == null || span.to >= pos.ch))
6364
+ { markers.push(span.marker.parent || span.marker); }
6365
+ } }
6366
+ return markers
6367
+ },
6368
+ findMarks: function(from, to, filter) {
6369
+ from = clipPos(this, from); to = clipPos(this, to);
6370
+ var found = [], lineNo = from.line;
6371
+ this.iter(from.line, to.line + 1, function (line) {
6372
+ var spans = line.markedSpans;
6373
+ if (spans) { for (var i = 0; i < spans.length; i++) {
6374
+ var span = spans[i];
6375
+ if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
6376
+ span.from == null && lineNo != from.line ||
6377
+ span.from != null && lineNo == to.line && span.from >= to.ch) &&
6378
+ (!filter || filter(span.marker)))
6379
+ { found.push(span.marker.parent || span.marker); }
6380
+ } }
6381
+ ++lineNo;
6382
+ });
6383
+ return found
6384
+ },
6385
+ getAllMarks: function() {
6386
+ var markers = [];
6387
+ this.iter(function (line) {
6388
+ var sps = line.markedSpans;
6389
+ if (sps) { for (var i = 0; i < sps.length; ++i)
6390
+ { if (sps[i].from != null) { markers.push(sps[i].marker); } } }
6391
+ });
6392
+ return markers
6393
+ },
6394
+
6395
+ posFromIndex: function(off) {
6396
+ var ch, lineNo = this.first, sepSize = this.lineSeparator().length;
6397
+ this.iter(function (line) {
6398
+ var sz = line.text.length + sepSize;
6399
+ if (sz > off) { ch = off; return true }
6400
+ off -= sz;
6401
+ ++lineNo;
6402
+ });
6403
+ return clipPos(this, Pos(lineNo, ch))
6404
+ },
6405
+ indexFromPos: function (coords) {
6406
+ coords = clipPos(this, coords);
6407
+ var index = coords.ch;
6408
+ if (coords.line < this.first || coords.ch < 0) { return 0 }
6409
+ var sepSize = this.lineSeparator().length;
6410
+ this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value
6411
+ index += line.text.length + sepSize;
6412
+ });
6413
+ return index
6414
+ },
6415
+
6416
+ copy: function(copyHistory) {
6417
+ var doc = new Doc(getLines(this, this.first, this.first + this.size),
6418
+ this.modeOption, this.first, this.lineSep, this.direction);
6419
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
6420
+ doc.sel = this.sel;
6421
+ doc.extend = false;
6422
+ if (copyHistory) {
6423
+ doc.history.undoDepth = this.history.undoDepth;
6424
+ doc.setHistory(this.getHistory());
6425
+ }
6426
+ return doc
6427
+ },
6428
+
6429
+ linkedDoc: function(options) {
6430
+ if (!options) { options = {}; }
6431
+ var from = this.first, to = this.first + this.size;
6432
+ if (options.from != null && options.from > from) { from = options.from; }
6433
+ if (options.to != null && options.to < to) { to = options.to; }
6434
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction);
6435
+ if (options.sharedHist) { copy.history = this.history
6436
+ ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
6437
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
6438
+ copySharedMarkers(copy, findSharedMarkers(this));
6439
+ return copy
6440
+ },
6441
+ unlinkDoc: function(other) {
6442
+ if (other instanceof CodeMirror) { other = other.doc; }
6443
+ if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
6444
+ var link = this.linked[i];
6445
+ if (link.doc != other) { continue }
6446
+ this.linked.splice(i, 1);
6447
+ other.unlinkDoc(this);
6448
+ detachSharedMarkers(findSharedMarkers(this));
6449
+ break
6450
+ } }
6451
+ // If the histories were shared, split them again
6452
+ if (other.history == this.history) {
6453
+ var splitIds = [other.id];
6454
+ linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true);
6455
+ other.history = new History(null);
6456
+ other.history.done = copyHistoryArray(this.history.done, splitIds);
6457
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds);
6458
+ }
6459
+ },
6460
+ iterLinkedDocs: function(f) {linkedDocs(this, f);},
6461
+
6462
+ getMode: function() {return this.mode},
6463
+ getEditor: function() {return this.cm},
6464
+
6465
+ splitLines: function(str) {
6466
+ if (this.lineSep) { return str.split(this.lineSep) }
6467
+ return splitLinesAuto(str)
6468
+ },
6469
+ lineSeparator: function() { return this.lineSep || "\n" },
6470
+
6471
+ setDirection: docMethodOp(function (dir) {
6472
+ if (dir != "rtl") { dir = "ltr"; }
6473
+ if (dir == this.direction) { return }
6474
+ this.direction = dir;
6475
+ this.iter(function (line) { return line.order = null; });
6476
+ if (this.cm) { directionChanged(this.cm); }
6477
+ })
6478
+ });
6479
+
6480
+ // Public alias.
6481
+ Doc.prototype.eachLine = Doc.prototype.iter;
6482
+
6483
+ // Kludge to work around strange IE behavior where it'll sometimes
6484
+ // re-fire a series of drag-related events right after the drop (#1551)
6485
+ var lastDrop = 0;
6486
+
6487
+ function onDrop(e) {
6488
+ var cm = this;
6489
+ clearDragCursor(cm);
6490
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
6491
+ { return }
6492
+ e_preventDefault(e);
6493
+ if (ie) { lastDrop = +new Date; }
6494
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
6495
+ if (!pos || cm.isReadOnly()) { return }
6496
+ // Might be a file drop, in which case we simply extract the text
6497
+ // and insert it.
6498
+ if (files && files.length && window.FileReader && window.File) {
6499
+ var n = files.length, text = Array(n), read = 0;
6500
+ var markAsReadAndPasteIfAllFilesAreRead = function () {
6501
+ if (++read == n) {
6502
+ operation(cm, function () {
6503
+ pos = clipPos(cm.doc, pos);
6504
+ var change = {from: pos, to: pos,
6505
+ text: cm.doc.splitLines(
6506
+ text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())),
6507
+ origin: "paste"};
6508
+ makeChange(cm.doc, change);
6509
+ setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change))));
6510
+ })();
6511
+ }
6512
+ };
6513
+ var readTextFromFile = function (file, i) {
6514
+ if (cm.options.allowDropFileTypes &&
6515
+ indexOf(cm.options.allowDropFileTypes, file.type) == -1) {
6516
+ markAsReadAndPasteIfAllFilesAreRead();
6517
+ return
6518
+ }
6519
+ var reader = new FileReader;
6520
+ reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); };
6521
+ reader.onload = function () {
6522
+ var content = reader.result;
6523
+ if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) {
6524
+ markAsReadAndPasteIfAllFilesAreRead();
6525
+ return
6526
+ }
6527
+ text[i] = content;
6528
+ markAsReadAndPasteIfAllFilesAreRead();
6529
+ };
6530
+ reader.readAsText(file);
6531
+ };
6532
+ for (var i = 0; i < files.length; i++) { readTextFromFile(files[i], i); }
6533
+ } else { // Normal drop
6534
+ // Don't do a replace if the drop happened inside of the selected text.
6535
+ if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
6536
+ cm.state.draggingText(e);
6537
+ // Ensure the editor is re-focused
6538
+ setTimeout(function () { return cm.display.input.focus(); }, 20);
6539
+ return
6540
+ }
6541
+ try {
6542
+ var text$1 = e.dataTransfer.getData("Text");
6543
+ if (text$1) {
6544
+ var selected;
6545
+ if (cm.state.draggingText && !cm.state.draggingText.copy)
6546
+ { selected = cm.listSelections(); }
6547
+ setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
6548
+ if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)
6549
+ { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } }
6550
+ cm.replaceSelection(text$1, "around", "paste");
6551
+ cm.display.input.focus();
6552
+ }
6553
+ }
6554
+ catch(e$1){}
6555
+ }
6556
+ }
6557
+
6558
+ function onDragStart(cm, e) {
6559
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
6560
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }
6561
+
6562
+ e.dataTransfer.setData("Text", cm.getSelection());
6563
+ e.dataTransfer.effectAllowed = "copyMove";
6564
+
6565
+ // Use dummy image instead of default browsers image.
6566
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
6567
+ if (e.dataTransfer.setDragImage && !safari) {
6568
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
6569
+ img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
6570
+ if (presto) {
6571
+ img.width = img.height = 1;
6572
+ cm.display.wrapper.appendChild(img);
6573
+ // Force a relayout, or Opera won't use our image for some obscure reason
6574
+ img._top = img.offsetTop;
6575
+ }
6576
+ e.dataTransfer.setDragImage(img, 0, 0);
6577
+ if (presto) { img.parentNode.removeChild(img); }
6578
+ }
6579
+ }
6580
+
6581
+ function onDragOver(cm, e) {
6582
+ var pos = posFromMouse(cm, e);
6583
+ if (!pos) { return }
6584
+ var frag = document.createDocumentFragment();
6585
+ drawSelectionCursor(cm, pos, frag);
6586
+ if (!cm.display.dragCursor) {
6587
+ cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
6588
+ cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
6589
+ }
6590
+ removeChildrenAndAdd(cm.display.dragCursor, frag);
6591
  }
6592
 
6593
+ function clearDragCursor(cm) {
6594
+ if (cm.display.dragCursor) {
6595
+ cm.display.lineSpace.removeChild(cm.display.dragCursor);
6596
+ cm.display.dragCursor = null;
 
 
 
6597
  }
 
6598
  }
6599
 
6600
+ // These must be handled carefully, because naively registering a
6601
+ // handler for each editor will cause the editors to never be
6602
+ // garbage collected.
6603
+
6604
+ function forEachCodeMirror(f) {
6605
+ if (!document.getElementsByClassName) { return }
6606
+ var byClass = document.getElementsByClassName("CodeMirror"), editors = [];
6607
+ for (var i = 0; i < byClass.length; i++) {
6608
+ var cm = byClass[i].CodeMirror;
6609
+ if (cm) { editors.push(cm); }
 
6610
  }
6611
+ if (editors.length) { editors[0].operation(function () {
6612
+ for (var i = 0; i < editors.length; i++) { f(editors[i]); }
6613
+ }); }
6614
  }
6615
 
6616
+ var globalsRegistered = false;
6617
+ function ensureGlobalHandlers() {
6618
+ if (globalsRegistered) { return }
6619
+ registerGlobalHandlers();
6620
+ globalsRegistered = true;
6621
+ }
6622
+ function registerGlobalHandlers() {
6623
+ // When the window resizes, we need to refresh active editors.
6624
+ var resizeTimer;
6625
+ on(window, "resize", function () {
6626
+ if (resizeTimer == null) { resizeTimer = setTimeout(function () {
6627
+ resizeTimer = null;
6628
+ forEachCodeMirror(onResize);
6629
+ }, 100); }
6630
+ });
6631
+ // When the window loses focus, we want to show the editor as blurred
6632
+ on(window, "blur", function () { return forEachCodeMirror(onBlur); });
6633
+ }
6634
+ // Called when the window resizes
6635
+ function onResize(cm) {
6636
+ var d = cm.display;
6637
+ // Might be a text scaling operation, clear size caches.
6638
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
6639
+ d.scrollbarsClipped = false;
6640
+ cm.setSize();
6641
  }
6642
 
6643
+ var keyNames = {
6644
+ 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
6645
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
6646
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
6647
+ 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
6648
+ 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock",
6649
+ 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
6650
+ 221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
6651
+ 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
6652
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6653
 
6654
+ // Number keys
6655
+ for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); }
6656
+ // Alphabetic keys
6657
+ for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); }
6658
+ // Function keys
6659
+ for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; }
6660
 
6661
+ var keyMap = {};
 
 
 
 
 
 
 
 
6662
 
6663
+ keyMap.basic = {
6664
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
6665
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
6666
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
6667
+ "Tab": "defaultTab", "Shift-Tab": "indentAuto",
6668
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
6669
+ "Esc": "singleSelection"
6670
+ };
6671
+ // Note that the save and find-related commands aren't defined by
6672
+ // default. User code or addons can define them. Unknown commands
6673
+ // are simply ignored.
6674
+ keyMap.pcDefault = {
6675
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
6676
+ "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
6677
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
6678
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
6679
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
6680
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
6681
+ "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
6682
+ "fallthrough": "basic"
6683
+ };
6684
+ // Very basic readline/emacs-style bindings, which are standard on Mac.
6685
+ keyMap.emacsy = {
6686
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
6687
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
6688
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
6689
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
6690
+ "Ctrl-O": "openLine"
6691
+ };
6692
+ keyMap.macDefault = {
6693
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
6694
+ "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
6695
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
6696
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
6697
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
6698
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
6699
+ "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
6700
+ "fallthrough": ["basic", "emacsy"]
6701
+ };
6702
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
6703
 
6704
+ // KEYMAP DISPATCH
 
 
6705
 
6706
+ function normalizeKeyName(name) {
6707
+ var parts = name.split(/-(?!$)/);
6708
+ name = parts[parts.length - 1];
6709
+ var alt, ctrl, shift, cmd;
6710
+ for (var i = 0; i < parts.length - 1; i++) {
6711
+ var mod = parts[i];
6712
+ if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; }
6713
+ else if (/^a(lt)?$/i.test(mod)) { alt = true; }
6714
+ else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; }
6715
+ else if (/^s(hift)?$/i.test(mod)) { shift = true; }
6716
+ else { throw new Error("Unrecognized modifier name: " + mod) }
6717
+ }
6718
+ if (alt) { name = "Alt-" + name; }
6719
+ if (ctrl) { name = "Ctrl-" + name; }
6720
+ if (cmd) { name = "Cmd-" + name; }
6721
+ if (shift) { name = "Shift-" + name; }
6722
+ return name
6723
  }
6724
 
6725
+ // This is a kludge to keep keymaps mostly working as raw objects
6726
+ // (backwards compatibility) while at the same time support features
6727
+ // like normalization and multi-stroke key bindings. It compiles a
6728
+ // new normalized keymap, and then updates the old object to reflect
6729
+ // this.
6730
+ function normalizeKeyMap(keymap) {
6731
+ var copy = {};
6732
+ for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {
6733
+ var value = keymap[keyname];
6734
+ if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }
6735
+ if (value == "...") { delete keymap[keyname]; continue }
6736
 
6737
+ var keys = map(keyname.split(" "), normalizeKeyName);
6738
+ for (var i = 0; i < keys.length; i++) {
6739
+ var val = (void 0), name = (void 0);
6740
+ if (i == keys.length - 1) {
6741
+ name = keys.join(" ");
6742
+ val = value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6743
  } else {
6744
+ name = keys.slice(0, i + 1).join(" ");
6745
+ val = "...";
 
 
 
6746
  }
6747
+ var prev = copy[name];
6748
+ if (!prev) { copy[name] = val; }
6749
+ else if (prev != val) { throw new Error("Inconsistent bindings for " + name) }
6750
  }
6751
+ delete keymap[keyname];
6752
+ } }
6753
+ for (var prop in copy) { keymap[prop] = copy[prop]; }
6754
+ return keymap
 
 
 
 
 
 
6755
  }
6756
 
6757
+ function lookupKey(key, map, handle, context) {
6758
+ map = getKeyMap(map);
6759
+ var found = map.call ? map.call(key, context) : map[key];
6760
+ if (found === false) { return "nothing" }
6761
+ if (found === "...") { return "multi" }
6762
+ if (found != null && handle(found)) { return "handled" }
6763
 
6764
+ if (map.fallthrough) {
6765
+ if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
6766
+ { return lookupKey(key, map.fallthrough, handle, context) }
6767
+ for (var i = 0; i < map.fallthrough.length; i++) {
6768
+ var result = lookupKey(key, map.fallthrough[i], handle, context);
6769
+ if (result) { return result }
 
 
 
 
 
 
 
 
 
 
 
6770
  }
6771
+ }
6772
  }
6773
 
6774
+ // Modifier key presses don't count as 'real' key presses for the
6775
+ // purpose of keymap fallthrough.
6776
+ function isModifierKey(value) {
6777
+ var name = typeof value == "string" ? value : keyNames[value.keyCode];
6778
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"
 
 
 
 
 
 
 
 
6779
  }
6780
 
6781
+ function addModifierNames(name, event, noShift) {
6782
+ var base = name;
6783
+ if (event.altKey && base != "Alt") { name = "Alt-" + name; }
6784
+ if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; }
6785
+ if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; }
6786
+ if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; }
6787
+ return name
6788
+ }
 
6789
 
6790
+ // Look up the name of a key as indicated by an event object.
6791
+ function keyName(event, noShift) {
6792
+ if (presto && event.keyCode == 34 && event["char"]) { return false }
6793
+ var name = keyNames[event.keyCode];
6794
+ if (name == null || event.altGraphKey) { return false }
6795
+ // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause,
6796
+ // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+)
6797
+ if (event.keyCode == 3 && event.code) { name = event.code; }
6798
+ return addModifierNames(name, event, noShift)
6799
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6800
 
6801
+ function getKeyMap(val) {
6802
+ return typeof val == "string" ? keyMap[val] : val
6803
+ }
6804
+
6805
+ // Helper for deleting text near the selection(s), used to implement
6806
+ // backspace, delete, and similar functionality.
6807
+ function deleteNearSelection(cm, compute) {
6808
+ var ranges = cm.doc.sel.ranges, kill = [];
6809
+ // Build up a set of ranges to kill first, merging overlapping
6810
+ // ranges.
6811
+ for (var i = 0; i < ranges.length; i++) {
6812
+ var toKill = compute(ranges[i]);
6813
+ while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
6814
+ var replaced = kill.pop();
6815
+ if (cmp(replaced.from, toKill.from) < 0) {
6816
+ toKill.from = replaced.from;
6817
+ break
6818
  }
 
 
6819
  }
6820
+ kill.push(toKill);
6821
  }
6822
+ // Next, remove those actual ranges.
6823
+ runInOp(cm, function () {
6824
+ for (var i = kill.length - 1; i >= 0; i--)
6825
+ { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); }
6826
+ ensureCursorVisible(cm);
6827
+ });
6828
  }
6829
 
6830
+ function moveCharLogically(line, ch, dir) {
6831
+ var target = skipExtendingChars(line.text, ch + dir, dir);
6832
+ return target < 0 || target > line.text.length ? null : target
6833
+ }
6834
+
6835
+ function moveLogically(line, start, dir) {
6836
+ var ch = moveCharLogically(line, start.ch, dir);
6837
+ return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before")
6838
+ }
6839
+
6840
+ function endOfLine(visually, cm, lineObj, lineNo, dir) {
6841
+ if (visually) {
6842
+ if (cm.doc.direction == "rtl") { dir = -dir; }
6843
+ var order = getOrder(lineObj, cm.doc.direction);
6844
+ if (order) {
6845
+ var part = dir < 0 ? lst(order) : order[0];
6846
+ var moveInStorageOrder = (dir < 0) == (part.level == 1);
6847
+ var sticky = moveInStorageOrder ? "after" : "before";
6848
+ var ch;
6849
+ // With a wrapped rtl chunk (possibly spanning multiple bidi parts),
6850
+ // it could be that the last bidi part is not on the last visual line,
6851
+ // since visual lines contain content order-consecutive chunks.
6852
+ // Thus, in rtl, we are looking for the first (content-order) character
6853
+ // in the rtl chunk that is on the last line (that is, the same line
6854
+ // as the last (content-order) character).
6855
+ if (part.level > 0 || cm.doc.direction == "rtl") {
6856
+ var prep = prepareMeasureForLine(cm, lineObj);
6857
+ ch = dir < 0 ? lineObj.text.length - 1 : 0;
6858
+ var targetTop = measureCharPrepared(cm, prep, ch).top;
6859
+ ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
6860
+ if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); }
6861
+ } else { ch = dir < 0 ? part.to : part.from; }
6862
+ return new Pos(lineNo, ch, sticky)
6863
+ }
6864
+ }
6865
+ return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after")
6866
+ }
6867
+
6868
+ function moveVisually(cm, line, start, dir) {
6869
+ var bidi = getOrder(line, cm.doc.direction);
6870
+ if (!bidi) { return moveLogically(line, start, dir) }
6871
+ if (start.ch >= line.text.length) {
6872
+ start.ch = line.text.length;
6873
+ start.sticky = "before";
6874
+ } else if (start.ch <= 0) {
6875
+ start.ch = 0;
6876
+ start.sticky = "after";
6877
+ }
6878
+ var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos];
6879
+ if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) {
6880
+ // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines,
6881
+ // nothing interesting happens.
6882
+ return moveLogically(line, start, dir)
6883
+ }
6884
+
6885
+ var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); };
6886
+ var prep;
6887
+ var getWrappedLineExtent = function (ch) {
6888
+ if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} }
6889
+ prep = prep || prepareMeasureForLine(cm, line);
6890
+ return wrappedLineExtentChar(cm, line, prep, ch)
6891
+ };
6892
+ var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch);
6893
 
6894
+ if (cm.doc.direction == "rtl" || part.level == 1) {
6895
+ var moveInStorageOrder = (part.level == 1) == (dir < 0);
6896
+ var ch = mv(start, moveInStorageOrder ? 1 : -1);
6897
+ if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) {
6898
+ // Case 2: We move within an rtl part or in an rtl editor on the same visual line
6899
+ var sticky = moveInStorageOrder ? "before" : "after";
6900
+ return new Pos(start.line, ch, sticky)
6901
+ }
6902
  }
6903
+
6904
+ // Case 3: Could not move within this bidi part in this visual line, so leave
6905
+ // the current bidi part
6906
+
6907
+ var searchInVisualLine = function (partPos, dir, wrappedLineExtent) {
6908
+ var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder
6909
+ ? new Pos(start.line, mv(ch, 1), "before")
6910
+ : new Pos(start.line, ch, "after"); };
6911
+
6912
+ for (; partPos >= 0 && partPos < bidi.length; partPos += dir) {
6913
+ var part = bidi[partPos];
6914
+ var moveInStorageOrder = (dir > 0) == (part.level != 1);
6915
+ var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1);
6916
+ if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) }
6917
+ ch = moveInStorageOrder ? part.from : mv(part.to, -1);
6918
+ if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) }
6919
+ }
6920
+ };
6921
+
6922
+ // Case 3a: Look for other bidi parts on the same visual line
6923
+ var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent);
6924
+ if (res) { return res }
6925
+
6926
+ // Case 3b: Look for other bidi parts on the next visual line
6927
+ var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1);
6928
+ if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) {
6929
+ res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh));
6930
+ if (res) { return res }
6931
  }
6932
 
6933
+ // Case 4: Nowhere to move
6934
+ return null
6935
+ }
6936
 
6937
+ // Commands are parameter-less actions that can be performed on an
6938
+ // editor, mostly used for keybindings.
6939
+ var commands = {
6940
+ selectAll: selectAll,
6941
+ singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); },
6942
+ killLine: function (cm) { return deleteNearSelection(cm, function (range) {
6943
+ if (range.empty()) {
6944
+ var len = getLine(cm.doc, range.head.line).text.length;
6945
+ if (range.head.ch == len && range.head.line < cm.lastLine())
6946
+ { return {from: range.head, to: Pos(range.head.line + 1, 0)} }
6947
+ else
6948
+ { return {from: range.head, to: Pos(range.head.line, len)} }
 
 
6949
  } else {
6950
+ return {from: range.from(), to: range.to()}
6951
+ }
6952
+ }); },
6953
+ deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({
6954
+ from: Pos(range.from().line, 0),
6955
+ to: clipPos(cm.doc, Pos(range.to().line + 1, 0))
6956
+ }); }); },
6957
+ delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({
6958
+ from: Pos(range.from().line, 0), to: range.from()
6959
+ }); }); },
6960
+ delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {
6961
+ var top = cm.charCoords(range.head, "div").top + 5;
6962
+ var leftPos = cm.coordsChar({left: 0, top: top}, "div");
6963
+ return {from: leftPos, to: range.from()}
6964
+ }); },
6965
+ delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {
6966
+ var top = cm.charCoords(range.head, "div").top + 5;
6967
+ var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
6968
+ return {from: range.from(), to: rightPos }
6969
+ }); },
6970
+ undo: function (cm) { return cm.undo(); },
6971
+ redo: function (cm) { return cm.redo(); },
6972
+ undoSelection: function (cm) { return cm.undoSelection(); },
6973
+ redoSelection: function (cm) { return cm.redoSelection(); },
6974
+ goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },
6975
+ goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },
6976
+ goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },
6977
+ {origin: "+move", bias: 1}
6978
+ ); },
6979
+ goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },
6980
+ {origin: "+move", bias: 1}
6981
+ ); },
6982
+ goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },
6983
+ {origin: "+move", bias: -1}
6984
+ ); },
6985
+ goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {
6986
+ var top = cm.cursorCoords(range.head, "div").top + 5;
6987
+ return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
6988
+ }, sel_move); },
6989
+ goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {
6990
+ var top = cm.cursorCoords(range.head, "div").top + 5;
6991
+ return cm.coordsChar({left: 0, top: top}, "div")
6992
+ }, sel_move); },
6993
+ goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {
6994
+ var top = cm.cursorCoords(range.head, "div").top + 5;
6995
+ var pos = cm.coordsChar({left: 0, top: top}, "div");
6996
+ if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) }
6997
+ return pos
6998
+ }, sel_move); },
6999
+ goLineUp: function (cm) { return cm.moveV(-1, "line"); },
7000
+ goLineDown: function (cm) { return cm.moveV(1, "line"); },
7001
+ goPageUp: function (cm) { return cm.moveV(-1, "page"); },
7002
+ goPageDown: function (cm) { return cm.moveV(1, "page"); },
7003
+ goCharLeft: function (cm) { return cm.moveH(-1, "char"); },
7004
+ goCharRight: function (cm) { return cm.moveH(1, "char"); },
7005
+ goColumnLeft: function (cm) { return cm.moveH(-1, "column"); },
7006
+ goColumnRight: function (cm) { return cm.moveH(1, "column"); },
7007
+ goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
7008
+ goGroupRight: function (cm) { return cm.moveH(1, "group"); },
7009
+ goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
7010
+ goWordRight: function (cm) { return cm.moveH(1, "word"); },
7011
+ delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); },
7012
+ delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
7013
+ delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
7014
+ delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
7015
+ delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
7016
+ delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
7017
+ indentAuto: function (cm) { return cm.indentSelection("smart"); },
7018
+ indentMore: function (cm) { return cm.indentSelection("add"); },
7019
+ indentLess: function (cm) { return cm.indentSelection("subtract"); },
7020
+ insertTab: function (cm) { return cm.replaceSelection("\t"); },
7021
+ insertSoftTab: function (cm) {
7022
+ var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
7023
+ for (var i = 0; i < ranges.length; i++) {
7024
+ var pos = ranges[i].from();
7025
+ var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
7026
+ spaces.push(spaceStr(tabSize - col % tabSize));
7027
  }
7028
+ cm.replaceSelections(spaces);
7029
+ },
7030
+ defaultTab: function (cm) {
7031
+ if (cm.somethingSelected()) { cm.indentSelection("add"); }
7032
+ else { cm.execCommand("insertTab"); }
7033
+ },
7034
+ // Swap the two chars left and right of each selection's head.
7035
+ // Move cursor behind the two swapped characters afterwards.
7036
+ //
7037
+ // Doesn't consider line feeds a character.
7038
+ // Doesn't scan more than one line above to find a character.
7039
+ // Doesn't do anything on an empty line.
7040
+ // Doesn't do anything with non-empty selections.
7041
+ transposeChars: function (cm) { return runInOp(cm, function () {
7042
+ var ranges = cm.listSelections(), newSel = [];
7043
+ for (var i = 0; i < ranges.length; i++) {
7044
+ if (!ranges[i].empty()) { continue }
7045
+ var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
7046
+ if (line) {
7047
+ if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); }
7048
+ if (cur.ch > 0) {
7049
+ cur = new Pos(cur.line, cur.ch + 1);
7050
+ cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
7051
+ Pos(cur.line, cur.ch - 2), cur, "+transpose");
7052
+ } else if (cur.line > cm.doc.first) {
7053
+ var prev = getLine(cm.doc, cur.line - 1).text;
7054
+ if (prev) {
7055
+ cur = new Pos(cur.line, 1);
7056
+ cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
7057
+ prev.charAt(prev.length - 1),
7058
+ Pos(cur.line - 1, prev.length - 1), cur, "+transpose");
7059
+ }
7060
+ }
7061
+ }
7062
+ newSel.push(new Range(cur, cur));
7063
+ }
7064
+ cm.setSelections(newSel);
7065
+ }); },
7066
+ newlineAndIndent: function (cm) { return runInOp(cm, function () {
7067
+ var sels = cm.listSelections();
7068
+ for (var i = sels.length - 1; i >= 0; i--)
7069
+ { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); }
7070
+ sels = cm.listSelections();
7071
+ for (var i$1 = 0; i$1 < sels.length; i$1++)
7072
+ { cm.indentLine(sels[i$1].from().line, null, true); }
7073
+ ensureCursorVisible(cm);
7074
+ }); },
7075
+ openLine: function (cm) { return cm.replaceSelection("\n", "start"); },
7076
+ toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }
7077
+ };
7078
+
7079
+
7080
+ function lineStart(cm, lineN) {
7081
+ var line = getLine(cm.doc, lineN);
7082
+ var visual = visualLine(line);
7083
+ if (visual != line) { lineN = lineNo(visual); }
7084
+ return endOfLine(true, cm, visual, lineN, 1)
7085
+ }
7086
+ function lineEnd(cm, lineN) {
7087
+ var line = getLine(cm.doc, lineN);
7088
+ var visual = visualLineEnd(line);
7089
+ if (visual != line) { lineN = lineNo(visual); }
7090
+ return endOfLine(true, cm, line, lineN, -1)
7091
+ }
7092
+ function lineStartSmart(cm, pos) {
7093
+ var start = lineStart(cm, pos.line);
7094
+ var line = getLine(cm.doc, start.line);
7095
+ var order = getOrder(line, cm.doc.direction);
7096
+ if (!order || order[0].level == 0) {
7097
+ var firstNonWS = Math.max(start.ch, line.text.search(/\S/));
7098
+ var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
7099
+ return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky)
7100
  }
7101
+ return start
7102
+ }
7103
 
7104
+ // Run a handler that was bound to a key.
7105
+ function doHandleBinding(cm, bound, dropShift) {
7106
+ if (typeof bound == "string") {
7107
+ bound = commands[bound];
7108
+ if (!bound) { return false }
7109
+ }
7110
+ // Ensure previous input has been read, so that the handler sees a
7111
+ // consistent view of the document
7112
+ cm.display.input.ensurePolled();
7113
+ var prevShift = cm.display.shift, done = false;
7114
+ try {
7115
+ if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
7116
+ if (dropShift) { cm.display.shift = false; }
7117
+ done = bound(cm) != Pass;
7118
+ } finally {
7119
+ cm.display.shift = prevShift;
7120
+ cm.state.suppressEdits = false;
7121
+ }
7122
+ return done
7123
  }
7124
 
7125
+ function lookupKeyForEditor(cm, name, handle) {
7126
+ for (var i = 0; i < cm.state.keyMaps.length; i++) {
7127
+ var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
7128
+ if (result) { return result }
7129
+ }
7130
+ return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
7131
+ || lookupKey(name, cm.options.keyMap, handle, cm)
7132
+ }
 
 
 
 
7133
 
7134
+ // Note that, despite the name, this function is also used to check
7135
+ // for bound mouse clicks.
7136
+
7137
+ var stopSeq = new Delayed;
7138
+
7139
+ function dispatchKey(cm, name, e, handle) {
7140
+ var seq = cm.state.keySeq;
7141
+ if (seq) {
7142
+ if (isModifierKey(name)) { return "handled" }
7143
+ if (/\'$/.test(name))
7144
+ { cm.state.keySeq = null; }
7145
+ else
7146
+ { stopSeq.set(50, function () {
7147
+ if (cm.state.keySeq == seq) {
7148
+ cm.state.keySeq = null;
7149
+ cm.display.input.reset();
7150
+ }
7151
+ }); }
7152
+ if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true }
7153
  }
7154
+ return dispatchKeyInner(cm, name, e, handle)
7155
  }
7156
 
7157
+ function dispatchKeyInner(cm, name, e, handle) {
7158
+ var result = lookupKeyForEditor(cm, name, handle);
7159
+
7160
+ if (result == "multi")
7161
+ { cm.state.keySeq = name; }
7162
+ if (result == "handled")
7163
+ { signalLater(cm, "keyHandled", cm, name, e); }
7164
+
7165
+ if (result == "handled" || result == "multi") {
7166
+ e_preventDefault(e);
7167
+ restartBlink(cm);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7168
  }
 
7169
 
7170
+ return !!result
7171
+ }
7172
+
7173
+ // Handle a key from the keydown event.
7174
+ function handleKeyBinding(cm, e) {
7175
+ var name = keyName(e, true);
7176
+ if (!name) { return false }
7177
+
7178
+ if (e.shiftKey && !cm.state.keySeq) {
7179
+ // First try to resolve full name (including 'Shift-'). Failing
7180
+ // that, see if there is a cursor-motion command (starting with
7181
+ // 'go') bound to the keyname without 'Shift-'.
7182
+ return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); })
7183
+ || dispatchKey(cm, name, e, function (b) {
7184
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
7185
+ { return doHandleBinding(cm, b) }
7186
+ })
7187
+ } else {
7188
+ return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })
7189
  }
 
 
 
7190
  }
7191
 
7192
+ // Handle a key from the keypress event
7193
+ function handleCharBinding(cm, e, ch) {
7194
+ return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); })
7195
+ }
7196
+
7197
+ var lastStoppedKey = null;
7198
+ function onKeyDown(e) {
7199
+ var cm = this;
7200
+ if (e.target && e.target != cm.display.input.getField()) { return }
7201
+ cm.curOp.focus = activeElt();
7202
+ if (signalDOMEvent(cm, e)) { return }
7203
+ // IE does strange things with escape.
7204
+ if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; }
7205
+ var code = e.keyCode;
7206
+ cm.display.shift = code == 16 || e.shiftKey;
7207
+ var handled = handleKeyBinding(cm, e);
7208
+ if (presto) {
7209
+ lastStoppedKey = handled ? code : null;
7210
+ // Opera has no cut event... we try to at least catch the key combo
7211
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
7212
+ { cm.replaceSelection("", null, "cut"); }
7213
+ }
7214
+ if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand)
7215
+ { document.execCommand("cut"); }
7216
+
7217
+ // Turn mouse into crosshair when Alt is held on Mac.
7218
+ if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
7219
+ { showCrossHair(cm); }
7220
+ }
7221
+
7222
+ function showCrossHair(cm) {
7223
+ var lineDiv = cm.display.lineDiv;
7224
+ addClass(lineDiv, "CodeMirror-crosshair");
7225
+
7226
+ function up(e) {
7227
+ if (e.keyCode == 18 || !e.altKey) {
7228
+ rmClass(lineDiv, "CodeMirror-crosshair");
7229
+ off(document, "keyup", up);
7230
+ off(document, "mouseover", up);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7231
  }
7232
  }
7233
+ on(document, "keyup", up);
7234
+ on(document, "mouseover", up);
7235
+ }
7236
 
7237
+ function onKeyUp(e) {
7238
+ if (e.keyCode == 16) { this.doc.sel.shift = false; }
7239
+ signalDOMEvent(this, e);
7240
+ }
7241
 
7242
+ function onKeyPress(e) {
7243
+ var cm = this;
7244
+ if (e.target && e.target != cm.display.input.getField()) { return }
7245
+ if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
7246
+ var keyCode = e.keyCode, charCode = e.charCode;
7247
+ if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
7248
+ if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }
7249
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
7250
+ // Some browsers fire keypress events for backspace
7251
+ if (ch == "\x08") { return }
7252
+ if (handleCharBinding(cm, e, ch)) { return }
7253
+ cm.display.input.onKeyPress(e);
7254
+ }
7255
 
7256
+ var DOUBLECLICK_DELAY = 400;
7257
+
7258
+ var PastClick = function(time, pos, button) {
7259
+ this.time = time;
7260
+ this.pos = pos;
7261
+ this.button = button;
7262
  };
7263
 
7264
+ PastClick.prototype.compare = function (time, pos, button) {
7265
+ return this.time + DOUBLECLICK_DELAY > time &&
7266
+ cmp(pos, this.pos) == 0 && button == this.button
7267
+ };
 
 
 
 
 
 
7268
 
7269
+ var lastClick, lastDoubleClick;
7270
+ function clickRepeat(pos, button) {
7271
+ var now = +new Date;
7272
+ if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) {
7273
+ lastClick = lastDoubleClick = null;
7274
+ return "triple"
7275
+ } else if (lastClick && lastClick.compare(now, pos, button)) {
7276
+ lastDoubleClick = new PastClick(now, pos, button);
7277
+ lastClick = null;
7278
+ return "double"
7279
+ } else {
7280
+ lastClick = new PastClick(now, pos, button);
7281
+ lastDoubleClick = null;
7282
+ return "single"
7283
+ }
7284
+ }
7285
 
7286
+ // A mouse down can be a single click, double click, triple click,
7287
+ // start of selection drag, start of text drag, new cursor
7288
+ // (ctrl-click), rectangle drag (alt-drag), or xwin
7289
+ // middle-click-paste. Or it might be a click on something we should
7290
+ // not interfere with, such as a scrollbar or widget.
7291
+ function onMouseDown(e) {
7292
+ var cm = this, display = cm.display;
7293
+ if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }
7294
+ display.input.ensurePolled();
7295
+ display.shift = e.shiftKey;
7296
 
7297
+ if (eventInWidget(display, e)) {
7298
+ if (!webkit) {
7299
+ // Briefly turn off draggability, to allow widgets to do
7300
+ // normal dragging things.
7301
+ display.scroller.draggable = false;
7302
+ setTimeout(function () { return display.scroller.draggable = true; }, 100);
7303
+ }
7304
+ return
7305
+ }
7306
+ if (clickInGutter(cm, e)) { return }
7307
+ var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single";
7308
+ window.focus();
 
 
 
 
 
 
 
 
 
7309
 
7310
+ // #3261: make sure, that we're not starting a second selection
7311
+ if (button == 1 && cm.state.selectingText)
7312
+ { cm.state.selectingText(e); }
7313
 
7314
+ if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return }
 
7315
 
7316
+ if (button == 1) {
7317
+ if (pos) { leftButtonDown(cm, pos, repeat, e); }
7318
+ else if (e_target(e) == display.scroller) { e_preventDefault(e); }
7319
+ } else if (button == 2) {
7320
+ if (pos) { extendSelection(cm.doc, pos); }
7321
+ setTimeout(function () { return display.input.focus(); }, 20);
7322
+ } else if (button == 3) {
7323
+ if (captureRightClick) { cm.display.input.onContextMenu(e); }
7324
+ else { delayBlurEvent(cm); }
7325
+ }
7326
+ }
7327
 
7328
+ function handleMappedButton(cm, button, pos, repeat, event) {
7329
+ var name = "Click";
7330
+ if (repeat == "double") { name = "Double" + name; }
7331
+ else if (repeat == "triple") { name = "Triple" + name; }
7332
+ name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name;
7333
 
7334
+ return dispatchKey(cm, addModifierNames(name, event), event, function (bound) {
7335
+ if (typeof bound == "string") { bound = commands[bound]; }
7336
+ if (!bound) { return false }
7337
+ var done = false;
7338
+ try {
7339
+ if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
7340
+ done = bound(cm, pos) != Pass;
7341
+ } finally {
7342
+ cm.state.suppressEdits = false;
7343
+ }
7344
+ return done
7345
+ })
7346
+ }
7347
 
7348
+ function configureMouse(cm, repeat, event) {
7349
+ var option = cm.getOption("configureMouse");
7350
+ var value = option ? option(cm, repeat, event) : {};
7351
+ if (value.unit == null) {
7352
+ var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey;
7353
+ value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line";
7354
+ }
7355
+ if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; }
7356
+ if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; }
7357
+ if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); }
7358
+ return value
7359
+ }
7360
 
7361
+ function leftButtonDown(cm, pos, repeat, event) {
7362
+ if (ie) { setTimeout(bind(ensureFocus, cm), 0); }
7363
+ else { cm.curOp.focus = activeElt(); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7364
 
7365
+ var behavior = configureMouse(cm, repeat, event);
7366
+
7367
+ var sel = cm.doc.sel, contained;
7368
+ if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
7369
+ repeat == "single" && (contained = sel.contains(pos)) > -1 &&
7370
+ (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) &&
7371
+ (cmp(contained.to(), pos) > 0 || pos.xRel < 0))
7372
+ { leftButtonStartDrag(cm, event, pos, behavior); }
7373
+ else
7374
+ { leftButtonSelect(cm, event, pos, behavior); }
7375
+ }
7376
+
7377
+ // Start a text drag. When it ends, see if any dragging actually
7378
+ // happen, and treat as a click if it didn't.
7379
+ function leftButtonStartDrag(cm, event, pos, behavior) {
7380
+ var display = cm.display, moved = false;
7381
+ var dragEnd = operation(cm, function (e) {
7382
+ if (webkit) { display.scroller.draggable = false; }
7383
+ cm.state.draggingText = false;
7384
+ if (cm.state.delayingBlurEvent) {
7385
+ if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; }
7386
+ else { delayBlurEvent(cm); }
7387
  }
7388
+ off(display.wrapper.ownerDocument, "mouseup", dragEnd);
7389
+ off(display.wrapper.ownerDocument, "mousemove", mouseMove);
7390
+ off(display.scroller, "dragstart", dragStart);
7391
+ off(display.scroller, "drop", dragEnd);
7392
+ if (!moved) {
7393
+ e_preventDefault(e);
7394
+ if (!behavior.addNew)
7395
+ { extendSelection(cm.doc, pos, null, null, behavior.extend); }
7396
+ // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
7397
+ if ((webkit && !safari) || ie && ie_version == 9)
7398
+ { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); }
7399
+ else
7400
+ { display.input.focus(); }
7401
  }
7402
+ });
7403
+ var mouseMove = function(e2) {
7404
+ moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10;
7405
+ };
7406
+ var dragStart = function () { return moved = true; };
7407
+ // Let the drag handler handle this.
7408
+ if (webkit) { display.scroller.draggable = true; }
7409
+ cm.state.draggingText = dragEnd;
7410
+ dragEnd.copy = !behavior.moveOnDrag;
7411
+ on(display.wrapper.ownerDocument, "mouseup", dragEnd);
7412
+ on(display.wrapper.ownerDocument, "mousemove", mouseMove);
7413
+ on(display.scroller, "dragstart", dragStart);
7414
+ on(display.scroller, "drop", dragEnd);
7415
 
7416
+ cm.state.delayingBlurEvent = true;
7417
+ setTimeout(function () { return display.input.focus(); }, 20);
7418
+ // IE's approach to draggable
7419
+ if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
7420
+ }
7421
 
7422
+ function rangeForUnit(cm, pos, unit) {
7423
+ if (unit == "char") { return new Range(pos, pos) }
7424
+ if (unit == "word") { return cm.findWordAt(pos) }
7425
+ if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }
7426
+ var result = unit(cm, pos);
7427
+ return new Range(result.from, result.to)
7428
+ }
7429
 
7430
+ // Normal selection, as opposed to text dragging.
7431
+ function leftButtonSelect(cm, event, start, behavior) {
7432
+ if (ie) { delayBlurEvent(cm); }
7433
+ var display = cm.display, doc = cm.doc;
7434
+ e_preventDefault(event);
 
 
 
 
 
 
7435
 
7436
+ var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
7437
+ if (behavior.addNew && !behavior.extend) {
7438
+ ourIndex = doc.sel.contains(start);
7439
+ if (ourIndex > -1)
7440
+ { ourRange = ranges[ourIndex]; }
7441
+ else
7442
+ { ourRange = new Range(start, start); }
7443
+ } else {
7444
+ ourRange = doc.sel.primary();
7445
+ ourIndex = doc.sel.primIndex;
7446
+ }
7447
 
7448
+ if (behavior.unit == "rectangle") {
7449
+ if (!behavior.addNew) { ourRange = new Range(start, start); }
7450
+ start = posFromMouse(cm, event, true, true);
7451
+ ourIndex = -1;
7452
+ } else {
7453
+ var range = rangeForUnit(cm, start, behavior.unit);
7454
+ if (behavior.extend)
7455
+ { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); }
7456
+ else
7457
+ { ourRange = range; }
7458
+ }
7459
+
7460
+ if (!behavior.addNew) {
7461
+ ourIndex = 0;
7462
+ setSelection(doc, new Selection([ourRange], 0), sel_mouse);
7463
+ startSel = doc.sel;
7464
+ } else if (ourIndex == -1) {
7465
+ ourIndex = ranges.length;
7466
+ setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex),
7467
+ {scroll: false, origin: "*mouse"});
7468
+ } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) {
7469
+ setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
7470
+ {scroll: false, origin: "*mouse"});
7471
+ startSel = doc.sel;
7472
+ } else {
7473
+ replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
7474
+ }
7475
+
7476
+ var lastPos = start;
7477
+ function extendTo(pos) {
7478
+ if (cmp(lastPos, pos) == 0) { return }
7479
+ lastPos = pos;
7480
+
7481
+ if (behavior.unit == "rectangle") {
7482
+ var ranges = [], tabSize = cm.options.tabSize;
7483
+ var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
7484
+ var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
7485
+ var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
7486
+ for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
7487
+ line <= end; line++) {
7488
+ var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
7489
+ if (left == right)
7490
+ { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); }
7491
+ else if (text.length > leftPos)
7492
+ { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); }
7493
  }
7494
+ if (!ranges.length) { ranges.push(new Range(start, start)); }
7495
+ setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
7496
+ {origin: "*mouse", scroll: false});
7497
+ cm.scrollIntoView(pos);
7498
+ } else {
7499
+ var oldRange = ourRange;
7500
+ var range = rangeForUnit(cm, pos, behavior.unit);
7501
+ var anchor = oldRange.anchor, head;
7502
+ if (cmp(range.anchor, anchor) > 0) {
7503
+ head = range.head;
7504
+ anchor = minPos(oldRange.from(), range.anchor);
7505
+ } else {
7506
+ head = range.anchor;
7507
+ anchor = maxPos(oldRange.to(), range.head);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7508
  }
7509
+ var ranges$1 = startSel.ranges.slice(0);
7510
+ ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head));
7511
+ setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse);
7512
+ }
7513
+ }
 
 
 
 
 
 
 
 
7514
 
7515
+ var editorSize = display.wrapper.getBoundingClientRect();
7516
+ // Used to ensure timeout re-tries don't fire when another extend
7517
+ // happened in the meantime (clearTimeout isn't reliable -- at
7518
+ // least on Chrome, the timeouts still happen even when cleared,
7519
+ // if the clear happens after their scheduled firing time).
7520
+ var counter = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
7521
 
7522
+ function extend(e) {
7523
+ var curCount = ++counter;
7524
+ var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle");
7525
+ if (!cur) { return }
7526
+ if (cmp(cur, lastPos) != 0) {
7527
+ cm.curOp.focus = activeElt();
7528
+ extendTo(cur);
7529
+ var visible = visibleLines(display, doc);
7530
+ if (cur.line >= visible.to || cur.line < visible.from)
7531
+ { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); }
7532
+ } else {
7533
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
7534
+ if (outside) { setTimeout(operation(cm, function () {
7535
+ if (counter != curCount) { return }
7536
+ display.scroller.scrollTop += outside;
7537
+ extend(e);
7538
+ }), 50); }
7539
  }
7540
+ }
 
7541
 
7542
+ function done(e) {
7543
+ cm.state.selectingText = false;
7544
+ counter = Infinity;
7545
+ // If e is null or undefined we interpret this as someone trying
7546
+ // to explicitly cancel the selection rather than the user
7547
+ // letting go of the mouse button.
7548
+ if (e) {
7549
+ e_preventDefault(e);
7550
+ display.input.focus();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7551
  }
7552
+ off(display.wrapper.ownerDocument, "mousemove", move);
7553
+ off(display.wrapper.ownerDocument, "mouseup", up);
7554
+ doc.history.lastSelOrigin = null;
7555
+ }
7556
 
7557
+ var move = operation(cm, function (e) {
7558
+ if (e.buttons === 0 || !e_button(e)) { done(e); }
7559
+ else { extend(e); }
7560
+ });
7561
+ var up = operation(cm, done);
7562
+ cm.state.selectingText = up;
7563
+ on(display.wrapper.ownerDocument, "mousemove", move);
7564
+ on(display.wrapper.ownerDocument, "mouseup", up);
7565
+ }
7566
+
7567
+ // Used when mouse-selecting to adjust the anchor to the proper side
7568
+ // of a bidi jump depending on the visual position of the head.
7569
+ function bidiSimplify(cm, range) {
7570
+ var anchor = range.anchor;
7571
+ var head = range.head;
7572
+ var anchorLine = getLine(cm.doc, anchor.line);
7573
+ if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range }
7574
+ var order = getOrder(anchorLine);
7575
+ if (!order) { return range }
7576
+ var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index];
7577
+ if (part.from != anchor.ch && part.to != anchor.ch) { return range }
7578
+ var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1);
7579
+ if (boundary == 0 || boundary == order.length) { return range }
7580
+
7581
+ // Compute the relative visual position of the head compared to the
7582
+ // anchor (<0 is to the left, >0 to the right)
7583
+ var leftSide;
7584
+ if (head.line != anchor.line) {
7585
+ leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0;
7586
+ } else {
7587
+ var headIndex = getBidiPartAt(order, head.ch, head.sticky);
7588
+ var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1);
7589
+ if (headIndex == boundary - 1 || headIndex == boundary)
7590
+ { leftSide = dir < 0; }
7591
+ else
7592
+ { leftSide = dir > 0; }
7593
+ }
7594
 
7595
+ var usePart = order[boundary + (leftSide ? -1 : 0)];
7596
+ var from = leftSide == (usePart.level == 1);
7597
+ var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before";
7598
+ return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head)
7599
+ }
7600
 
 
 
 
 
 
 
7601
 
7602
+ // Determines whether an event happened in the gutter, and fires the
7603
+ // handlers for the corresponding event.
7604
+ function gutterEvent(cm, e, type, prevent) {
7605
+ var mX, mY;
7606
+ if (e.touches) {
7607
+ mX = e.touches[0].clientX;
7608
+ mY = e.touches[0].clientY;
7609
+ } else {
7610
+ try { mX = e.clientX; mY = e.clientY; }
7611
+ catch(e$1) { return false }
7612
+ }
7613
+ if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
7614
+ if (prevent) { e_preventDefault(e); }
7615
 
7616
+ var display = cm.display;
7617
+ var lineBox = display.lineDiv.getBoundingClientRect();
7618
+
7619
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }
7620
+ mY -= lineBox.top - display.viewOffset;
7621
+
7622
+ for (var i = 0; i < cm.display.gutterSpecs.length; ++i) {
7623
+ var g = display.gutters.childNodes[i];
7624
+ if (g && g.getBoundingClientRect().right >= mX) {
7625
+ var line = lineAtHeight(cm.doc, mY);
7626
+ var gutter = cm.display.gutterSpecs[i];
7627
+ signal(cm, type, cm, line, gutter.className, e);
7628
+ return e_defaultPrevented(e)
7629
  }
7630
  }
 
7631
  }
7632
 
7633
+ function clickInGutter(cm, e) {
7634
+ return gutterEvent(cm, e, "gutterClick", true)
 
 
 
 
 
 
 
 
7635
  }
7636
 
7637
+ // CONTEXT MENU HANDLING
7638
 
7639
+ // To make the context menu work, we need to briefly unhide the
7640
+ // textarea (making it as unobtrusive as possible) to let the
7641
+ // right-click take effect on it.
7642
+ function onContextMenu(cm, e) {
7643
+ if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }
7644
+ if (signalDOMEvent(cm, e, "contextmenu")) { return }
7645
+ if (!captureRightClick) { cm.display.input.onContextMenu(e); }
 
 
 
 
 
7646
  }
7647
 
7648
+ function contextMenuInGutter(cm, e) {
7649
+ if (!hasHandler(cm, "gutterContextMenu")) { return false }
7650
+ return gutterEvent(cm, e, "gutterContextMenu", false)
 
 
 
 
 
 
 
 
 
7651
  }
7652
+
7653
+ function themeChanged(cm) {
7654
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
7655
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
7656
+ clearCaches(cm);
7657
  }
7658
 
7659
+ var Init = {toString: function(){return "CodeMirror.Init"}};
7660
+
7661
+ var defaults = {};
7662
+ var optionHandlers = {};
7663
+
7664
+ function defineOptions(CodeMirror) {
7665
+ var optionHandlers = CodeMirror.optionHandlers;
7666
+
7667
+ function option(name, deflt, handle, notOnInit) {
7668
+ CodeMirror.defaults[name] = deflt;
7669
+ if (handle) { optionHandlers[name] =
7670
+ notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; }
7671
+ }
7672
+
7673
+ CodeMirror.defineOption = option;
7674
+
7675
+ // Passed to option handlers when there is no old value.
7676
+ CodeMirror.Init = Init;
7677
+
7678
+ // These two are, on init, called from the constructor because they
7679
+ // have to be initialized before the editor can start at all.
7680
+ option("value", "", function (cm, val) { return cm.setValue(val); }, true);
7681
+ option("mode", null, function (cm, val) {
7682
+ cm.doc.modeOption = val;
7683
+ loadMode(cm);
7684
+ }, true);
7685
+
7686
+ option("indentUnit", 2, loadMode, true);
7687
+ option("indentWithTabs", false);
7688
+ option("smartIndent", true);
7689
+ option("tabSize", 4, function (cm) {
7690
+ resetModeState(cm);
7691
+ clearCaches(cm);
7692
+ regChange(cm);
7693
+ }, true);
7694
+
7695
+ option("lineSeparator", null, function (cm, val) {
7696
+ cm.doc.lineSep = val;
7697
+ if (!val) { return }
7698
+ var newBreaks = [], lineNo = cm.doc.first;
7699
+ cm.doc.iter(function (line) {
7700
+ for (var pos = 0;;) {
7701
+ var found = line.text.indexOf(val, pos);
7702
+ if (found == -1) { break }
7703
+ pos = found + val.length;
7704
+ newBreaks.push(Pos(lineNo, found));
7705
+ }
7706
+ lineNo++;
7707
+ });
7708
+ for (var i = newBreaks.length - 1; i >= 0; i--)
7709
+ { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
7710
+ });
7711
+ option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
7712
+ cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
7713
+ if (old != Init) { cm.refresh(); }
7714
+ });
7715
+ option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true);
7716
+ option("electricChars", true);
7717
+ option("inputStyle", mobile ? "contenteditable" : "textarea", function () {
7718
+ throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
7719
+ }, true);
7720
+ option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true);
7721
+ option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true);
7722
+ option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true);
7723
+ option("rtlMoveVisually", !windows);
7724
+ option("wholeLineUpdateBefore", true);
7725
+
7726
+ option("theme", "default", function (cm) {
7727
+ themeChanged(cm);
7728
+ updateGutters(cm);
7729
+ }, true);
7730
+ option("keyMap", "default", function (cm, val, old) {
7731
+ var next = getKeyMap(val);
7732
+ var prev = old != Init && getKeyMap(old);
7733
+ if (prev && prev.detach) { prev.detach(cm, next); }
7734
+ if (next.attach) { next.attach(cm, prev || null); }
7735
+ });
7736
+ option("extraKeys", null);
7737
+ option("configureMouse", null);
7738
+
7739
+ option("lineWrapping", false, wrappingChanged, true);
7740
+ option("gutters", [], function (cm, val) {
7741
+ cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers);
7742
+ updateGutters(cm);
7743
+ }, true);
7744
+ option("fixedGutter", true, function (cm, val) {
7745
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
7746
+ cm.refresh();
7747
+ }, true);
7748
+ option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true);
7749
+ option("scrollbarStyle", "native", function (cm) {
7750
+ initScrollbars(cm);
7751
+ updateScrollbars(cm);
7752
+ cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
7753
+ cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
7754
+ }, true);
7755
+ option("lineNumbers", false, function (cm, val) {
7756
+ cm.display.gutterSpecs = getGutters(cm.options.gutters, val);
7757
+ updateGutters(cm);
7758
+ }, true);
7759
+ option("firstLineNumber", 1, updateGutters, true);
7760
+ option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true);
7761
+ option("showCursorWhenSelecting", false, updateSelection, true);
7762
+
7763
+ option("resetSelectionOnContextMenu", true);
7764
+ option("lineWiseCopyCut", true);
7765
+ option("pasteLinesPerSelection", true);
7766
+ option("selectionsMayTouch", false);
7767
+
7768
+ option("readOnly", false, function (cm, val) {
7769
+ if (val == "nocursor") {
7770
+ onBlur(cm);
7771
+ cm.display.input.blur();
7772
+ }
7773
+ cm.display.input.readOnlyChanged(val);
7774
+ });
7775
+
7776
+ option("screenReaderLabel", null, function (cm, val) {
7777
+ val = (val === '') ? null : val;
7778
+ cm.display.input.screenReaderLabelChanged(val);
7779
+ });
7780
+
7781
+ option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true);
7782
+ option("dragDrop", true, dragDropChanged);
7783
+ option("allowDropFileTypes", null);
7784
+
7785
+ option("cursorBlinkRate", 530);
7786
+ option("cursorScrollMargin", 0);
7787
+ option("cursorHeight", 1, updateSelection, true);
7788
+ option("singleCursorHeightPerLine", true, updateSelection, true);
7789
+ option("workTime", 100);
7790
+ option("workDelay", 100);
7791
+ option("flattenSpans", true, resetModeState, true);
7792
+ option("addModeClass", false, resetModeState, true);
7793
+ option("pollInterval", 100);
7794
+ option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; });
7795
+ option("historyEventDelay", 1250);
7796
+ option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true);
7797
+ option("maxHighlightLength", 10000, resetModeState, true);
7798
+ option("moveInputWithCursor", true, function (cm, val) {
7799
+ if (!val) { cm.display.input.resetPosition(); }
7800
+ });
7801
+
7802
+ option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; });
7803
+ option("autofocus", null);
7804
+ option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true);
7805
+ option("phrases", null);
7806
  }
7807
 
7808
+ function dragDropChanged(cm, value, old) {
7809
+ var wasOn = old && old != Init;
7810
+ if (!value != !wasOn) {
7811
+ var funcs = cm.display.dragFunctions;
7812
+ var toggle = value ? on : off;
7813
+ toggle(cm.display.scroller, "dragstart", funcs.start);
7814
+ toggle(cm.display.scroller, "dragenter", funcs.enter);
7815
+ toggle(cm.display.scroller, "dragover", funcs.over);
7816
+ toggle(cm.display.scroller, "dragleave", funcs.leave);
7817
+ toggle(cm.display.scroller, "drop", funcs.drop);
7818
+ }
7819
+ }
7820
+
7821
+ function wrappingChanged(cm) {
7822
+ if (cm.options.lineWrapping) {
7823
+ addClass(cm.display.wrapper, "CodeMirror-wrap");
7824
+ cm.display.sizer.style.minWidth = "";
7825
+ cm.display.sizerWidth = null;
7826
+ } else {
7827
+ rmClass(cm.display.wrapper, "CodeMirror-wrap");
7828
+ findMaxLine(cm);
7829
  }
7830
+ estimateLineHeights(cm);
7831
+ regChange(cm);
7832
+ clearCaches(cm);
7833
+ setTimeout(function () { return updateScrollbars(cm); }, 100);
7834
  }
7835
 
7836
+ // A CodeMirror instance represents an editor. This is the object
7837
+ // that user code is usually dealing with.
7838
+
7839
+ function CodeMirror(place, options) {
7840
+ var this$1 = this;
7841
+
7842
+ if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) }
7843
+
7844
+ this.options = options = options ? copyObj(options) : {};
7845
+ // Determine effective options based on given values and defaults.
7846
+ copyObj(defaults, options, false);
7847
+
7848
+ var doc = options.value;
7849
+ if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); }
7850
+ else if (options.mode) { doc.modeOption = options.mode; }
7851
+ this.doc = doc;
7852
+
7853
+ var input = new CodeMirror.inputStyles[options.inputStyle](this);
7854
+ var display = this.display = new Display(place, doc, input, options);
7855
+ display.wrapper.CodeMirror = this;
7856
+ themeChanged(this);
7857
+ if (options.lineWrapping)
7858
+ { this.display.wrapper.className += " CodeMirror-wrap"; }
7859
+ initScrollbars(this);
7860
+
7861
+ this.state = {
7862
+ keyMaps: [], // stores maps added by addKeyMap
7863
+ overlays: [], // highlighting overlays, as added by addOverlay
7864
+ modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
7865
+ overwrite: false,
7866
+ delayingBlurEvent: false,
7867
+ focused: false,
7868
+ suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
7869
+ pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll
7870
+ selectingText: false,
7871
+ draggingText: false,
7872
+ highlight: new Delayed(), // stores highlight worker timeout
7873
+ keySeq: null, // Unfinished key sequence
7874
+ specialChars: null
7875
+ };
7876
+
7877
+ if (options.autofocus && !mobile) { display.input.focus(); }
7878
+
7879
+ // Override magic textarea content restore that IE sometimes does
7880
+ // on our hidden textarea on reload
7881
+ if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); }
7882
+
7883
+ registerEventHandlers(this);
7884
+ ensureGlobalHandlers();
7885
+
7886
+ startOperation(this);
7887
+ this.curOp.forceUpdate = true;
7888
+ attachDoc(this, doc);
7889
+
7890
+ if ((options.autofocus && !mobile) || this.hasFocus())
7891
+ { setTimeout(function () {
7892
+ if (this$1.hasFocus() && !this$1.state.focused) { onFocus(this$1); }
7893
+ }, 20); }
7894
+ else
7895
+ { onBlur(this); }
7896
+
7897
+ for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
7898
+ { optionHandlers[opt](this, options[opt], Init); } }
7899
+ maybeUpdateLineNumberWidth(this);
7900
+ if (options.finishInit) { options.finishInit(this); }
7901
+ for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); }
7902
+ endOperation(this);
7903
+ // Suppress optimizelegibility in Webkit, since it breaks text
7904
+ // measuring on line wrapping boundaries.
7905
+ if (webkit && options.lineWrapping &&
7906
+ getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
7907
+ { display.lineDiv.style.textRendering = "auto"; }
7908
  }
7909
 
7910
+ // The default configuration options.
7911
+ CodeMirror.defaults = defaults;
7912
+ // Functions to run when options are changed.
7913
+ CodeMirror.optionHandlers = optionHandlers;
7914
 
7915
+ // Attach the necessary event handlers when initializing the editor
7916
+ function registerEventHandlers(cm) {
7917
+ var d = cm.display;
7918
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
7919
+ // Older IE's will not fire a second mousedown for a double click
7920
+ if (ie && ie_version < 11)
7921
+ { on(d.scroller, "dblclick", operation(cm, function (e) {
7922
+ if (signalDOMEvent(cm, e)) { return }
7923
+ var pos = posFromMouse(cm, e);
7924
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }
7925
+ e_preventDefault(e);
7926
+ var word = cm.findWordAt(pos);
7927
+ extendSelection(cm.doc, word.anchor, word.head);
7928
+ })); }
7929
+ else
7930
+ { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); }
7931
+ // Some browsers fire contextmenu *after* opening the menu, at
7932
+ // which point we can't mess with it anymore. Context menu is
7933
+ // handled in onMouseDown for these browsers.
7934
+ on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); });
7935
+ on(d.input.getField(), "contextmenu", function (e) {
7936
+ if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); }
7937
+ });
7938
 
7939
+ // Used to suppress mouse event handling when a touch happens
7940
+ var touchFinished, prevTouch = {end: 0};
7941
+ function finishTouch() {
7942
+ if (d.activeTouch) {
7943
+ touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000);
7944
+ prevTouch = d.activeTouch;
7945
+ prevTouch.end = +new Date;
 
 
 
 
7946
  }
7947
  }
7948
+ function isMouseLikeTouchEvent(e) {
7949
+ if (e.touches.length != 1) { return false }
7950
+ var touch = e.touches[0];
7951
+ return touch.radiusX <= 1 && touch.radiusY <= 1
7952
+ }
7953
+ function farAway(touch, other) {
7954
+ if (other.left == null) { return true }
7955
+ var dx = other.left - touch.left, dy = other.top - touch.top;
7956
+ return dx * dx + dy * dy > 20 * 20
7957
+ }
7958
+ on(d.scroller, "touchstart", function (e) {
7959
+ if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) {
7960
+ d.input.ensurePolled();
7961
+ clearTimeout(touchFinished);
7962
+ var now = +new Date;
7963
+ d.activeTouch = {start: now, moved: false,
7964
+ prev: now - prevTouch.end <= 300 ? prevTouch : null};
7965
+ if (e.touches.length == 1) {
7966
+ d.activeTouch.left = e.touches[0].pageX;
7967
+ d.activeTouch.top = e.touches[0].pageY;
7968
+ }
7969
+ }
7970
+ });
7971
+ on(d.scroller, "touchmove", function () {
7972
+ if (d.activeTouch) { d.activeTouch.moved = true; }
7973
+ });
7974
+ on(d.scroller, "touchend", function (e) {
7975
+ var touch = d.activeTouch;
7976
+ if (touch && !eventInWidget(d, e) && touch.left != null &&
7977
+ !touch.moved && new Date - touch.start < 300) {
7978
+ var pos = cm.coordsChar(d.activeTouch, "page"), range;
7979
+ if (!touch.prev || farAway(touch, touch.prev)) // Single tap
7980
+ { range = new Range(pos, pos); }
7981
+ else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
7982
+ { range = cm.findWordAt(pos); }
7983
+ else // Triple tap
7984
+ { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); }
7985
+ cm.setSelection(range.anchor, range.head);
7986
+ cm.focus();
7987
+ e_preventDefault(e);
7988
+ }
7989
+ finishTouch();
7990
+ });
7991
+ on(d.scroller, "touchcancel", finishTouch);
7992
 
7993
+ // Sync scrolling between fake scrollbars and real scrollable
7994
+ // area, ensure viewport is updated when scrolling.
7995
+ on(d.scroller, "scroll", function () {
7996
+ if (d.scroller.clientHeight) {
7997
+ updateScrollTop(cm, d.scroller.scrollTop);
7998
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
7999
+ signal(cm, "scroll", cm);
8000
+ }
8001
+ });
8002
 
8003
+ // Listen to wheel events in order to try and update the viewport on time.
8004
+ on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); });
8005
+ on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); });
8006
 
8007
+ // Prevent wrapper from ever scrolling
8008
+ on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
8009
+
8010
+ d.dragFunctions = {
8011
+ enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }},
8012
+ over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
8013
+ start: function (e) { return onDragStart(cm, e); },
8014
+ drop: operation(cm, onDrop),
8015
+ leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }}
8016
+ };
 
 
 
 
8017
 
8018
+ var inp = d.input.getField();
8019
+ on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); });
8020
+ on(inp, "keydown", operation(cm, onKeyDown));
8021
+ on(inp, "keypress", operation(cm, onKeyPress));
8022
+ on(inp, "focus", function (e) { return onFocus(cm, e); });
8023
+ on(inp, "blur", function (e) { return onBlur(cm, e); });
 
8024
  }
8025
 
8026
+ var initHooks = [];
8027
+ CodeMirror.defineInitHook = function (f) { return initHooks.push(f); };
8028
+
8029
+ // Indent the given line. The how parameter can be "smart",
8030
+ // "add"/null, "subtract", or "prev". When aggressive is false
8031
+ // (typically set to true for forced single-line indents), empty
8032
+ // lines are not indented, and places where the mode returns Pass
8033
+ // are left alone.
8034
+ function indentLine(cm, n, how, aggressive) {
8035
+ var doc = cm.doc, state;
8036
+ if (how == null) { how = "add"; }
8037
+ if (how == "smart") {
8038
+ // Fall back to "prev" when the mode doesn't have an indentation
8039
+ // method.
8040
+ if (!doc.mode.indent) { how = "prev"; }
8041
+ else { state = getContextBefore(cm, n).state; }
8042
  }
 
8043
 
8044
+ var tabSize = cm.options.tabSize;
8045
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
8046
+ if (line.stateAfter) { line.stateAfter = null; }
8047
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation;
8048
+ if (!aggressive && !/\S/.test(line.text)) {
8049
+ indentation = 0;
8050
+ how = "not";
8051
+ } else if (how == "smart") {
8052
+ indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
8053
+ if (indentation == Pass || indentation > 150) {
8054
+ if (!aggressive) { return }
8055
+ how = "prev";
8056
+ }
8057
  }
8058
+ if (how == "prev") {
8059
+ if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); }
8060
+ else { indentation = 0; }
8061
+ } else if (how == "add") {
8062
+ indentation = curSpace + cm.options.indentUnit;
8063
+ } else if (how == "subtract") {
8064
+ indentation = curSpace - cm.options.indentUnit;
8065
+ } else if (typeof how == "number") {
8066
+ indentation = curSpace + how;
8067
+ }
8068
+ indentation = Math.max(0, indentation);
8069
 
8070
+ var indentString = "", pos = 0;
8071
+ if (cm.options.indentWithTabs)
8072
+ { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} }
8073
+ if (pos < indentation) { indentString += spaceStr(indentation - pos); }
 
 
 
8074
 
8075
+ if (indentString != curSpaceString) {
8076
+ replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
8077
+ line.stateAfter = null;
8078
+ return true
 
 
 
 
 
 
 
 
 
 
 
8079
  } else {
8080
+ // Ensure that, if the cursor was in the whitespace at the start
8081
+ // of the line, it is moved to the end of that space.
8082
+ for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {
8083
+ var range = doc.sel.ranges[i$1];
8084
+ if (range.head.line == n && range.head.ch < curSpaceString.length) {
8085
+ var pos$1 = Pos(n, curSpaceString.length);
8086
+ replaceOneSelection(doc, i$1, new Range(pos$1, pos$1));
8087
+ break
8088
+ }
 
8089
  }
8090
  }
 
 
 
 
 
 
 
8091
  }
8092
 
8093
+ // This will be set to a {lineWise: bool, text: [string]} object, so
8094
+ // that, when pasting, we know what kind of selections the copied
8095
+ // text was made out of.
8096
+ var lastCopied = null;
8097
+
8098
+ function setLastCopied(newLastCopied) {
8099
+ lastCopied = newLastCopied;
8100
  }
8101
 
8102
+ function applyTextInput(cm, inserted, deleted, sel, origin) {
8103
+ var doc = cm.doc;
8104
+ cm.display.shift = false;
8105
+ if (!sel) { sel = doc.sel; }
8106
+
8107
+ var recent = +new Date - 200;
8108
+ var paste = origin == "paste" || cm.state.pasteIncoming > recent;
8109
+ var textLines = splitLinesAuto(inserted), multiPaste = null;
8110
+ // When pasting N lines into N selections, insert one line per selection
8111
+ if (paste && sel.ranges.length > 1) {
8112
+ if (lastCopied && lastCopied.text.join("\n") == inserted) {
8113
+ if (sel.ranges.length % lastCopied.text.length == 0) {
8114
+ multiPaste = [];
8115
+ for (var i = 0; i < lastCopied.text.length; i++)
8116
+ { multiPaste.push(doc.splitLines(lastCopied.text[i])); }
8117
+ }
8118
+ } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) {
8119
+ multiPaste = map(textLines, function (l) { return [l]; });
8120
+ }
8121
+ }
8122
 
8123
+ var updateInput = cm.curOp.updateInput;
8124
+ // Normal behavior is to insert the new text into every selection
8125
+ for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
8126
+ var range = sel.ranges[i$1];
8127
+ var from = range.from(), to = range.to();
8128
+ if (range.empty()) {
8129
+ if (deleted && deleted > 0) // Handle deletion
8130
+ { from = Pos(from.line, from.ch - deleted); }
8131
+ else if (cm.state.overwrite && !paste) // Handle overwrite
8132
+ { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); }
8133
+ else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n"))
8134
+ { from = to = Pos(from.line, 0); }
8135
+ }
8136
+ var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
8137
+ origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")};
8138
+ makeChange(cm.doc, changeEvent);
8139
+ signalLater(cm, "inputRead", cm, changeEvent);
8140
+ }
8141
+ if (inserted && !paste)
8142
+ { triggerElectric(cm, inserted); }
8143
 
8144
+ ensureCursorVisible(cm);
8145
+ if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; }
8146
+ cm.curOp.typing = true;
8147
+ cm.state.pasteIncoming = cm.state.cutIncoming = -1;
 
8148
  }
8149
 
8150
+ function handlePaste(e, cm) {
8151
+ var pasted = e.clipboardData && e.clipboardData.getData("Text");
8152
+ if (pasted) {
8153
+ e.preventDefault();
8154
+ if (!cm.isReadOnly() && !cm.options.disableInput)
8155
+ { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); }
8156
+ return true
8157
+ }
8158
  }
8159
 
8160
+ function triggerElectric(cm, inserted) {
8161
+ // When an 'electric' character is inserted, immediately trigger a reindent
8162
+ if (!cm.options.electricChars || !cm.options.smartIndent) { return }
8163
+ var sel = cm.doc.sel;
8164
+
8165
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
8166
+ var range = sel.ranges[i];
8167
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue }
8168
+ var mode = cm.getModeAt(range.head);
8169
+ var indented = false;
8170
+ if (mode.electricChars) {
8171
+ for (var j = 0; j < mode.electricChars.length; j++)
8172
+ { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
8173
+ indented = indentLine(cm, range.head.line, "smart");
8174
+ break
8175
+ } }
8176
+ } else if (mode.electricInput) {
8177
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
8178
+ { indented = indentLine(cm, range.head.line, "smart"); }
8179
+ }
8180
+ if (indented) { signalLater(cm, "electricInput", cm, range.head.line); }
8181
+ }
8182
  }
8183
 
8184
+ function copyableRanges(cm) {
8185
+ var text = [], ranges = [];
8186
+ for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
8187
+ var line = cm.doc.sel.ranges[i].head.line;
8188
+ var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
8189
+ ranges.push(lineRange);
8190
+ text.push(cm.getRange(lineRange.anchor, lineRange.head));
8191
  }
8192
+ return {text: text, ranges: ranges}
8193
  }
8194
 
8195
+ function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) {
8196
+ field.setAttribute("autocorrect", autocorrect ? "" : "off");
8197
+ field.setAttribute("autocapitalize", autocapitalize ? "" : "off");
8198
+ field.setAttribute("spellcheck", !!spellcheck);
 
 
 
8199
  }
8200
 
8201
+ function hiddenTextarea() {
8202
+ var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none");
8203
+ var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
8204
+ // The textarea is kept positioned near the cursor to prevent the
8205
+ // fact that it'll be scrolled into view on input from scrolling
8206
+ // our fake cursor out of view. On webkit, when wrap=off, paste is
8207
+ // very slow. So make the area wide instead.
8208
+ if (webkit) { te.style.width = "1000px"; }
8209
+ else { te.setAttribute("wrap", "off"); }
8210
+ // If border: 0; -- iOS fails to open keyboard (issue #1287)
8211
+ if (ios) { te.style.border = "1px solid black"; }
8212
+ disableBrowserMagic(te);
8213
+ return div
8214
+ }
8215
+
8216
+ // The publicly visible API. Note that methodOp(f) means
8217
+ // 'wrap f in an operation, performed on its `this` parameter'.
8218
+
8219
+ // This is not the complete set of editor methods. Most of the
8220
+ // methods defined on the Doc type are also injected into
8221
+ // CodeMirror.prototype, for backwards compatibility and
8222
+ // convenience.
8223
+
8224
+ function addEditorMethods(CodeMirror) {
8225
+ var optionHandlers = CodeMirror.optionHandlers;
8226
+
8227
+ var helpers = CodeMirror.helpers = {};
8228
+
8229
+ CodeMirror.prototype = {
8230
+ constructor: CodeMirror,
8231
+ focus: function(){window.focus(); this.display.input.focus();},
8232
+
8233
+ setOption: function(option, value) {
8234
+ var options = this.options, old = options[option];
8235
+ if (options[option] == value && option != "mode") { return }
8236
+ options[option] = value;
8237
+ if (optionHandlers.hasOwnProperty(option))
8238
+ { operation(this, optionHandlers[option])(this, value, old); }
8239
+ signal(this, "optionChange", this, option);
8240
+ },
8241
+
8242
+ getOption: function(option) {return this.options[option]},
8243
+ getDoc: function() {return this.doc},
8244
+
8245
+ addKeyMap: function(map, bottom) {
8246
+ this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
8247
+ },
8248
+ removeKeyMap: function(map) {
8249
+ var maps = this.state.keyMaps;
8250
+ for (var i = 0; i < maps.length; ++i)
8251
+ { if (maps[i] == map || maps[i].name == map) {
8252
+ maps.splice(i, 1);
8253
+ return true
8254
+ } }
8255
+ },
8256
+
8257
+ addOverlay: methodOp(function(spec, options) {
8258
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
8259
+ if (mode.startState) { throw new Error("Overlays may not be stateful.") }
8260
+ insertSorted(this.state.overlays,
8261
+ {mode: mode, modeSpec: spec, opaque: options && options.opaque,
8262
+ priority: (options && options.priority) || 0},
8263
+ function (overlay) { return overlay.priority; });
8264
+ this.state.modeGen++;
8265
+ regChange(this);
8266
+ }),
8267
+ removeOverlay: methodOp(function(spec) {
8268
+ var overlays = this.state.overlays;
8269
+ for (var i = 0; i < overlays.length; ++i) {
8270
+ var cur = overlays[i].modeSpec;
8271
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
8272
+ overlays.splice(i, 1);
8273
+ this.state.modeGen++;
8274
+ regChange(this);
8275
+ return
8276
  }
8277
  }
8278
+ }),
 
 
 
8279
 
8280
+ indentLine: methodOp(function(n, dir, aggressive) {
8281
+ if (typeof dir != "string" && typeof dir != "number") {
8282
+ if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; }
8283
+ else { dir = dir ? "add" : "subtract"; }
8284
+ }
8285
+ if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); }
8286
+ }),
8287
+ indentSelection: methodOp(function(how) {
8288
+ var ranges = this.doc.sel.ranges, end = -1;
8289
+ for (var i = 0; i < ranges.length; i++) {
8290
+ var range = ranges[i];
8291
+ if (!range.empty()) {
8292
+ var from = range.from(), to = range.to();
8293
+ var start = Math.max(end, from.line);
8294
+ end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
8295
+ for (var j = start; j < end; ++j)
8296
+ { indentLine(this, j, how); }
8297
+ var newRanges = this.doc.sel.ranges;
8298
+ if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
8299
+ { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); }
8300
+ } else if (range.head.line > end) {
8301
+ indentLine(this, range.head.line, how, true);
8302
+ end = range.head.line;
8303
+ if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); }
8304
+ }
8305
+ }
8306
+ }),
8307
+
8308
+ // Fetch the parser token for a given character. Useful for hacks
8309
+ // that want to inspect the mode state (say, for completion).
8310
+ getTokenAt: function(pos, precise) {
8311
+ return takeToken(this, pos, precise)
8312
+ },
8313
+
8314
+ getLineTokens: function(line, precise) {
8315
+ return takeToken(this, Pos(line), precise, true)
8316
+ },
8317
+
8318
+ getTokenTypeAt: function(pos) {
8319
+ pos = clipPos(this.doc, pos);
8320
+ var styles = getLineStyles(this, getLine(this.doc, pos.line));
8321
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
8322
+ var type;
8323
+ if (ch == 0) { type = styles[2]; }
8324
+ else { for (;;) {
8325
+ var mid = (before + after) >> 1;
8326
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; }
8327
+ else if (styles[mid * 2 + 1] < ch) { before = mid + 1; }
8328
+ else { type = styles[mid * 2 + 2]; break }
8329
+ } }
8330
+ var cut = type ? type.indexOf("overlay ") : -1;
8331
+ return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)
8332
+ },
8333
+
8334
+ getModeAt: function(pos) {
8335
+ var mode = this.doc.mode;
8336
+ if (!mode.innerMode) { return mode }
8337
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode
8338
+ },
8339
+
8340
+ getHelper: function(pos, type) {
8341
+ return this.getHelpers(pos, type)[0]
8342
+ },
8343
+
8344
+ getHelpers: function(pos, type) {
8345
+ var found = [];
8346
+ if (!helpers.hasOwnProperty(type)) { return found }
8347
+ var help = helpers[type], mode = this.getModeAt(pos);
8348
+ if (typeof mode[type] == "string") {
8349
+ if (help[mode[type]]) { found.push(help[mode[type]]); }
8350
+ } else if (mode[type]) {
8351
+ for (var i = 0; i < mode[type].length; i++) {
8352
+ var val = help[mode[type][i]];
8353
+ if (val) { found.push(val); }
8354
+ }
8355
+ } else if (mode.helperType && help[mode.helperType]) {
8356
+ found.push(help[mode.helperType]);
8357
+ } else if (help[mode.name]) {
8358
+ found.push(help[mode.name]);
8359
+ }
8360
+ for (var i$1 = 0; i$1 < help._global.length; i$1++) {
8361
+ var cur = help._global[i$1];
8362
+ if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
8363
+ { found.push(cur.val); }
8364
+ }
8365
+ return found
8366
+ },
8367
+
8368
+ getStateAfter: function(line, precise) {
8369
+ var doc = this.doc;
8370
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
8371
+ return getContextBefore(this, line + 1, precise).state
8372
+ },
8373
+
8374
+ cursorCoords: function(start, mode) {
8375
+ var pos, range = this.doc.sel.primary();
8376
+ if (start == null) { pos = range.head; }
8377
+ else if (typeof start == "object") { pos = clipPos(this.doc, start); }
8378
+ else { pos = start ? range.from() : range.to(); }
8379
+ return cursorCoords(this, pos, mode || "page")
8380
+ },
8381
+
8382
+ charCoords: function(pos, mode) {
8383
+ return charCoords(this, clipPos(this.doc, pos), mode || "page")
8384
+ },
8385
+
8386
+ coordsChar: function(coords, mode) {
8387
+ coords = fromCoordSystem(this, coords, mode || "page");
8388
+ return coordsChar(this, coords.left, coords.top)
8389
+ },
8390
+
8391
+ lineAtHeight: function(height, mode) {
8392
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
8393
+ return lineAtHeight(this.doc, height + this.display.viewOffset)
8394
+ },
8395
+ heightAtLine: function(line, mode, includeWidgets) {
8396
+ var end = false, lineObj;
8397
+ if (typeof line == "number") {
8398
+ var last = this.doc.first + this.doc.size - 1;
8399
+ if (line < this.doc.first) { line = this.doc.first; }
8400
+ else if (line > last) { line = last; end = true; }
8401
+ lineObj = getLine(this.doc, line);
8402
+ } else {
8403
+ lineObj = line;
8404
+ }
8405
+ return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top +
8406
+ (end ? this.doc.height - heightAtLine(lineObj) : 0)
8407
+ },
8408
+
8409
+ defaultTextHeight: function() { return textHeight(this.display) },
8410
+ defaultCharWidth: function() { return charWidth(this.display) },
8411
+
8412
+ getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},
8413
+
8414
+ addWidget: function(pos, node, scroll, vert, horiz) {
8415
+ var display = this.display;
8416
+ pos = cursorCoords(this, clipPos(this.doc, pos));
8417
+ var top = pos.bottom, left = pos.left;
8418
+ node.style.position = "absolute";
8419
+ node.setAttribute("cm-ignore-events", "true");
8420
+ this.display.input.setUneditable(node);
8421
+ display.sizer.appendChild(node);
8422
+ if (vert == "over") {
8423
+ top = pos.top;
8424
+ } else if (vert == "above" || vert == "near") {
8425
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
8426
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
8427
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
8428
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
8429
+ { top = pos.top - node.offsetHeight; }
8430
+ else if (pos.bottom + node.offsetHeight <= vspace)
8431
+ { top = pos.bottom; }
8432
+ if (left + node.offsetWidth > hspace)
8433
+ { left = hspace - node.offsetWidth; }
8434
+ }
8435
+ node.style.top = top + "px";
8436
+ node.style.left = node.style.right = "";
8437
+ if (horiz == "right") {
8438
+ left = display.sizer.clientWidth - node.offsetWidth;
8439
+ node.style.right = "0px";
8440
+ } else {
8441
+ if (horiz == "left") { left = 0; }
8442
+ else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; }
8443
+ node.style.left = left + "px";
8444
+ }
8445
+ if (scroll)
8446
+ { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); }
8447
+ },
8448
+
8449
+ triggerOnKeyDown: methodOp(onKeyDown),
8450
+ triggerOnKeyPress: methodOp(onKeyPress),
8451
+ triggerOnKeyUp: onKeyUp,
8452
+ triggerOnMouseDown: methodOp(onMouseDown),
8453
+
8454
+ execCommand: function(cmd) {
8455
+ if (commands.hasOwnProperty(cmd))
8456
+ { return commands[cmd].call(null, this) }
8457
+ },
8458
+
8459
+ triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
8460
+
8461
+ findPosH: function(from, amount, unit, visually) {
8462
+ var dir = 1;
8463
+ if (amount < 0) { dir = -1; amount = -amount; }
8464
+ var cur = clipPos(this.doc, from);
8465
+ for (var i = 0; i < amount; ++i) {
8466
+ cur = findPosH(this.doc, cur, dir, unit, visually);
8467
+ if (cur.hitSide) { break }
8468
+ }
8469
+ return cur
8470
+ },
8471
 
8472
+ moveH: methodOp(function(dir, unit) {
8473
+ var this$1 = this;
8474
+
8475
+ this.extendSelectionsBy(function (range) {
8476
+ if (this$1.display.shift || this$1.doc.extend || range.empty())
8477
+ { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) }
8478
+ else
8479
+ { return dir < 0 ? range.from() : range.to() }
8480
+ }, sel_move);
8481
+ }),
8482
+
8483
+ deleteH: methodOp(function(dir, unit) {
8484
+ var sel = this.doc.sel, doc = this.doc;
8485
+ if (sel.somethingSelected())
8486
+ { doc.replaceSelection("", null, "+delete"); }
8487
+ else
8488
+ { deleteNearSelection(this, function (range) {
8489
+ var other = findPosH(doc, range.head, dir, unit, false);
8490
+ return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}
8491
+ }); }
8492
+ }),
8493
+
8494
+ findPosV: function(from, amount, unit, goalColumn) {
8495
+ var dir = 1, x = goalColumn;
8496
+ if (amount < 0) { dir = -1; amount = -amount; }
8497
+ var cur = clipPos(this.doc, from);
8498
+ for (var i = 0; i < amount; ++i) {
8499
+ var coords = cursorCoords(this, cur, "div");
8500
+ if (x == null) { x = coords.left; }
8501
+ else { coords.left = x; }
8502
+ cur = findPosV(this, coords, dir, unit);
8503
+ if (cur.hitSide) { break }
8504
+ }
8505
+ return cur
8506
+ },
8507
+
8508
+ moveV: methodOp(function(dir, unit) {
8509
+ var this$1 = this;
8510
+
8511
+ var doc = this.doc, goals = [];
8512
+ var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected();
8513
+ doc.extendSelectionsBy(function (range) {
8514
+ if (collapse)
8515
+ { return dir < 0 ? range.from() : range.to() }
8516
+ var headPos = cursorCoords(this$1, range.head, "div");
8517
+ if (range.goalColumn != null) { headPos.left = range.goalColumn; }
8518
+ goals.push(headPos.left);
8519
+ var pos = findPosV(this$1, headPos, dir, unit);
8520
+ if (unit == "page" && range == doc.sel.primary())
8521
+ { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); }
8522
+ return pos
8523
+ }, sel_move);
8524
+ if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
8525
+ { doc.sel.ranges[i].goalColumn = goals[i]; } }
8526
+ }),
8527
+
8528
+ // Find the word at the given position (as returned by coordsChar).
8529
+ findWordAt: function(pos) {
8530
+ var doc = this.doc, line = getLine(doc, pos.line).text;
8531
+ var start = pos.ch, end = pos.ch;
8532
+ if (line) {
8533
+ var helper = this.getHelper(pos, "wordChars");
8534
+ if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; }
8535
+ var startChar = line.charAt(start);
8536
+ var check = isWordChar(startChar, helper)
8537
+ ? function (ch) { return isWordChar(ch, helper); }
8538
+ : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); }
8539
+ : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); };
8540
+ while (start > 0 && check(line.charAt(start - 1))) { --start; }
8541
+ while (end < line.length && check(line.charAt(end))) { ++end; }
8542
+ }
8543
+ return new Range(Pos(pos.line, start), Pos(pos.line, end))
8544
+ },
8545
+
8546
+ toggleOverwrite: function(value) {
8547
+ if (value != null && value == this.state.overwrite) { return }
8548
+ if (this.state.overwrite = !this.state.overwrite)
8549
+ { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); }
8550
+ else
8551
+ { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); }
8552
+
8553
+ signal(this, "overwriteToggle", this, this.state.overwrite);
8554
+ },
8555
+ hasFocus: function() { return this.display.input.getField() == activeElt() },
8556
+ isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
8557
+
8558
+ scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }),
8559
+ getScrollInfo: function() {
8560
+ var scroller = this.display.scroller;
8561
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
8562
+ height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
8563
+ width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
8564
+ clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
8565
+ },
8566
+
8567
+ scrollIntoView: methodOp(function(range, margin) {
8568
+ if (range == null) {
8569
+ range = {from: this.doc.sel.primary().head, to: null};
8570
+ if (margin == null) { margin = this.options.cursorScrollMargin; }
8571
+ } else if (typeof range == "number") {
8572
+ range = {from: Pos(range, 0), to: null};
8573
+ } else if (range.from == null) {
8574
+ range = {from: range, to: null};
8575
+ }
8576
+ if (!range.to) { range.to = range.from; }
8577
+ range.margin = margin || 0;
8578
+
8579
+ if (range.from.line != null) {
8580
+ scrollToRange(this, range);
8581
+ } else {
8582
+ scrollToCoordsRange(this, range.from, range.to, range.margin);
8583
+ }
8584
+ }),
8585
+
8586
+ setSize: methodOp(function(width, height) {
8587
+ var this$1 = this;
8588
+
8589
+ var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; };
8590
+ if (width != null) { this.display.wrapper.style.width = interpret(width); }
8591
+ if (height != null) { this.display.wrapper.style.height = interpret(height); }
8592
+ if (this.options.lineWrapping) { clearLineMeasurementCache(this); }
8593
+ var lineNo = this.display.viewFrom;
8594
+ this.doc.iter(lineNo, this.display.viewTo, function (line) {
8595
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
8596
+ { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } }
8597
+ ++lineNo;
8598
+ });
8599
+ this.curOp.forceUpdate = true;
8600
+ signal(this, "refresh", this);
8601
+ }),
8602
+
8603
+ operation: function(f){return runInOp(this, f)},
8604
+ startOperation: function(){return startOperation(this)},
8605
+ endOperation: function(){return endOperation(this)},
8606
+
8607
+ refresh: methodOp(function() {
8608
+ var oldHeight = this.display.cachedTextHeight;
8609
+ regChange(this);
8610
+ this.curOp.forceUpdate = true;
8611
+ clearCaches(this);
8612
+ scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop);
8613
+ updateGutterSpace(this.display);
8614
+ if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping)
8615
+ { estimateLineHeights(this); }
8616
+ signal(this, "refresh", this);
8617
+ }),
8618
+
8619
+ swapDoc: methodOp(function(doc) {
8620
+ var old = this.doc;
8621
+ old.cm = null;
8622
+ // Cancel the current text selection if any (#5821)
8623
+ if (this.state.selectingText) { this.state.selectingText(); }
8624
+ attachDoc(this, doc);
8625
+ clearCaches(this);
8626
+ this.display.input.reset();
8627
+ scrollToCoords(this, doc.scrollLeft, doc.scrollTop);
8628
+ this.curOp.forceScroll = true;
8629
+ signalLater(this, "swapDoc", this, old);
8630
+ return old
8631
+ }),
8632
+
8633
+ phrase: function(phraseText) {
8634
+ var phrases = this.options.phrases;
8635
+ return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText
8636
+ },
8637
+
8638
+ getInputField: function(){return this.display.input.getField()},
8639
+ getWrapperElement: function(){return this.display.wrapper},
8640
+ getScrollerElement: function(){return this.display.scroller},
8641
+ getGutterElement: function(){return this.display.gutters}
8642
+ };
8643
+ eventMixin(CodeMirror);
8644
+
8645
+ CodeMirror.registerHelper = function(type, name, value) {
8646
+ if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; }
8647
+ helpers[type][name] = value;
8648
+ };
8649
+ CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
8650
+ CodeMirror.registerHelper(type, name, value);
8651
+ helpers[type]._global.push({pred: predicate, val: value});
8652
+ };
8653
  }
8654
 
8655
+ // Used for horizontal relative motion. Dir is -1 or 1 (left or
8656
+ // right), unit can be "codepoint", "char", "column" (like char, but
8657
+ // doesn't cross line boundaries), "word" (across next word), or
8658
+ // "group" (to the start of next group of word or
8659
+ // non-word-non-whitespace chars). The visually param controls
8660
+ // whether, in right-to-left text, direction 1 means to move towards
8661
+ // the next index in the string, or towards the character to the right
8662
+ // of the current position. The resulting position will have a
8663
+ // hitSide=true property if it reached the end of the document.
8664
+ function findPosH(doc, pos, dir, unit, visually) {
8665
+ var oldPos = pos;
8666
+ var origDir = dir;
8667
+ var lineObj = getLine(doc, pos.line);
8668
+ var lineDir = visually && doc.direction == "rtl" ? -dir : dir;
8669
+ function findNextLine() {
8670
+ var l = pos.line + lineDir;
8671
+ if (l < doc.first || l >= doc.first + doc.size) { return false }
8672
+ pos = new Pos(l, pos.ch, pos.sticky);
8673
+ return lineObj = getLine(doc, l)
8674
+ }
8675
+ function moveOnce(boundToLine) {
8676
+ var next;
8677
+ if (unit == "codepoint") {
8678
+ var ch = lineObj.text.charCodeAt(pos.ch + (dir > 0 ? 0 : -1));
8679
+ if (isNaN(ch)) {
8680
+ next = null;
8681
+ } else {
8682
+ var astral = dir > 0 ? ch >= 0xD800 && ch < 0xDC00 : ch >= 0xDC00 && ch < 0xDFFF;
8683
+ next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (astral ? 2 : 1))), -dir);
8684
  }
8685
+ } else if (visually) {
8686
+ next = moveVisually(doc.cm, lineObj, pos, dir);
8687
+ } else {
8688
+ next = moveLogically(lineObj, pos, dir);
8689
  }
8690
+ if (next == null) {
8691
+ if (!boundToLine && findNextLine())
8692
+ { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); }
8693
+ else
8694
+ { return false }
8695
+ } else {
8696
+ pos = next;
 
 
8697
  }
8698
+ return true
8699
+ }
8700
+
8701
+ if (unit == "char" || unit == "codepoint") {
8702
+ moveOnce();
8703
+ } else if (unit == "column") {
8704
+ moveOnce(true);
8705
+ } else if (unit == "word" || unit == "group") {
8706
+ var sawType = null, group = unit == "group";
8707
+ var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
8708
+ for (var first = true;; first = false) {
8709
+ if (dir < 0 && !moveOnce(!first)) { break }
8710
+ var cur = lineObj.text.charAt(pos.ch) || "\n";
8711
+ var type = isWordChar(cur, helper) ? "w"
8712
+ : group && cur == "\n" ? "n"
8713
+ : !group || /\s/.test(cur) ? null
8714
+ : "p";
8715
+ if (group && !first && !type) { type = "s"; }
8716
+ if (sawType && sawType != type) {
8717
+ if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";}
8718
+ break
8719
+ }
8720
+
8721
+ if (type) { sawType = type; }
8722
+ if (dir > 0 && !moveOnce(!first)) { break }
8723
  }
8724
  }
8725
+ var result = skipAtomic(doc, pos, oldPos, origDir, true);
8726
+ if (equalCursorPos(oldPos, result)) { result.hitSide = true; }
8727
+ return result
8728
  }
8729
 
8730
+ // For relative vertical movement. Dir may be -1 or 1. Unit can be
8731
+ // "page" or "line". The resulting position will have a hitSide=true
8732
+ // property if it reached the end of the document.
8733
+ function findPosV(cm, pos, dir, unit) {
8734
+ var doc = cm.doc, x = pos.left, y;
8735
+ if (unit == "page") {
8736
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
8737
+ var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3);
8738
+ y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount;
8739
 
8740
+ } else if (unit == "line") {
8741
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
8742
+ }
8743
+ var target;
8744
+ for (;;) {
8745
+ target = coordsChar(cm, x, y);
8746
+ if (!target.outside) { break }
8747
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }
8748
+ y += dir * 5;
8749
+ }
8750
+ return target
8751
+ }
8752
 
8753
+ // CONTENTEDITABLE INPUT STYLE
 
8754
 
8755
+ var ContentEditableInput = function(cm) {
8756
+ this.cm = cm;
8757
+ this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
8758
+ this.polling = new Delayed();
8759
+ this.composing = null;
8760
+ this.gracePeriod = false;
8761
+ this.readDOMTimeout = null;
8762
  };
 
 
 
 
8763
 
8764
+ ContentEditableInput.prototype.init = function (display) {
8765
+ var this$1 = this;
8766
+
8767
+ var input = this, cm = input.cm;
8768
+ var div = input.div = display.lineDiv;
8769
+ disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize);
8770
+
8771
+ function belongsToInput(e) {
8772
+ for (var t = e.target; t; t = t.parentNode) {
8773
+ if (t == div) { return true }
8774
+ if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break }
8775
+ }
8776
+ return false
8777
  }
 
 
 
8778
 
8779
+ on(div, "paste", function (e) {
8780
+ if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
8781
+ // IE doesn't fire input events, so we schedule a read for the pasted content in this way
8782
+ if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); }
8783
+ });
8784
 
8785
+ on(div, "compositionstart", function (e) {
8786
+ this$1.composing = {data: e.data, done: false};
8787
+ });
8788
+ on(div, "compositionupdate", function (e) {
8789
+ if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; }
8790
+ });
8791
+ on(div, "compositionend", function (e) {
8792
+ if (this$1.composing) {
8793
+ if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); }
8794
+ this$1.composing.done = true;
8795
+ }
8796
+ });
8797
 
8798
+ on(div, "touchstart", function () { return input.forceCompositionEnd(); });
8799
+
8800
+ on(div, "input", function () {
8801
+ if (!this$1.composing) { this$1.readFromDOMSoon(); }
8802
+ });
8803
+
8804
+ function onCopyCut(e) {
8805
+ if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return }
8806
+ if (cm.somethingSelected()) {
8807
+ setLastCopied({lineWise: false, text: cm.getSelections()});
8808
+ if (e.type == "cut") { cm.replaceSelection("", null, "cut"); }
8809
+ } else if (!cm.options.lineWiseCopyCut) {
8810
+ return
8811
+ } else {
8812
+ var ranges = copyableRanges(cm);
8813
+ setLastCopied({lineWise: true, text: ranges.text});
8814
+ if (e.type == "cut") {
8815
+ cm.operation(function () {
8816
+ cm.setSelections(ranges.ranges, 0, sel_dontScroll);
8817
+ cm.replaceSelection("", null, "cut");
8818
+ });
8819
+ }
8820
+ }
8821
+ if (e.clipboardData) {
8822
+ e.clipboardData.clearData();
8823
+ var content = lastCopied.text.join("\n");
8824
+ // iOS exposes the clipboard API, but seems to discard content inserted into it
8825
+ e.clipboardData.setData("Text", content);
8826
+ if (e.clipboardData.getData("Text") == content) {
8827
+ e.preventDefault();
8828
+ return
8829
+ }
8830
+ }
8831
+ // Old-fashioned briefly-focus-a-textarea hack
8832
+ var kludge = hiddenTextarea(), te = kludge.firstChild;
8833
+ cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
8834
+ te.value = lastCopied.text.join("\n");
8835
+ var hadFocus = document.activeElement;
8836
+ selectInput(te);
8837
+ setTimeout(function () {
8838
+ cm.display.lineSpace.removeChild(kludge);
8839
+ hadFocus.focus();
8840
+ if (hadFocus == div) { input.showPrimarySelection(); }
8841
+ }, 50);
8842
+ }
8843
+ on(div, "copy", onCopyCut);
8844
+ on(div, "cut", onCopyCut);
8845
  };
8846
 
8847
+ ContentEditableInput.prototype.screenReaderLabelChanged = function (label) {
8848
+ // Label for screenreaders, accessibility
8849
+ if(label) {
8850
+ this.div.setAttribute('aria-label', label);
8851
+ } else {
8852
+ this.div.removeAttribute('aria-label');
 
 
 
 
8853
  }
8854
  };
8855
 
8856
+ ContentEditableInput.prototype.prepareSelection = function () {
8857
+ var result = prepareSelection(this.cm, false);
8858
+ result.focus = document.activeElement == this.div;
8859
+ return result
 
8860
  };
8861
 
8862
+ ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
8863
+ if (!info || !this.cm.display.view.length) { return }
8864
+ if (info.focus || takeFocus) { this.showPrimarySelection(); }
8865
+ this.showMultipleSelections(info);
8866
+ };
8867
 
8868
+ ContentEditableInput.prototype.getSelection = function () {
8869
+ return this.cm.display.wrapper.ownerDocument.getSelection()
8870
+ };
8871
+
8872
+ ContentEditableInput.prototype.showPrimarySelection = function () {
8873
+ var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary();
8874
+ var from = prim.from(), to = prim.to();
8875
+
8876
+ if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) {
8877
+ sel.removeAllRanges();
8878
+ return
 
 
 
 
 
 
 
8879
  }
 
 
 
 
8880
 
8881
+ var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
8882
+ var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset);
8883
+ if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
8884
+ cmp(minPos(curAnchor, curFocus), from) == 0 &&
8885
+ cmp(maxPos(curAnchor, curFocus), to) == 0)
8886
+ { return }
8887
 
8888
+ var view = cm.display.view;
8889
+ var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) ||
8890
+ {node: view[0].measure.map[2], offset: 0};
8891
+ var end = to.line < cm.display.viewTo && posToDOM(cm, to);
8892
+ if (!end) {
8893
+ var measure = view[view.length - 1].measure;
8894
+ var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
8895
+ end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
8896
+ }
8897
+
8898
+ if (!start || !end) {
8899
+ sel.removeAllRanges();
8900
+ return
8901
+ }
8902
+
8903
+ var old = sel.rangeCount && sel.getRangeAt(0), rng;
8904
+ try { rng = range(start.node, start.offset, end.offset, end.node); }
8905
+ catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
8906
+ if (rng) {
8907
+ if (!gecko && cm.state.focused) {
8908
+ sel.collapse(start.node, start.offset);
8909
+ if (!rng.collapsed) {
8910
+ sel.removeAllRanges();
8911
+ sel.addRange(rng);
8912
+ }
8913
+ } else {
8914
+ sel.removeAllRanges();
8915
+ sel.addRange(rng);
8916
+ }
8917
+ if (old && sel.anchorNode == null) { sel.addRange(old); }
8918
+ else if (gecko) { this.startGracePeriod(); }
8919
+ }
8920
+ this.rememberSelection();
8921
+ };
8922
 
8923
+ ContentEditableInput.prototype.startGracePeriod = function () {
8924
+ var this$1 = this;
8925
+
8926
+ clearTimeout(this.gracePeriod);
8927
+ this.gracePeriod = setTimeout(function () {
8928
+ this$1.gracePeriod = false;
8929
+ if (this$1.selectionChanged())
8930
+ { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); }
8931
+ }, 20);
8932
+ };
8933
+
8934
+ ContentEditableInput.prototype.showMultipleSelections = function (info) {
8935
+ removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
8936
+ removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
8937
+ };
8938
+
8939
+ ContentEditableInput.prototype.rememberSelection = function () {
8940
+ var sel = this.getSelection();
8941
+ this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
8942
+ this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
8943
+ };
8944
 
8945
+ ContentEditableInput.prototype.selectionInEditor = function () {
8946
+ var sel = this.getSelection();
8947
+ if (!sel.rangeCount) { return false }
8948
+ var node = sel.getRangeAt(0).commonAncestorContainer;
8949
+ return contains(this.div, node)
8950
+ };
8951
 
8952
+ ContentEditableInput.prototype.focus = function () {
8953
+ if (this.cm.options.readOnly != "nocursor") {
8954
+ if (!this.selectionInEditor() || document.activeElement != this.div)
8955
+ { this.showSelection(this.prepareSelection(), true); }
8956
+ this.div.focus();
8957
+ }
8958
+ };
8959
+ ContentEditableInput.prototype.blur = function () { this.div.blur(); };
8960
+ ContentEditableInput.prototype.getField = function () { return this.div };
8961
 
8962
+ ContentEditableInput.prototype.supportsTouch = function () { return true };
8963
 
8964
+ ContentEditableInput.prototype.receivedFocus = function () {
8965
+ var input = this;
8966
+ if (this.selectionInEditor())
8967
+ { this.pollSelection(); }
8968
+ else
8969
+ { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }
8970
 
8971
+ function poll() {
8972
+ if (input.cm.state.focused) {
8973
+ input.pollSelection();
8974
+ input.polling.set(input.cm.options.pollInterval, poll);
8975
+ }
8976
+ }
8977
+ this.polling.set(this.cm.options.pollInterval, poll);
8978
+ };
8979
 
8980
+ ContentEditableInput.prototype.selectionChanged = function () {
8981
+ var sel = this.getSelection();
8982
+ return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
8983
+ sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
8984
+ };
8985
 
8986
+ ContentEditableInput.prototype.pollSelection = function () {
8987
+ if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return }
8988
+ var sel = this.getSelection(), cm = this.cm;
8989
+ // On Android Chrome (version 56, at least), backspacing into an
8990
+ // uneditable block element will put the cursor in that element,
8991
+ // and then, because it's not editable, hide the virtual keyboard.
8992
+ // Because Android doesn't allow us to actually detect backspace
8993
+ // presses in a sane way, this code checks for when that happens
8994
+ // and simulates a backspace press in this case.
8995
+ if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) {
8996
+ this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs});
8997
+ this.blur();
8998
+ this.focus();
8999
+ return
9000
+ }
9001
+ if (this.composing) { return }
9002
+ this.rememberSelection();
9003
+ var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
9004
+ var head = domToPos(cm, sel.focusNode, sel.focusOffset);
9005
+ if (anchor && head) { runInOp(cm, function () {
9006
+ setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
9007
+ if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; }
9008
+ }); }
9009
  };
9010
 
9011
+ ContentEditableInput.prototype.pollContent = function () {
9012
+ if (this.readDOMTimeout != null) {
9013
+ clearTimeout(this.readDOMTimeout);
9014
+ this.readDOMTimeout = null;
 
 
9015
  }
9016
+
9017
+ var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
9018
+ var from = sel.from(), to = sel.to();
9019
+ if (from.ch == 0 && from.line > cm.firstLine())
9020
+ { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); }
9021
+ if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())
9022
+ { to = Pos(to.line + 1, 0); }
9023
+ if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }
9024
+
9025
+ var fromIndex, fromLine, fromNode;
9026
+ if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
9027
+ fromLine = lineNo(display.view[0].line);
9028
+ fromNode = display.view[0].node;
9029
+ } else {
9030
+ fromLine = lineNo(display.view[fromIndex].line);
9031
+ fromNode = display.view[fromIndex - 1].node.nextSibling;
9032
+ }
9033
+ var toIndex = findViewIndex(cm, to.line);
9034
+ var toLine, toNode;
9035
+ if (toIndex == display.view.length - 1) {
9036
+ toLine = display.viewTo - 1;
9037
+ toNode = display.lineDiv.lastChild;
9038
+ } else {
9039
+ toLine = lineNo(display.view[toIndex + 1].line) - 1;
9040
+ toNode = display.view[toIndex + 1].node.previousSibling;
9041
+ }
9042
+
9043
+ if (!fromNode) { return false }
9044
+ var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
9045
+ var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
9046
+ while (newText.length > 1 && oldText.length > 1) {
9047
+ if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
9048
+ else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
9049
+ else { break }
9050
+ }
9051
+
9052
+ var cutFront = 0, cutEnd = 0;
9053
+ var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
9054
+ while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
9055
+ { ++cutFront; }
9056
+ var newBot = lst(newText), oldBot = lst(oldText);
9057
+ var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
9058
+ oldBot.length - (oldText.length == 1 ? cutFront : 0));
9059
+ while (cutEnd < maxCutEnd &&
9060
+ newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
9061
+ { ++cutEnd; }
9062
+ // Try to move start of change to start of selection if ambiguous
9063
+ if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) {
9064
+ while (cutFront && cutFront > from.ch &&
9065
+ newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) {
9066
+ cutFront--;
9067
+ cutEnd++;
9068
+ }
9069
+ }
9070
+
9071
+ newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "");
9072
+ newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "");
9073
+
9074
+ var chFrom = Pos(fromLine, cutFront);
9075
+ var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
9076
+ if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
9077
+ replaceRange(cm.doc, newText, chFrom, chTo, "+input");
9078
+ return true
9079
  }
9080
  };
9081
 
9082
+ ContentEditableInput.prototype.ensurePolled = function () {
9083
+ this.forceCompositionEnd();
9084
+ };
9085
+ ContentEditableInput.prototype.reset = function () {
9086
+ this.forceCompositionEnd();
9087
+ };
9088
+ ContentEditableInput.prototype.forceCompositionEnd = function () {
9089
+ if (!this.composing) { return }
9090
+ clearTimeout(this.readDOMTimeout);
9091
+ this.composing = null;
9092
+ this.updateFromDOM();
9093
+ this.div.blur();
9094
+ this.div.focus();
9095
+ };
9096
+ ContentEditableInput.prototype.readFromDOMSoon = function () {
9097
+ var this$1 = this;
9098
+
9099
+ if (this.readDOMTimeout != null) { return }
9100
+ this.readDOMTimeout = setTimeout(function () {
9101
+ this$1.readDOMTimeout = null;
9102
+ if (this$1.composing) {
9103
+ if (this$1.composing.done) { this$1.composing = null; }
9104
+ else { return }
9105
+ }
9106
+ this$1.updateFromDOM();
9107
+ }, 80);
9108
+ };
9109
 
9110
+ ContentEditableInput.prototype.updateFromDOM = function () {
9111
+ var this$1 = this;
 
 
 
 
9112
 
9113
+ if (this.cm.isReadOnly() || !this.pollContent())
9114
+ { runInOp(this.cm, function () { return regChange(this$1.cm); }); }
9115
+ };
9116
 
9117
+ ContentEditableInput.prototype.setUneditable = function (node) {
9118
+ node.contentEditable = "false";
9119
+ };
 
 
9120
 
9121
+ ContentEditableInput.prototype.onKeyPress = function (e) {
9122
+ if (e.charCode == 0 || this.composing) { return }
9123
+ e.preventDefault();
9124
+ if (!this.cm.isReadOnly())
9125
+ { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); }
9126
+ };
9127
+
9128
+ ContentEditableInput.prototype.readOnlyChanged = function (val) {
9129
+ this.div.contentEditable = String(val != "nocursor");
9130
+ };
9131
+
9132
+ ContentEditableInput.prototype.onContextMenu = function () {};
9133
+ ContentEditableInput.prototype.resetPosition = function () {};
9134
+
9135
+ ContentEditableInput.prototype.needsContentAttribute = true;
9136
+
9137
+ function posToDOM(cm, pos) {
9138
+ var view = findViewForLine(cm, pos.line);
9139
+ if (!view || view.hidden) { return null }
9140
+ var line = getLine(cm.doc, pos.line);
9141
+ var info = mapFromLineView(view, line, pos.line);
9142
+
9143
+ var order = getOrder(line, cm.doc.direction), side = "left";
9144
+ if (order) {
9145
+ var partPos = getBidiPartAt(order, pos.ch);
9146
+ side = partPos % 2 ? "right" : "left";
9147
+ }
9148
+ var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
9149
+ result.offset = result.collapse == "right" ? result.end : result.start;
9150
+ return result
9151
  }
9152
+
9153
+ function isInGutter(node) {
9154
+ for (var scan = node; scan; scan = scan.parentNode)
9155
+ { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } }
9156
+ return false
9157
  }
9158
 
9159
+ function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }
9160
 
9161
+ function domTextBetween(cm, from, to, fromLine, toLine) {
9162
+ var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false;
9163
+ function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
9164
+ function close() {
9165
+ if (closing) {
9166
+ text += lineSep;
9167
+ if (extraLinebreak) { text += lineSep; }
9168
+ closing = extraLinebreak = false;
9169
+ }
9170
  }
9171
+ function addText(str) {
9172
+ if (str) {
9173
+ close();
9174
+ text += str;
9175
+ }
9176
+ }
9177
+ function walk(node) {
9178
+ if (node.nodeType == 1) {
9179
+ var cmText = node.getAttribute("cm-text");
9180
+ if (cmText) {
9181
+ addText(cmText);
9182
+ return
9183
+ }
9184
+ var markerID = node.getAttribute("cm-marker"), range;
9185
+ if (markerID) {
9186
+ var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
9187
+ if (found.length && (range = found[0].find(0)))
9188
+ { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); }
9189
+ return
9190
+ }
9191
+ if (node.getAttribute("contenteditable") == "false") { return }
9192
+ var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName);
9193
+ if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return }
9194
 
9195
+ if (isBlock) { close(); }
9196
+ for (var i = 0; i < node.childNodes.length; i++)
9197
+ { walk(node.childNodes[i]); }
 
 
 
 
9198
 
9199
+ if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; }
9200
+ if (isBlock) { closing = true; }
9201
+ } else if (node.nodeType == 3) {
9202
+ addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " "));
9203
+ }
9204
+ }
9205
+ for (;;) {
9206
+ walk(from);
9207
+ if (from == to) { break }
9208
+ from = from.nextSibling;
9209
+ extraLinebreak = false;
9210
+ }
9211
+ return text
9212
  }
9213
 
9214
+ function domToPos(cm, node, offset) {
9215
+ var lineNode;
9216
+ if (node == cm.display.lineDiv) {
9217
+ lineNode = cm.display.lineDiv.childNodes[offset];
9218
+ if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }
9219
+ node = null; offset = 0;
9220
+ } else {
9221
+ for (lineNode = node;; lineNode = lineNode.parentNode) {
9222
+ if (!lineNode || lineNode == cm.display.lineDiv) { return null }
9223
+ if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }
9224
+ }
9225
+ }
9226
+ for (var i = 0; i < cm.display.view.length; i++) {
9227
+ var lineView = cm.display.view[i];
9228
+ if (lineView.node == lineNode)
9229
+ { return locateNodeInLineView(lineView, node, offset) }
9230
+ }
9231
  }
9232
 
9233
+ function locateNodeInLineView(lineView, node, offset) {
9234
+ var wrapper = lineView.text.firstChild, bad = false;
9235
+ if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }
9236
+ if (node == wrapper) {
9237
+ bad = true;
9238
+ node = wrapper.childNodes[offset];
9239
+ offset = 0;
9240
+ if (!node) {
9241
+ var line = lineView.rest ? lst(lineView.rest) : lineView.line;
9242
+ return badPos(Pos(lineNo(line), line.text.length), bad)
9243
+ }
9244
+ }
9245
 
9246
+ var textNode = node.nodeType == 3 ? node : null, topNode = node;
9247
+ if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
9248
+ textNode = node.firstChild;
9249
+ if (offset) { offset = textNode.nodeValue.length; }
9250
+ }
9251
+ while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; }
9252
+ var measure = lineView.measure, maps = measure.maps;
9253
 
9254
+ function find(textNode, topNode, offset) {
9255
+ for (var i = -1; i < (maps ? maps.length : 0); i++) {
9256
+ var map = i < 0 ? measure.map : maps[i];
9257
+ for (var j = 0; j < map.length; j += 3) {
9258
+ var curNode = map[j + 2];
9259
+ if (curNode == textNode || curNode == topNode) {
9260
+ var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
9261
+ var ch = map[j] + offset;
9262
+ if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; }
9263
+ return Pos(line, ch)
9264
+ }
9265
+ }
9266
+ }
9267
+ }
9268
+ var found = find(textNode, topNode, offset);
9269
+ if (found) { return badPos(found, bad) }
9270
 
9271
+ // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
9272
+ for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
9273
+ found = find(after, after.firstChild, 0);
9274
+ if (found)
9275
+ { return badPos(Pos(found.line, found.ch - dist), bad) }
9276
+ else
9277
+ { dist += after.textContent.length; }
9278
+ }
9279
+ for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {
9280
+ found = find(before, before.firstChild, -1);
9281
+ if (found)
9282
+ { return badPos(Pos(found.line, found.ch + dist$1), bad) }
9283
+ else
9284
+ { dist$1 += before.textContent.length; }
9285
+ }
9286
  }
9287
 
9288
+ // TEXTAREA INPUT STYLE
9289
+
9290
+ var TextareaInput = function(cm) {
9291
+ this.cm = cm;
9292
+ // See input.poll and input.reset
9293
+ this.prevInput = "";
9294
+
9295
+ // Flag that indicates whether we expect input to appear real soon
9296
+ // now (after some event like 'keypress' or 'input') and are
9297
+ // polling intensively.
9298
+ this.pollingFast = false;
9299
+ // Self-resetting timeout for the poller
9300
+ this.polling = new Delayed();
9301
+ // Used to work around IE issue with selection being forgotten when focus moves away from textarea
9302
+ this.hasSelection = false;
9303
+ this.composing = null;
9304
  };
9305
 
9306
+ TextareaInput.prototype.init = function (display) {
9307
+ var this$1 = this;
 
 
 
9308
 
9309
+ var input = this, cm = this.cm;
9310
+ this.createField(display);
9311
+ var te = this.textarea;
9312
 
9313
+ display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild);
 
 
 
 
 
 
 
 
 
9314
 
9315
+ // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
9316
+ if (ios) { te.style.width = "0px"; }
 
 
 
 
 
9317
 
9318
+ on(te, "input", function () {
9319
+ if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; }
9320
+ input.poll();
9321
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9322
 
9323
+ on(te, "paste", function (e) {
9324
+ if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
9325
 
9326
+ cm.state.pasteIncoming = +new Date;
9327
+ input.fastPoll();
9328
+ });
9329
 
9330
+ function prepareCopyCut(e) {
9331
+ if (signalDOMEvent(cm, e)) { return }
9332
+ if (cm.somethingSelected()) {
9333
+ setLastCopied({lineWise: false, text: cm.getSelections()});
9334
+ } else if (!cm.options.lineWiseCopyCut) {
9335
+ return
9336
+ } else {
9337
+ var ranges = copyableRanges(cm);
9338
+ setLastCopied({lineWise: true, text: ranges.text});
9339
+ if (e.type == "cut") {
9340
+ cm.setSelections(ranges.ranges, null, sel_dontScroll);
9341
+ } else {
9342
+ input.prevInput = "";
9343
+ te.value = ranges.text.join("\n");
9344
+ selectInput(te);
9345
+ }
9346
+ }
9347
+ if (e.type == "cut") { cm.state.cutIncoming = +new Date; }
9348
  }
9349
+ on(te, "cut", prepareCopyCut);
9350
+ on(te, "copy", prepareCopyCut);
9351
 
9352
+ on(display.scroller, "paste", function (e) {
9353
+ if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }
9354
+ if (!te.dispatchEvent) {
9355
+ cm.state.pasteIncoming = +new Date;
9356
+ input.focus();
9357
+ return
9358
+ }
9359
+
9360
+ // Pass the `paste` event to the textarea so it's handled by its event listener.
9361
+ var event = new Event("paste");
9362
+ event.clipboardData = e.clipboardData;
9363
+ te.dispatchEvent(event);
 
 
9364
  });
9365
+
9366
+ // Prevent normal selection in the editor (we handle our own)
9367
+ on(display.lineSpace, "selectstart", function (e) {
9368
+ if (!eventInWidget(display, e)) { e_preventDefault(e); }
9369
  });
 
9370
 
9371
+ on(te, "compositionstart", function () {
9372
+ var start = cm.getCursor("from");
9373
+ if (input.composing) { input.composing.range.clear(); }
9374
+ input.composing = {
9375
+ start: start,
9376
+ range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
9377
+ };
9378
+ });
9379
+ on(te, "compositionend", function () {
9380
+ if (input.composing) {
9381
+ input.poll();
9382
+ input.composing.range.clear();
9383
+ input.composing = null;
9384
+ }
9385
+ });
9386
+ };
9387
 
9388
+ TextareaInput.prototype.createField = function (_display) {
9389
+ // Wraps and hides input textarea
9390
+ this.wrapper = hiddenTextarea();
9391
+ // The semihidden textarea that is focused when the editor is
9392
+ // focused, and receives input.
9393
+ this.textarea = this.wrapper.firstChild;
9394
+ };
 
9395
 
9396
+ TextareaInput.prototype.screenReaderLabelChanged = function (label) {
9397
+ // Label for screenreaders, accessibility
9398
+ if(label) {
9399
+ this.textarea.setAttribute('aria-label', label);
9400
+ } else {
9401
+ this.textarea.removeAttribute('aria-label');
 
9402
  }
9403
+ };
 
 
 
 
9404
 
9405
+ TextareaInput.prototype.prepareSelection = function () {
9406
+ // Redraw the selection and/or cursor
9407
+ var cm = this.cm, display = cm.display, doc = cm.doc;
9408
+ var result = prepareSelection(cm);
 
 
 
 
 
 
9409
 
9410
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
9411
+ if (cm.options.moveInputWithCursor) {
9412
+ var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
9413
+ var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
9414
+ result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
9415
+ headPos.top + lineOff.top - wrapOff.top));
9416
+ result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
9417
+ headPos.left + lineOff.left - wrapOff.left));
 
 
 
 
 
 
 
 
9418
  }
 
 
9419
 
9420
+ return result
 
 
 
 
 
 
 
9421
  };
9422
 
9423
+ TextareaInput.prototype.showSelection = function (drawn) {
9424
+ var cm = this.cm, display = cm.display;
9425
+ removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
9426
+ removeChildrenAndAdd(display.selectionDiv, drawn.selection);
9427
+ if (drawn.teTop != null) {
9428
+ this.wrapper.style.top = drawn.teTop + "px";
9429
+ this.wrapper.style.left = drawn.teLeft + "px";
9430
+ }
9431
+ };
9432
 
9433
+ // Reset the input to correspond to the selection (or to be empty,
9434
+ // when not typing and nothing is selected)
9435
+ TextareaInput.prototype.reset = function (typing) {
9436
+ if (this.contextMenuPending || this.composing) { return }
9437
+ var cm = this.cm;
9438
+ if (cm.somethingSelected()) {
9439
+ this.prevInput = "";
9440
+ var content = cm.getSelection();
9441
+ this.textarea.value = content;
9442
+ if (cm.state.focused) { selectInput(this.textarea); }
9443
+ if (ie && ie_version >= 9) { this.hasSelection = content; }
9444
+ } else if (!typing) {
9445
+ this.prevInput = this.textarea.value = "";
9446
+ if (ie && ie_version >= 9) { this.hasSelection = null; }
9447
+ }
9448
+ };
 
 
 
 
 
 
 
 
 
 
 
9449
 
9450
+ TextareaInput.prototype.getField = function () { return this.textarea };
9451
 
9452
+ TextareaInput.prototype.supportsTouch = function () { return false };
9453
+
9454
+ TextareaInput.prototype.focus = function () {
9455
+ if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
9456
+ try { this.textarea.focus(); }
9457
+ catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
 
 
 
9458
  }
9459
+ };
 
9460
 
9461
+ TextareaInput.prototype.blur = function () { this.textarea.blur(); };
 
9462
 
9463
+ TextareaInput.prototype.resetPosition = function () {
9464
+ this.wrapper.style.top = this.wrapper.style.left = 0;
9465
+ };
 
 
 
9466
 
9467
+ TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9468
 
9469
+ // Poll for input changes, using the normal rate of polling. This
9470
+ // runs as long as the editor is focused.
9471
+ TextareaInput.prototype.slowPoll = function () {
9472
+ var this$1 = this;
9473
+
9474
+ if (this.pollingFast) { return }
9475
+ this.polling.set(this.cm.options.pollInterval, function () {
9476
+ this$1.poll();
9477
+ if (this$1.cm.state.focused) { this$1.slowPoll(); }
9478
+ });
9479
+ };
9480
+
9481
+ // When an event has just come in that is likely to add or change
9482
+ // something in the input textarea, we poll faster, to ensure that
9483
+ // the change appears on the screen quickly.
9484
+ TextareaInput.prototype.fastPoll = function () {
9485
+ var missed = false, input = this;
9486
+ input.pollingFast = true;
9487
+ function p() {
9488
+ var changed = input.poll();
9489
+ if (!changed && !missed) {missed = true; input.polling.set(60, p);}
9490
+ else {input.pollingFast = false; input.slowPoll();}
9491
+ }
9492
+ input.polling.set(20, p);
9493
+ };
9494
+
9495
+ // Read input from the textarea, and update the document to match.
9496
+ // When something is selected, it is present in the textarea, and
9497
+ // selected (unless it is huge, in which case a placeholder is
9498
+ // used). When nothing is selected, the cursor sits after previously
9499
+ // seen text (can be empty), which is stored in prevInput (we must
9500
+ // not reset the textarea when typing, because that breaks IME).
9501
+ TextareaInput.prototype.poll = function () {
9502
+ var this$1 = this;
9503
+
9504
+ var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
9505
+ // Since this is called a *lot*, try to bail out as cheaply as
9506
+ // possible when it is clear that nothing happened. hasSelection
9507
+ // will be the case when there is a lot of text in the textarea,
9508
+ // in which case reading its value would be expensive.
9509
+ if (this.contextMenuPending || !cm.state.focused ||
9510
+ (hasSelection(input) && !prevInput && !this.composing) ||
9511
+ cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
9512
+ { return false }
9513
+
9514
+ var text = input.value;
9515
+ // If nothing changed, bail.
9516
+ if (text == prevInput && !cm.somethingSelected()) { return false }
9517
+ // Work around nonsensical selection resetting in IE9/10, and
9518
+ // inexplicable appearance of private area unicode characters on
9519
+ // some key combos in Mac (#2689).
9520
+ if (ie && ie_version >= 9 && this.hasSelection === text ||
9521
+ mac && /[\uf700-\uf7ff]/.test(text)) {
9522
+ cm.display.input.reset();
9523
+ return false
9524
+ }
9525
+
9526
+ if (cm.doc.sel == cm.display.selForContextMenu) {
9527
+ var first = text.charCodeAt(0);
9528
+ if (first == 0x200b && !prevInput) { prevInput = "\u200b"; }
9529
+ if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") }
9530
+ }
9531
+ // Find the part of the input that is actually new
9532
+ var same = 0, l = Math.min(prevInput.length, text.length);
9533
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; }
9534
+
9535
+ runInOp(cm, function () {
9536
+ applyTextInput(cm, text.slice(same), prevInput.length - same,
9537
+ null, this$1.composing ? "*compose" : null);
9538
+
9539
+ // Don't leave long text in the textarea, since it makes further polling slow
9540
+ if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; }
9541
+ else { this$1.prevInput = text; }
9542
+
9543
+ if (this$1.composing) {
9544
+ this$1.composing.range.clear();
9545
+ this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"),
9546
+ {className: "CodeMirror-composing"});
9547
  }
9548
+ });
9549
+ return true
9550
+ };
9551
 
9552
+ TextareaInput.prototype.ensurePolled = function () {
9553
+ if (this.pollingFast && this.poll()) { this.pollingFast = false; }
9554
+ };
 
 
 
9555
 
9556
+ TextareaInput.prototype.onKeyPress = function () {
9557
+ if (ie && ie_version >= 9) { this.hasSelection = null; }
9558
+ this.fastPoll();
9559
+ };
 
 
 
 
 
 
9560
 
9561
+ TextareaInput.prototype.onContextMenu = function (e) {
9562
+ var input = this, cm = input.cm, display = cm.display, te = input.textarea;
9563
+ if (input.contextMenuPending) { input.contextMenuPending(); }
9564
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
9565
+ if (!pos || presto) { return } // Opera is difficult.
9566
+
9567
+ // Reset the current text selection only if the click is done outside of the selection
9568
+ // and 'resetSelectionOnContextMenu' option is true.
9569
+ var reset = cm.options.resetSelectionOnContextMenu;
9570
+ if (reset && cm.doc.sel.contains(pos) == -1)
9571
+ { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); }
9572
+
9573
+ var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText;
9574
+ var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect();
9575
+ input.wrapper.style.cssText = "position: static";
9576
+ te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
9577
+ var oldScrollY;
9578
+ if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712)
9579
+ display.input.focus();
9580
+ if (webkit) { window.scrollTo(null, oldScrollY); }
9581
+ display.input.reset();
9582
+ // Adds "Select all" to context menu in FF
9583
+ if (!cm.somethingSelected()) { te.value = input.prevInput = " "; }
9584
+ input.contextMenuPending = rehide;
9585
+ display.selForContextMenu = cm.doc.sel;
9586
+ clearTimeout(display.detectingSelectAll);
9587
+
9588
+ // Select-all will be greyed out if there's nothing to select, so
9589
+ // this adds a zero-width space so that we can later check whether
9590
+ // it got selected.
9591
+ function prepareSelectAllHack() {
9592
+ if (te.selectionStart != null) {
9593
+ var selected = cm.somethingSelected();
9594
+ var extval = "\u200b" + (selected ? te.value : "");
9595
+ te.value = "\u21da"; // Used to catch context-menu undo
9596
+ te.value = extval;
9597
+ input.prevInput = selected ? "" : "\u200b";
9598
+ te.selectionStart = 1; te.selectionEnd = extval.length;
9599
+ // Re-set this, in case some other handler touched the
9600
+ // selection in the meantime.
9601
+ display.selForContextMenu = cm.doc.sel;
9602
+ }
9603
+ }
9604
+ function rehide() {
9605
+ if (input.contextMenuPending != rehide) { return }
9606
+ input.contextMenuPending = false;
9607
+ input.wrapper.style.cssText = oldWrapperCSS;
9608
+ te.style.cssText = oldCSS;
9609
+ if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); }
9610
+
9611
+ // Try to detect the user choosing select-all
9612
+ if (te.selectionStart != null) {
9613
+ if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); }
9614
+ var i = 0, poll = function () {
9615
+ if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
9616
+ te.selectionEnd > 0 && input.prevInput == "\u200b") {
9617
+ operation(cm, selectAll)(cm);
9618
+ } else if (i++ < 10) {
9619
+ display.detectingSelectAll = setTimeout(poll, 500);
9620
+ } else {
9621
+ display.selForContextMenu = null;
9622
+ display.input.reset();
9623
+ }
9624
+ };
9625
+ display.detectingSelectAll = setTimeout(poll, 200);
9626
  }
9627
  }
 
9628
 
9629
+ if (ie && ie_version >= 9) { prepareSelectAllHack(); }
9630
+ if (captureRightClick) {
9631
+ e_stop(e);
9632
+ var mouseup = function () {
9633
+ off(window, "mouseup", mouseup);
9634
+ setTimeout(rehide, 20);
9635
+ };
9636
+ on(window, "mouseup", mouseup);
9637
+ } else {
9638
+ setTimeout(rehide, 50);
9639
+ }
9640
+ };
9641
 
9642
+ TextareaInput.prototype.readOnlyChanged = function (val) {
9643
+ if (!val) { this.reset(); }
9644
+ this.textarea.disabled = val == "nocursor";
9645
+ this.textarea.readOnly = !!val;
9646
+ };
9647
 
9648
+ TextareaInput.prototype.setUneditable = function () {};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9649
 
9650
+ TextareaInput.prototype.needsContentAttribute = false;
9651
+
9652
+ function fromTextArea(textarea, options) {
9653
+ options = options ? copyObj(options) : {};
9654
+ options.value = textarea.value;
9655
+ if (!options.tabindex && textarea.tabIndex)
9656
+ { options.tabindex = textarea.tabIndex; }
9657
+ if (!options.placeholder && textarea.placeholder)
9658
+ { options.placeholder = textarea.placeholder; }
9659
+ // Set autofocus to true if this textarea is focused, or if it has
9660
+ // autofocus and no other element is focused.
9661
+ if (options.autofocus == null) {
9662
+ var hasFocus = activeElt();
9663
+ options.autofocus = hasFocus == textarea ||
9664
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body;
 
9665
  }
9666
 
9667
+ function save() {textarea.value = cm.getValue();}
 
 
 
9668
 
9669
+ var realSubmit;
9670
+ if (textarea.form) {
9671
+ on(textarea.form, "submit", save);
9672
+ // Deplorable hack to make the submit method do the right thing.
9673
+ if (!options.leaveSubmitMethodAlone) {
9674
+ var form = textarea.form;
9675
+ realSubmit = form.submit;
9676
+ try {
9677
+ var wrappedSubmit = form.submit = function () {
9678
+ save();
9679
+ form.submit = realSubmit;
9680
+ form.submit();
9681
+ form.submit = wrappedSubmit;
9682
+ };
9683
+ } catch(e) {}
9684
+ }
9685
  }
9686
 
9687
+ options.finishInit = function (cm) {
9688
+ cm.save = save;
9689
+ cm.getTextArea = function () { return textarea; };
9690
+ cm.toTextArea = function () {
9691
+ cm.toTextArea = isNaN; // Prevent this from being ran twice
9692
+ save();
9693
+ textarea.parentNode.removeChild(cm.getWrapperElement());
9694
+ textarea.style.display = "";
9695
+ if (textarea.form) {
9696
+ off(textarea.form, "submit", save);
9697
+ if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function")
9698
+ { textarea.form.submit = realSubmit; }
9699
+ }
9700
+ };
9701
+ };
9702
 
9703
+ textarea.style.display = "none";
9704
+ var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },
9705
+ options);
9706
+ return cm
9707
+ }
9708
+
9709
+ function addLegacyProps(CodeMirror) {
9710
+ CodeMirror.off = off;
9711
+ CodeMirror.on = on;
9712
+ CodeMirror.wheelEventPixels = wheelEventPixels;
9713
+ CodeMirror.Doc = Doc;
9714
+ CodeMirror.splitLines = splitLinesAuto;
9715
+ CodeMirror.countColumn = countColumn;
9716
+ CodeMirror.findColumn = findColumn;
9717
+ CodeMirror.isWordChar = isWordCharBasic;
9718
+ CodeMirror.Pass = Pass;
9719
+ CodeMirror.signal = signal;
9720
+ CodeMirror.Line = Line;
9721
+ CodeMirror.changeEnd = changeEnd;
9722
+ CodeMirror.scrollbarModel = scrollbarModel;
9723
+ CodeMirror.Pos = Pos;
9724
+ CodeMirror.cmpPos = cmp;
9725
+ CodeMirror.modes = modes;
9726
+ CodeMirror.mimeModes = mimeModes;
9727
+ CodeMirror.resolveMode = resolveMode;
9728
+ CodeMirror.getMode = getMode;
9729
+ CodeMirror.modeExtensions = modeExtensions;
9730
+ CodeMirror.extendMode = extendMode;
9731
+ CodeMirror.copyState = copyState;
9732
+ CodeMirror.startState = startState;
9733
+ CodeMirror.innerMode = innerMode;
9734
+ CodeMirror.commands = commands;
9735
+ CodeMirror.keyMap = keyMap;
9736
+ CodeMirror.keyName = keyName;
9737
+ CodeMirror.isModifierKey = isModifierKey;
9738
+ CodeMirror.lookupKey = lookupKey;
9739
+ CodeMirror.normalizeKeyMap = normalizeKeyMap;
9740
+ CodeMirror.StringStream = StringStream;
9741
+ CodeMirror.SharedTextMarker = SharedTextMarker;
9742
+ CodeMirror.TextMarker = TextMarker;
9743
+ CodeMirror.LineWidget = LineWidget;
9744
+ CodeMirror.e_preventDefault = e_preventDefault;
9745
+ CodeMirror.e_stopPropagation = e_stopPropagation;
9746
+ CodeMirror.e_stop = e_stop;
9747
+ CodeMirror.addClass = addClass;
9748
+ CodeMirror.contains = contains;
9749
+ CodeMirror.rmClass = rmClass;
9750
+ CodeMirror.keyNames = keyNames;
9751
+ }
9752
 
9753
+ // EDITOR CONSTRUCTOR
 
 
 
 
 
 
 
 
 
9754
 
9755
+ defineOptions(CodeMirror);
 
 
 
 
 
 
 
 
 
9756
 
9757
+ addEditorMethods(CodeMirror);
 
 
 
 
 
 
 
 
 
 
 
 
 
9758
 
9759
+ // Set up methods on CodeMirror's prototype to redirect to the editor's document.
9760
+ var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
9761
+ for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
9762
+ { CodeMirror.prototype[prop] = (function(method) {
9763
+ return function() {return method.apply(this.doc, arguments)}
9764
+ })(Doc.prototype[prop]); } }
 
 
9765
 
9766
+ eventMixin(Doc);
9767
+ CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9768
 
9769
+ // Extra arguments are stored as the mode's dependencies, which is
9770
+ // used by (legacy) mechanisms like loadmode.js to automatically
9771
+ // load a mode. (Preferred mechanism is the require/define calls.)
9772
+ CodeMirror.defineMode = function(name/*, mode, …*/) {
9773
+ if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; }
9774
+ defineMode.apply(this, arguments);
9775
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9776
 
9777
+ CodeMirror.defineMIME = defineMIME;
9778
+
9779
+ // Minimal default mode.
9780
+ CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
9781
+ CodeMirror.defineMIME("text/plain", "null");
9782
+
9783
+ // EXTENSIONS
9784
+
9785
+ CodeMirror.defineExtension = function (name, func) {
9786
+ CodeMirror.prototype[name] = func;
9787
+ };
9788
+ CodeMirror.defineDocExtension = function (name, func) {
9789
+ Doc.prototype[name] = func;
9790
+ };
9791
 
9792
+ CodeMirror.fromTextArea = fromTextArea;
9793
 
9794
+ addLegacyProps(CodeMirror);
9795
+
9796
+ CodeMirror.version = "5.59.2";
9797
 
9798
  return CodeMirror;
9799
+
9800
+ })));
js/codemirror/codemirror.min.js CHANGED
@@ -1,5 +1 @@
1
- !function(e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else{if("function"==typeof define&&define.amd)return define([],e);this.CodeMirror=e()}}(function(){"use strict";function e(r,n){if(!(this instanceof e))return new e(r,n);this.options=n=n?Oo(n):{},Oo(Kl,n,!1),d(n);var i=n.value;"string"==typeof i&&(i=new ps(i,n.mode)),this.doc=i;var o=new e.inputStyles[n.inputStyle](this),l=this.display=new t(r,i,o);l.wrapper.CodeMirror=this,u(this),s(this),n.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),n.autofocus&&!wl&&l.input.focus(),m(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,draggingText:!1,highlight:new So,keySeq:null,specialChars:null};var a=this;cl&&11>fl&&setTimeout(function(){a.display.input.reset(!0)},20),Rr(this),Vo(),mr(this),this.curOp.forceUpdate=!0,Vi(this,i),n.autofocus&&!wl||a.hasFocus()?setTimeout(Do(cn,this),20):fn(this);for(var c in jl)jl.hasOwnProperty(c)&&jl[c](this,n[c],Xl);C(this),n.finishInit&&n.finishInit(this);for(var f=0;f<ql.length;++f)ql[f](this);br(this),hl&&n.lineWrapping&&"optimizelegibility"==getComputedStyle(l.lineDiv).textRendering&&(l.lineDiv.style.textRendering="auto")}function t(e,t,r){var n=this;this.input=r,n.scrollbarFiller=zo("div",null,"CodeMirror-scrollbar-filler"),n.scrollbarFiller.setAttribute("cm-not-content","true"),n.gutterFiller=zo("div",null,"CodeMirror-gutter-filler"),n.gutterFiller.setAttribute("cm-not-content","true"),n.lineDiv=zo("div",null,"CodeMirror-code"),n.selectionDiv=zo("div",null,null,"position: relative; z-index: 1"),n.cursorDiv=zo("div",null,"CodeMirror-cursors"),n.measure=zo("div",null,"CodeMirror-measure"),n.lineMeasure=zo("div",null,"CodeMirror-measure"),n.lineSpace=zo("div",[n.measure,n.lineMeasure,n.selectionDiv,n.cursorDiv,n.lineDiv],null,"position: relative; outline: none"),n.mover=zo("div",[zo("div",[n.lineSpace],"CodeMirror-lines")],null,"position: relative"),n.sizer=zo("div",[n.mover],"CodeMirror-sizer"),n.sizerWidth=null,n.heightForcer=zo("div",null,null,"position: absolute; height: "+Ls+"px; width: 1px;"),n.gutters=zo("div",null,"CodeMirror-gutters"),n.lineGutter=null,n.scroller=zo("div",[n.sizer,n.heightForcer,n.gutters],"CodeMirror-scroll"),n.scroller.setAttribute("tabIndex","-1"),n.wrapper=zo("div",[n.scrollbarFiller,n.gutterFiller,n.scroller],"CodeMirror"),cl&&8>fl&&(n.gutters.style.zIndex=-1,n.scroller.style.paddingRight=0),hl||sl&&wl||(n.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(n.wrapper):e(n.wrapper)),n.viewFrom=n.viewTo=t.first,n.reportedViewFrom=n.reportedViewTo=t.first,n.view=[],n.renderedView=null,n.externalMeasured=null,n.viewOffset=0,n.lastWrapHeight=n.lastWrapWidth=0,n.updateLineNumbers=null,n.nativeBarWidth=n.barHeight=n.barWidth=0,n.scrollbarsClipped=!1,n.lineNumWidth=n.lineNumInnerWidth=n.lineNumChars=null,n.alignWidgets=!1,n.cachedCharWidth=n.cachedTextHeight=n.cachedPaddingH=null,n.maxLine=null,n.maxLineLength=0,n.maxLineChanged=!1,n.wheelDX=n.wheelDY=n.wheelStartX=n.wheelStartY=null,n.shift=!1,n.selForContextMenu=null,n.activeTouch=null,r.init(n)}function r(t){t.doc.mode=e.getMode(t.options,t.doc.modeOption),n(t)}function n(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.frontier=e.doc.first,zt(e,100),e.state.modeGen++,e.curOp&&Dr(e)}function i(e){e.options.lineWrapping?(Bs(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(Rs(e.display.wrapper,"CodeMirror-wrap"),h(e)),l(e),Dr(e),ir(e),setTimeout(function(){y(e)},100)}function o(e){var t=gr(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/vr(e.display)-3);return function(i){if(gi(e.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l<i.widgets.length;l++)i.widgets[l].height&&(o+=i.widgets[l].height);return r?o+(Math.ceil(i.text.length/n)||1)*t:o+t}}function l(e){var t=e.doc,r=o(e);t.iter(function(e){var t=r(e);t!=e.height&&_i(e,t)})}function s(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),ir(e)}function a(e){u(e),Dr(e),setTimeout(function(){x(e)},20)}function u(e){var t=e.display.gutters,r=e.options.gutters;Eo(t);for(var n=0;n<r.length;++n){var i=r[n],o=t.appendChild(zo("div",null,"CodeMirror-gutter "+i));"CodeMirror-linenumbers"==i&&(e.display.lineGutter=o,o.style.width=(e.display.lineNumWidth||1)+"px")}t.style.display=n?"":"none",c(e)}function c(e){var t=e.display.gutters.offsetWidth;e.display.sizer.style.marginLeft=t+"px"}function f(e){if(0==e.height)return 0;for(var t,r=e.text.length,n=e;t=ai(n);){var i=t.find(0,!0);n=i.from.line,r+=i.from.ch-i.to.ch}for(n=e;t=ui(n);){var i=t.find(0,!0);r-=n.text.length-i.from.ch,n=i.to.line,r+=n.text.length-i.to.ch}return r}function h(e){var t=e.display,r=e.doc;t.maxLine=Ki(r,r.first),t.maxLineLength=f(t.maxLine),t.maxLineChanged=!0,r.iter(function(e){var r=f(e);r>t.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)})}function d(e){var t=Mo(e.gutters,"CodeMirror-linenumbers");-1==t&&e.lineNumbers?e.gutters=e.gutters.concat(["CodeMirror-linenumbers"]):t>-1&&!e.lineNumbers&&(e.gutters=e.gutters.slice(0),e.gutters.splice(t,1))}function p(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Gt(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+Vt(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}function g(e,t,r){this.cm=r;var n=this.vert=zo("div",[zo("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=zo("div",[zo("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");e(n),e(i),ws(n,"scroll",function(){n.clientHeight&&t(n.scrollTop,"vertical")}),ws(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedOverlay=!1,cl&&8>fl&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}function v(){}function m(t){t.display.scrollbars&&(t.display.scrollbars.clear(),t.display.scrollbars.addClass&&Rs(t.display.wrapper,t.display.scrollbars.addClass)),t.display.scrollbars=new e.scrollbarModel[t.options.scrollbarStyle](function(e){t.display.wrapper.insertBefore(e,t.display.scrollbarFiller),ws(e,"mousedown",function(){t.state.focused&&setTimeout(function(){t.display.input.focus()},0)}),e.setAttribute("cm-not-content","true")},function(e,r){"horizontal"==r?Qr(t,e):Zr(t,e)},t),t.display.scrollbars.addClass&&Bs(t.display.wrapper,t.display.scrollbars.addClass)}function y(e,t){t||(t=p(e));var r=e.display.barWidth,n=e.display.barHeight;b(e,t);for(var i=0;4>i&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&O(e),b(e,p(e)),r=e.display.barWidth,n=e.display.barHeight}function b(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}function w(e,t,r){var n=r&&null!=r.top?Math.max(0,r.top):e.scroller.scrollTop;n=Math.floor(n-Bt(e));var i=r&&null!=r.bottom?r.bottom:n+e.wrapper.clientHeight,o=$i(t,n),l=$i(t,i);if(r&&r.ensure){var s=r.ensure.from.line,a=r.ensure.to.line;o>s?(o=s,l=$i(t,qi(Ki(t,s))+e.wrapper.clientHeight)):Math.min(a,t.lastLine())>=l&&(o=$i(t,qi(Ki(t,a))-e.wrapper.clientHeight),l=a)}return{from:o,to:Math.max(l,o+1)}}function x(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=L(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",l=0;l<r.length;l++)if(!r[l].hidden){e.options.fixedGutter&&r[l].gutter&&(r[l].gutter.style.left=o);var s=r[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=n+i+"px")}}function C(e){if(!e.options.lineNumbers)return!1;var t=e.doc,r=S(e.options,t.first+t.size-1),n=e.display;if(r.length!=n.lineNumChars){var i=n.measure.appendChild(zo("div",[zo("div",r)],"CodeMirror-linenumber CodeMirror-gutter-elt")),o=i.firstChild.offsetWidth,l=i.offsetWidth-o;return n.lineGutter.style.width="",n.lineNumInnerWidth=Math.max(o,n.lineGutter.offsetWidth-l)+1,n.lineNumWidth=n.lineNumInnerWidth+l,n.lineNumChars=n.lineNumInnerWidth?r.length:-1,n.lineGutter.style.width=n.lineNumWidth+"px",c(e),!0}return!1}function S(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function L(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function k(e,t,r){var n=e.display;this.viewport=t,this.visible=w(n,e.doc,t),this.editorIsHidden=!n.wrapper.offsetWidth,this.wrapperHeight=n.wrapper.clientHeight,this.wrapperWidth=n.wrapper.clientWidth,this.oldDisplayWidth=Kt(e),this.force=r,this.dims=H(e),this.events=[]}function T(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=Vt(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=Vt(e)+"px",t.scrollbarsClipped=!0)}function M(e,t){var r=e.display,n=e.doc;if(t.editorIsHidden)return Pr(e),!1;if(!t.force&&t.visible.from>=r.viewFrom&&t.visible.to<=r.viewTo&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&0==Fr(e))return!1;C(e)&&(Pr(e),t.dims=H(e));var i=n.first+n.size,o=Math.max(t.visible.from-e.options.viewportMargin,n.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);r.viewFrom<o&&o-r.viewFrom<20&&(o=Math.max(n.first,r.viewFrom)),r.viewTo>l&&r.viewTo-l<20&&(l=Math.min(i,r.viewTo)),Ml&&(o=di(e.doc,o),l=pi(e.doc,l));var s=o!=r.viewFrom||l!=r.viewTo||r.lastWrapHeight!=t.wrapperHeight||r.lastWrapWidth!=t.wrapperWidth;Er(e,o,l),r.viewOffset=qi(Ki(e.doc,r.viewFrom)),e.display.mover.style.top=r.viewOffset+"px";var a=Fr(e);if(!s&&0==a&&!t.force&&r.renderedView==r.view&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo))return!1;var u=Ro();return a>4&&(r.lineDiv.style.display="none"),P(e,r.updateLineNumbers,t.dims),a>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,u&&Ro()!=u&&u.offsetHeight&&u.focus(),Eo(r.cursorDiv),Eo(r.selectionDiv),r.gutters.style.height=0,s&&(r.lastWrapHeight=t.wrapperHeight,r.lastWrapWidth=t.wrapperWidth,zt(e,400)),r.updateLineNumbers=null,!0}function A(e,t){for(var r=t.force,n=t.viewport,i=!0;;i=!1){if(i&&e.options.lineWrapping&&t.oldDisplayWidth!=Kt(e))r=!0;else if(r=!1,n&&null!=n.top&&(n={top:Math.min(e.doc.height+Gt(e.display)-jt(e),n.top)}),t.visible=w(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!M(e,t))break;O(e);var o=p(e);Ot(e),W(e,o),y(e,o)}t.signal(e,"update",e),(e.display.viewFrom!=e.display.reportedViewFrom||e.display.viewTo!=e.display.reportedViewTo)&&(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function N(e,t){var r=new k(e,t);if(M(e,r)){O(e),A(e,r);var n=p(e);Ot(e),W(e,n),y(e,n),r.finish()}}function W(e,t){e.display.sizer.style.minHeight=t.docHeight+"px";var r=t.docHeight+e.display.barHeight;e.display.heightForcer.style.top=r+"px",e.display.gutters.style.height=Math.max(r+Vt(e),t.clientHeight)+"px"}function O(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=0;n<t.view.length;n++){var i,o=t.view[n];if(!o.hidden){if(cl&&8>fl){var l=o.node.offsetTop+o.node.offsetHeight;i=l-r,r=l}else{var s=o.node.getBoundingClientRect();i=s.bottom-s.top}var a=o.line.height-i;if(2>i&&(i=gr(t)),(a>.001||-.001>a)&&(_i(o.line,i),D(o.line),o.rest))for(var u=0;u<o.rest.length;u++)D(o.rest[u])}}}function D(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t)e.widgets[t].height=e.widgets[t].node.offsetHeight}function H(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l)r[e.options.gutters[l]]=o.offsetLeft+o.clientLeft+i,n[e.options.gutters[l]]=o.clientWidth;return{fixedPos:L(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function P(e,t,r){function n(t){var r=t.nextSibling;return hl&&xl&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var i=e.display,o=e.options.lineNumbers,l=i.lineDiv,s=l.firstChild,a=i.view,u=i.viewFrom,c=0;c<a.length;c++){var f=a[c];if(f.hidden);else if(f.node&&f.node.parentNode==l){for(;s!=f.node;)s=n(s);var h=o&&null!=t&&u>=t&&f.lineNumber;f.changes&&(Mo(f.changes,"gutter")>-1&&(h=!1),I(e,f,u,r)),h&&(Eo(f.lineNumber),f.lineNumber.appendChild(document.createTextNode(S(e.options,u)))),s=f.node.nextSibling}else{var d=V(e,f,u,r);l.insertBefore(d,s)}u+=f.size}for(;s;)s=n(s)}function I(e,t,r,n){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?R(e,t):"gutter"==o?G(e,t,r,n):"class"==o?B(t):"widget"==o&&U(e,t,n)}t.changes=null}function z(e){return e.node==e.text&&(e.node=zo("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),cl&&8>fl&&(e.node.style.zIndex=2)),e.node}function E(e){var t=e.bgClass?e.bgClass+" "+(e.line.bgClass||""):e.line.bgClass;if(t&&(t+=" CodeMirror-linebackground"),e.background)t?e.background.className=t:(e.background.parentNode.removeChild(e.background),e.background=null);else if(t){var r=z(e);e.background=r.insertBefore(zo("div",null,t),r.firstChild)}}function F(e,t){var r=e.display.externalMeasured;return r&&r.line==t.line?(e.display.externalMeasured=null,t.measure=r.measure,r.built):Oi(e,t)}function R(e,t){var r=t.text.className,n=F(e,t);t.text==t.node&&(t.node=n.pre),t.text.parentNode.replaceChild(n.pre,t.text),t.text=n.pre,n.bgClass!=t.bgClass||n.textClass!=t.textClass?(t.bgClass=n.bgClass,t.textClass=n.textClass,B(t)):r&&(t.text.className=r)}function B(e){E(e),e.line.wrapClass?z(e).className=e.line.wrapClass:e.node!=e.text&&(e.node.className="");var t=e.textClass?e.textClass+" "+(e.line.textClass||""):e.line.textClass;e.text.className=t||""}function G(e,t,r,n){t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null);var i=t.line.gutterMarkers;if(e.options.lineNumbers||i){var o=z(t),l=t.gutter=zo("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?n.fixedPos:-n.gutterTotalWidth)+"px; width: "+n.gutterTotalWidth+"px");if(e.display.input.setUneditable(l),o.insertBefore(l,t.text),t.line.gutterClass&&(l.className+=" "+t.line.gutterClass),!e.options.lineNumbers||i&&i["CodeMirror-linenumbers"]||(t.lineNumber=l.appendChild(zo("div",S(e.options,r),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+n.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),i)for(var s=0;s<e.options.gutters.length;++s){var a=e.options.gutters[s],u=i.hasOwnProperty(a)&&i[a];u&&l.appendChild(zo("div",[u],"CodeMirror-gutter-elt","left: "+n.gutterLeft[a]+"px; width: "+n.gutterWidth[a]+"px"))}}}function U(e,t,r){t.alignable&&(t.alignable=null);for(var n,i=t.node.firstChild;i;i=n){var n=i.nextSibling;"CodeMirror-linewidget"==i.className&&t.node.removeChild(i)}K(e,t,r)}function V(e,t,r,n){var i=F(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),B(t),G(e,t,r,n),K(e,t,n),t.node}function K(e,t,r){if(j(e,t.line,t,r,!0),t.rest)for(var n=0;n<t.rest.length;n++)j(e,t.rest[n],t,r,!1)}function j(e,t,r,n,i){if(t.widgets)for(var o=z(r),l=0,s=t.widgets;l<s.length;++l){var a=s[l],u=zo("div",[a.node],"CodeMirror-linewidget");a.handleMouseEvents||u.setAttribute("cm-ignore-events","true"),X(a,u,r,n),e.display.input.setUneditable(u),i&&a.above?o.insertBefore(u,r.gutter||r.text):o.appendChild(u),mo(a,"redraw")}}function X(e,t,r,n){if(e.noHScroll){(r.alignable||(r.alignable=[])).push(t);var i=n.wrapperWidth;t.style.left=n.fixedPos+"px",e.coverGutter||(i-=n.gutterTotalWidth,t.style.paddingLeft=n.gutterTotalWidth+"px"),t.style.width=i+"px"}e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-n.gutterTotalWidth+"px"))}function _(e){return Al(e.line,e.ch)}function Y(e,t){return Nl(e,t)<0?t:e}function $(e,t){return Nl(e,t)<0?e:t}function q(e){e.state.focused||(e.display.input.focus(),cn(e))}function Z(e){return e.options.readOnly||e.doc.cantEdit}function Q(e,t,r,n){var i=e.doc;e.display.shift=!1,n||(n=i.sel);var o=Vs(t),l=null;e.state.pasteIncoming&&n.ranges.length>1&&(Wl&&Wl.join("\n")==t?l=n.ranges.length%Wl.length==0&&Ao(Wl,Vs):o.length==n.ranges.length&&(l=Ao(o,function(e){return[e]})));for(var s=n.ranges.length-1;s>=0;s--){var a=n.ranges[s],u=a.from(),c=a.to();a.empty()&&(r&&r>0?u=Al(u.line,u.ch-r):e.state.overwrite&&!e.state.pasteIncoming&&(c=Al(c.line,Math.min(Ki(i,c.line).text.length,c.ch+To(o).length))));var f=e.curOp.updateInput,h={from:u,to:c,text:l?l[s%l.length]:o,origin:e.state.pasteIncoming?"paste":e.state.cutIncoming?"cut":"+input"};if(bn(e.doc,h),mo(e,"inputRead",e,h),t&&!e.state.pasteIncoming&&e.options.electricChars&&e.options.smartIndent&&a.head.ch<100&&(!s||n.ranges[s-1].head.line!=a.head.line)){var d=e.getModeAt(a.head),p=Vl(h);if(d.electricChars){for(var g=0;g<d.electricChars.length;g++)if(t.indexOf(d.electricChars.charAt(g))>-1){Hn(e,p.line,"smart");break}}else d.electricInput&&d.electricInput.test(Ki(i,p.line).text.slice(0,p.ch))&&Hn(e,p.line,"smart")}}On(e),e.curOp.updateInput=f,e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=!1}function J(e){for(var t=[],r=[],n=0;n<e.doc.sel.ranges.length;n++){var i=e.doc.sel.ranges[n].head.line,o={anchor:Al(i,0),head:Al(i+1,0)};r.push(o),t.push(e.getRange(o.anchor,o.head))}return{text:t,ranges:r}}function et(e){e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),e.setAttribute("spellcheck","false")}function tt(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new So,this.inaccurateSelection=!1,this.hasSelection=!1}function rt(){var e=zo("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em; outline: none"),t=zo("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return hl?e.style.width="1000px":e.setAttribute("wrap","off"),bl&&(e.style.border="1px solid black"),et(e),t}function nt(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new So,this.gracePeriod=!1}function it(e,t){var r=qt(e,t.line);if(!r||r.hidden)return null;var n=Ki(e.doc,t.line),i=_t(r,n,t.line),o=Zi(n),l="left";if(o){var s=nl(o,t.ch);l=s%2?"right":"left"}var a=Jt(i.map,t.ch,"left");return a.offset="right"==a.collapse?a.end:a.start,a}function ot(e,t){return t&&(e.bad=!0),e}function lt(e,t,r){var n;if(t==e.display.lineDiv){if(n=e.display.lineDiv.childNodes[r],!n)return ot(e.clipPos(Al(e.display.viewTo-1)),!0);t=null,r=0}else for(n=t;;n=n.parentNode){if(!n||n==e.display.lineDiv)return null;if(n.parentNode&&n.parentNode==e.display.lineDiv)break}for(var i=0;i<e.display.view.length;i++){var o=e.display.view[i];if(o.node==n)return st(o,t,r)}}function st(e,t,r){function n(t,r,n){for(var i=-1;i<(c?c.length:0);i++)for(var o=0>i?u.map:c[i],l=0;l<o.length;l+=3){var s=o[l+2];if(s==t||s==r){var a=Yi(0>i?e.line:e.rest[i]),f=o[l]+n;return(0>n||s!=t)&&(f=o[l+(n?1:0)]),Al(a,f)}}}var i=e.text.firstChild,o=!1;if(!t||!zs(i,t))return ot(Al(Yi(e.line),0),!0);if(t==i&&(o=!0,t=i.childNodes[r],r=0,!t)){var l=e.rest?To(e.rest):e.line;return ot(Al(Yi(l),l.text.length),o)}var s=3==t.nodeType?t:null,a=t;for(s||1!=t.childNodes.length||3!=t.firstChild.nodeType||(s=t.firstChild,r&&(r=s.nodeValue.length));a.parentNode!=i;)a=a.parentNode;var u=e.measure,c=u.maps,f=n(s,a,r);if(f)return ot(f,o);for(var h=a.nextSibling,d=s?s.nodeValue.length-r:0;h;h=h.nextSibling){if(f=n(h,h.firstChild,0))return ot(Al(f.line,f.ch-d),o);d+=h.textContent.length}for(var p=a.previousSibling,d=r;p;p=p.previousSibling){if(f=n(p,p.firstChild,-1))return ot(Al(f.line,f.ch+d),o);d+=h.textContent.length}}function at(e,t,r,n,i){function o(e){return function(t){return t.id==e}}function l(t){if(1==t.nodeType){var r=t.getAttribute("cm-text");if(null!=r)return""==r&&(r=t.textContent.replace(/\u200b/g,"")),void(s+=r);var u,c=t.getAttribute("cm-marker");if(c){var f=e.findMarks(Al(n,0),Al(i+1,0),o(+c));return void(f.length&&(u=f[0].find())&&(s+=ji(e.doc,u.from,u.to).join("\n")))}if("false"==t.getAttribute("contenteditable"))return;for(var h=0;h<t.childNodes.length;h++)l(t.childNodes[h]);/^(pre|div|p)$/i.test(t.nodeName)&&(a=!0)}else if(3==t.nodeType){var d=t.nodeValue;if(!d)return;a&&(s+="\n",a=!1),s+=d}}for(var s="",a=!1;l(t),t!=r;)t=t.nextSibling;return s}function ut(e,t){this.ranges=e,this.primIndex=t}function ct(e,t){this.anchor=e,this.head=t}function ft(e,t){var r=e[t];e.sort(function(e,t){return Nl(e.from(),t.from())}),t=Mo(e,r);for(var n=1;n<e.length;n++){var i=e[n],o=e[n-1];if(Nl(o.to(),i.from())>=0){var l=$(o.from(),i.from()),s=Y(o.to(),i.to()),a=o.empty()?i.from()==i.head:o.from()==o.head;t>=n&&--t,e.splice(--n,2,new ct(a?s:l,a?l:s))}}return new ut(e,t)}function ht(e,t){return new ut([new ct(e,t||e)],0)}function dt(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function pt(e,t){if(t.line<e.first)return Al(e.first,0);var r=e.first+e.size-1;return t.line>r?Al(r,Ki(e,r).text.length):gt(t,Ki(e,t.line).text.length)}function gt(e,t){var r=e.ch;return null==r||r>t?Al(e.line,t):0>r?Al(e.line,0):e}function vt(e,t){return t>=e.first&&t<e.first+e.size}function mt(e,t){for(var r=[],n=0;n<t.length;n++)r[n]=pt(e,t[n]);return r}function yt(e,t,r,n){if(e.cm&&e.cm.display.shift||e.extend){var i=t.anchor;if(n){var o=Nl(r,i)<0;o!=Nl(n,i)<0?(i=r,r=n):o!=Nl(r,n)<0&&(r=n)}return new ct(i,r)}return new ct(n||r,r)}function bt(e,t,r,n){kt(e,new ut([yt(e,e.sel.primary(),t,r)],0),n)}function wt(e,t,r){for(var n=[],i=0;i<e.sel.ranges.length;i++)n[i]=yt(e,e.sel.ranges[i],t[i],null);var o=ft(n,e.sel.primIndex);kt(e,o,r)}function xt(e,t,r,n){var i=e.sel.ranges.slice(0);i[t]=r,kt(e,ft(i,e.sel.primIndex),n)}function Ct(e,t,r,n){kt(e,ht(t,r),n)}function St(e,t){var r={ranges:t.ranges,update:function(t){this.ranges=[];for(var r=0;r<t.length;r++)this.ranges[r]=new ct(pt(e,t[r].anchor),pt(e,t[r].head))}};return Cs(e,"beforeSelectionChange",e,r),e.cm&&Cs(e.cm,"beforeSelectionChange",e.cm,r),r.ranges!=t.ranges?ft(r.ranges,r.ranges.length-1):t}function Lt(e,t,r){var n=e.history.done,i=To(n);i&&i.ranges?(n[n.length-1]=t,Tt(e,t,r)):kt(e,t,r)}function kt(e,t,r){Tt(e,t,r),io(e,e.sel,e.cm?e.cm.curOp.id:0/0,r)}function Tt(e,t,r){(xo(e,"beforeSelectionChange")||e.cm&&xo(e.cm,"beforeSelectionChange"))&&(t=St(e,t));var n=r&&r.bias||(Nl(t.primary().head,e.sel.primary().head)<0?-1:1);Mt(e,Nt(e,t,n,!0)),r&&r.scroll===!1||!e.cm||On(e.cm)}function Mt(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=e.cm.curOp.selectionChanged=!0,wo(e.cm)),mo(e,"cursorActivity",e))}function At(e){Mt(e,Nt(e,e.sel,null,!1),Ts)}function Nt(e,t,r,n){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=Wt(e,l.anchor,r,n),a=Wt(e,l.head,r,n);(i||s!=l.anchor||a!=l.head)&&(i||(i=t.ranges.slice(0,o)),i[o]=new ct(s,a))}return i?ft(i,t.primIndex):t}function Wt(e,t,r,n){var i=!1,o=t,l=r||1;e.cantEdit=!1;e:for(;;){var s=Ki(e,o.line);if(s.markedSpans)for(var a=0;a<s.markedSpans.length;++a){var u=s.markedSpans[a],c=u.marker;if((null==u.from||(c.inclusiveLeft?u.from<=o.ch:u.from<o.ch))&&(null==u.to||(c.inclusiveRight?u.to>=o.ch:u.to>o.ch))){if(n&&(Cs(c,"beforeCursorEnter"),c.explicitlyCleared)){if(s.markedSpans){--a;continue}break}if(!c.atomic)continue;var f=c.find(0>l?-1:1);if(0==Nl(f,o)&&(f.ch+=l,f.ch<0?f=f.line>e.first?pt(e,Al(f.line-1)):null:f.ch>s.text.length&&(f=f.line<e.first+e.size-1?Al(f.line+1,0):null),!f)){if(i)return n?(e.cantEdit=!0,Al(e.first,0)):Wt(e,t,r,!0);i=!0,f=t,l=-l}o=f;continue e}}return o}}function Ot(e){e.display.input.showSelection(e.display.input.prepareSelection())}function Dt(e,t){for(var r=e.doc,n={},i=n.cursors=document.createDocumentFragment(),o=n.selection=document.createDocumentFragment(),l=0;l<r.sel.ranges.length;l++)if(t!==!1||l!=r.sel.primIndex){var s=r.sel.ranges[l],a=s.empty();(a||e.options.showCursorWhenSelecting)&&Ht(e,s,i),a||Pt(e,s,o)}return n}function Ht(e,t,r){var n=cr(e,t.head,"div",null,null,!e.options.singleCursorHeightPerLine),i=r.appendChild(zo("div"," ","CodeMirror-cursor"));if(i.style.left=n.left+"px",i.style.top=n.top+"px",i.style.height=Math.max(0,n.bottom-n.top)*e.options.cursorHeight+"px",n.other){var o=r.appendChild(zo("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));o.style.display="",o.style.left=n.other.left+"px",o.style.top=n.other.top+"px",o.style.height=.85*(n.other.bottom-n.other.top)+"px"}}function Pt(e,t,r){function n(e,t,r,n){0>t&&(t=0),t=Math.round(t),n=Math.round(n),s.appendChild(zo("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px; top: "+t+"px; width: "+(null==r?c-e:r)+"px; height: "+(n-t)+"px"))}function i(t,r,i){function o(r,n){return ur(e,Al(t,r),"div",f,n)}var s,a,f=Ki(l,t),h=f.text.length;return Yo(Zi(f),r||0,null==i?h:i,function(e,t,l){var f,d,p,g=o(e,"left");if(e==t)f=g,d=p=g.left;else{if(f=o(t-1,"right"),"rtl"==l){var v=g;g=f,f=v}d=g.left,p=f.right}null==r&&0==e&&(d=u),f.top-g.top>3&&(n(d,g.top,null,g.bottom),d=u,g.bottom<f.top&&n(d,g.bottom,null,f.top)),null==i&&t==h&&(p=c),(!s||g.top<s.top||g.top==s.top&&g.left<s.left)&&(s=g),(!a||f.bottom>a.bottom||f.bottom==a.bottom&&f.right>a.right)&&(a=f),u+1>d&&(d=u),n(d,f.top,p-d,f.bottom)}),{start:s,end:a}}var o=e.display,l=e.doc,s=document.createDocumentFragment(),a=Ut(e.display),u=a.left,c=Math.max(o.sizerWidth,Kt(e)-o.sizer.offsetLeft)-a.right,f=t.from(),h=t.to();if(f.line==h.line)i(f.line,f.ch,h.ch);else{var d=Ki(l,f.line),p=Ki(l,h.line),g=fi(d)==fi(p),v=i(f.line,f.ch,g?d.text.length+1:null).end,m=i(h.line,g?0:null,h.ch).start;g&&(v.top<m.top-2?(n(v.right,v.top,null,v.bottom),n(u,m.top,m.left,m.bottom)):n(v.right,v.top,m.left-v.right,v.bottom)),v.bottom<m.top&&n(u,v.bottom,null,m.top)}r.appendChild(s)}function It(e){if(e.state.focused){var t=e.display;clearInterval(t.blinker);var r=!0;t.cursorDiv.style.visibility="",e.options.cursorBlinkRate>0?t.blinker=setInterval(function(){t.cursorDiv.style.visibility=(r=!r)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function zt(e,t){e.doc.mode.startState&&e.doc.frontier<e.display.viewTo&&e.state.highlight.set(t,Do(Et,e))}function Et(e){var t=e.doc;if(t.frontier<t.first&&(t.frontier=t.first),!(t.frontier>=e.display.viewTo)){var r=+new Date+e.options.workTime,n=Ql(t.mode,Rt(e,t.frontier)),i=[];t.iter(t.frontier,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(t.frontier>=e.display.viewFrom){var l=o.styles,s=Mi(e,o,n,!0);o.styles=s.styles;var a=o.styleClasses,u=s.classes;u?o.styleClasses=u:a&&(o.styleClasses=null);for(var c=!l||l.length!=o.styles.length||a!=u&&(!a||!u||a.bgClass!=u.bgClass||a.textClass!=u.textClass),f=0;!c&&f<l.length;++f)c=l[f]!=o.styles[f];c&&i.push(t.frontier),o.stateAfter=Ql(t.mode,n)}else Ni(e,o.text,n),o.stateAfter=t.frontier%5==0?Ql(t.mode,n):null;return++t.frontier,+new Date>r?(zt(e,e.options.workDelay),!0):void 0}),i.length&&Tr(e,function(){for(var t=0;t<i.length;t++)Hr(e,i[t],"text")})}}function Ft(e,t,r){for(var n,i,o=e.doc,l=r?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>l;--s){if(s<=o.first)return o.first;var a=Ki(o,s-1);if(a.stateAfter&&(!r||s<=o.frontier))return s;var u=Ns(a.text,null,e.options.tabSize);(null==i||n>u)&&(i=s-1,n=u)}return i}function Rt(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return!0;var o=Ft(e,t,r),l=o>n.first&&Ki(n,o-1).stateAfter;return l=l?Ql(n.mode,l):Jl(n.mode),n.iter(o,t,function(r){Ni(e,r.text,l);var s=o==t-1||o%5==0||o>=i.viewFrom&&o<i.viewTo;r.stateAfter=s?Ql(n.mode,l):null,++o}),r&&(n.frontier=o),l}function Bt(e){return e.lineSpace.offsetTop}function Gt(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function Ut(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=Fo(e.measure,zo("pre","x")),r=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,n={left:parseInt(r.paddingLeft),right:parseInt(r.paddingRight)};return isNaN(n.left)||isNaN(n.right)||(e.cachedPaddingH=n),n}function Vt(e){return Ls-e.display.nativeBarWidth}function Kt(e){return e.display.scroller.clientWidth-Vt(e)-e.display.barWidth}function jt(e){return e.display.scroller.clientHeight-Vt(e)-e.display.barHeight}function Xt(e,t,r){var n=e.options.lineWrapping,i=n&&Kt(e);if(!t.measure.heights||n&&t.measure.width!=i){var o=t.measure.heights=[];if(n){t.measure.width=i;for(var l=t.text.firstChild.getClientRects(),s=0;s<l.length-1;s++){var a=l[s],u=l[s+1];Math.abs(a.bottom-u.bottom)>2&&o.push((a.bottom+u.top)/2-r.top)}}o.push(r.bottom-r.top)}}function _t(e,t,r){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var n=0;n<e.rest.length;n++)if(e.rest[n]==t)return{map:e.measure.maps[n],cache:e.measure.caches[n]};for(var n=0;n<e.rest.length;n++)if(Yi(e.rest[n])>r)return{map:e.measure.maps[n],cache:e.measure.caches[n],before:!0}}function Yt(e,t){t=fi(t);var r=Yi(t),n=e.display.externalMeasured=new Wr(e.doc,t,r);n.lineN=r;var i=n.built=Oi(e,n);return n.text=i.pre,Fo(e.display.lineMeasure,i.pre),n}function $t(e,t,r,n){return Qt(e,Zt(e,t),r,n)}function qt(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[Ir(e,t)];var r=e.display.externalMeasured;return r&&t>=r.lineN&&t<r.lineN+r.size?r:void 0}function Zt(e,t){var r=Yi(t),n=qt(e,r);n&&!n.text?n=null:n&&n.changes&&I(e,n,r,H(e)),n||(n=Yt(e,t));var i=_t(n,t,r);return{line:t,view:n,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function Qt(e,t,r,n,i){t.before&&(r=-1);var o,l=r+(n||"");return t.cache.hasOwnProperty(l)?o=t.cache[l]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||(Xt(e,t.view,t.rect),t.hasHeights=!0),o=er(e,t,r,n),o.bogus||(t.cache[l]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}function Jt(e,t,r){for(var n,i,o,l,s=0;s<e.length;s+=3){var a=e[s],u=e[s+1];if(a>t?(i=0,o=1,l="left"):u>t?(i=t-a,o=i+1):(s==e.length-3||t==u&&e[s+3]>t)&&(o=u-a,i=o-1,t>=u&&(l="right")),null!=i){if(n=e[s+2],a==u&&r==(n.insertLeft?"left":"right")&&(l=r),"left"==r&&0==i)for(;s&&e[s-2]==e[s-3]&&e[s-1].insertLeft;)n=e[(s-=3)+2],l="left";if("right"==r&&i==u-a)for(;s<e.length-3&&e[s+3]==e[s+4]&&!e[s+5].insertLeft;)n=e[(s+=3)+2],l="right";break}}return{node:n,start:i,end:o,collapse:l,coverStart:a,coverEnd:u}}function er(e,t,r,n){var i,o=Jt(t.map,r,n),l=o.node,s=o.start,a=o.end,u=o.collapse;if(3==l.nodeType){for(var c=0;4>c;c++){for(;s&&Io(t.line.text.charAt(o.coverStart+s));)--s;for(;o.coverStart+a<o.coverEnd&&Io(t.line.text.charAt(o.coverStart+a));)++a;if(cl&&9>fl&&0==s&&a==o.coverEnd-o.coverStart)i=l.parentNode.getBoundingClientRect();else if(cl&&e.options.lineWrapping){var f=Ds(l,s,a).getClientRects();i=f.length?f["right"==n?f.length-1:0]:Pl}else i=Ds(l,s,a).getBoundingClientRect()||Pl;if(i.left||i.right||0==s)break;a=s,s-=1,u="right"}cl&&11>fl&&(i=tr(e.display.measure,i))}else{s>0&&(u=n="right");var f;i=e.options.lineWrapping&&(f=l.getClientRects()).length>1?f["right"==n?f.length-1:0]:l.getBoundingClientRect()}if(cl&&9>fl&&!s&&(!i||!i.left&&!i.right)){var h=l.parentNode.getClientRects()[0];i=h?{left:h.left,right:h.left+vr(e.display),top:h.top,bottom:h.bottom}:Pl}for(var d=i.top-t.rect.top,p=i.bottom-t.rect.top,g=(d+p)/2,v=t.view.measure.heights,c=0;c<v.length-1&&!(g<v[c]);c++);var m=c?v[c-1]:0,y=v[c],b={left:("right"==u?i.right:i.left)-t.rect.left,right:("left"==u?i.left:i.right)-t.rect.left,top:m,bottom:y};return i.left||i.right||(b.bogus=!0),e.options.singleCursorHeightPerLine||(b.rtop=d,b.rbottom=p),b
2
- }function tr(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!_o(e))return t;var r=screen.logicalXDPI/screen.deviceXDPI,n=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*r,right:t.right*r,top:t.top*n,bottom:t.bottom*n}}function rr(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function nr(e){e.display.externalMeasure=null,Eo(e.display.lineMeasure);for(var t=0;t<e.display.view.length;t++)rr(e.display.view[t])}function ir(e){nr(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function or(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function lr(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function sr(e,t,r,n){if(t.widgets)for(var i=0;i<t.widgets.length;++i)if(t.widgets[i].above){var o=yi(t.widgets[i]);r.top+=o,r.bottom+=o}if("line"==n)return r;n||(n="local");var l=qi(t);if("local"==n?l+=Bt(e.display):l-=e.display.viewOffset,"page"==n||"window"==n){var s=e.display.lineSpace.getBoundingClientRect();l+=s.top+("window"==n?0:lr());var a=s.left+("window"==n?0:or());r.left+=a,r.right+=a}return r.top+=l,r.bottom+=l,r}function ar(e,t,r){if("div"==r)return t;var n=t.left,i=t.top;if("page"==r)n-=or(),i-=lr();else if("local"==r||!r){var o=e.display.sizer.getBoundingClientRect();n+=o.left,i+=o.top}var l=e.display.lineSpace.getBoundingClientRect();return{left:n-l.left,top:i-l.top}}function ur(e,t,r,n,i){return n||(n=Ki(e.doc,t.line)),sr(e,n,$t(e,n,t.ch,i),r)}function cr(e,t,r,n,i,o){function l(t,l){var s=Qt(e,i,t,l?"right":"left",o);return l?s.left=s.right:s.right=s.left,sr(e,n,s,r)}function s(e,t){var r=a[t],n=r.level%2;return e==$o(r)&&t&&r.level<a[t-1].level?(r=a[--t],e=qo(r)-(r.level%2?0:1),n=!0):e==qo(r)&&t<a.length-1&&r.level<a[t+1].level&&(r=a[++t],e=$o(r)-r.level%2,n=!1),n&&e==r.to&&e>r.from?l(e-1):l(e,n)}n=n||Ki(e.doc,t.line),i||(i=Zt(e,n));var a=Zi(n),u=t.ch;if(!a)return l(u);var c=nl(a,u),f=s(u,c);return null!=Ys&&(f.other=s(u,Ys)),f}function fr(e,t){var r=0,t=pt(e.doc,t);e.options.lineWrapping||(r=vr(e.display)*t.ch);var n=Ki(e.doc,t.line),i=qi(n)+Bt(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function hr(e,t,r,n){var i=Al(e,t);return i.xRel=n,r&&(i.outside=!0),i}function dr(e,t,r){var n=e.doc;if(r+=e.display.viewOffset,0>r)return hr(n.first,0,!0,-1);var i=$i(n,r),o=n.first+n.size-1;if(i>o)return hr(n.first+n.size-1,Ki(n,o).text.length,!0,1);0>t&&(t=0);for(var l=Ki(n,i);;){var s=pr(e,l,i,t,r),a=ui(l),u=a&&a.find(0,!0);if(!a||!(s.ch>u.from.ch||s.ch==u.from.ch&&s.xRel>0))return s;i=Yi(l=u.to.line)}}function pr(e,t,r,n,i){function o(n){var i=cr(e,Al(r,n),"line",t,u);return s=!0,l>i.bottom?i.left-a:l<i.top?i.left+a:(s=!1,i.left)}var l=i-qi(t),s=!1,a=2*e.display.wrapper.clientWidth,u=Zt(e,t),c=Zi(t),f=t.text.length,h=Zo(t),d=Qo(t),p=o(h),g=s,v=o(d),m=s;if(n>v)return hr(r,d,m,1);for(;;){if(c?d==h||d==ol(t,h,1):1>=d-h){for(var y=p>n||v-n>=n-p?h:d,b=n-(y==h?p:v);Io(t.text.charAt(y));)++y;var w=hr(r,y,y==h?g:m,-1>b?-1:b>1?1:0);return w}var x=Math.ceil(f/2),C=h+x;if(c){C=h;for(var S=0;x>S;++S)C=ol(t,C,1)}var L=o(C);L>n?(d=C,v=L,(m=s)&&(v+=1e3),f=x):(h=C,p=L,g=s,f-=x)}}function gr(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Ol){Ol=zo("pre");for(var t=0;49>t;++t)Ol.appendChild(document.createTextNode("x")),Ol.appendChild(zo("br"));Ol.appendChild(document.createTextNode("x"))}Fo(e.measure,Ol);var r=Ol.offsetHeight/50;return r>3&&(e.cachedTextHeight=r),Eo(e.measure),r||1}function vr(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=zo("span","xxxxxxxxxx"),r=zo("pre",[t]);Fo(e.measure,r);var n=t.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function mr(e){e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,id:++zl},Il?Il.ops.push(e.curOp):e.curOp.ownsGroup=Il={ops:[e.curOp],delayedCallbacks:[]}}function yr(e){var t=e.delayedCallbacks,r=0;do{for(;r<t.length;r++)t[r]();for(var n=0;n<e.ops.length;n++){var i=e.ops[n];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++](i.cm)}}while(r<t.length)}function br(e){var t=e.curOp,r=t.ownsGroup;if(r)try{yr(r)}finally{Il=null;for(var n=0;n<r.ops.length;n++)r.ops[n].cm.curOp=null;wr(r)}}function wr(e){for(var t=e.ops,r=0;r<t.length;r++)xr(t[r]);for(var r=0;r<t.length;r++)Cr(t[r]);for(var r=0;r<t.length;r++)Sr(t[r]);for(var r=0;r<t.length;r++)Lr(t[r]);for(var r=0;r<t.length;r++)kr(t[r])}function xr(e){var t=e.cm,r=t.display;T(t),e.updateMaxLine&&h(t),e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<r.viewFrom||e.scrollToPos.to.line>=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new k(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Cr(e){e.updatedDisplay=e.mustUpdate&&M(e.cm,e.update)}function Sr(e){var t=e.cm,r=t.display;e.updatedDisplay&&O(t),e.barMeasure=p(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=$t(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+Vt(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Kt(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection())}function Lr(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&Qr(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1),e.preparedSelection&&t.display.input.showSelection(e.preparedSelection),e.updatedDisplay&&W(t,e.barMeasure),(e.updatedDisplay||e.startHeight!=t.doc.height)&&y(t,e.barMeasure),e.selectionChanged&&It(t),t.state.focused&&e.updateInput&&t.display.input.reset(e.typing)}function kr(e){var t=e.cm,r=t.display,n=t.doc;if(e.updatedDisplay&&A(t,e.update),null==r.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(r.wheelStartX=r.wheelStartY=null),null==e.scrollTop||r.scroller.scrollTop==e.scrollTop&&!e.forceScroll||(n.scrollTop=Math.max(0,Math.min(r.scroller.scrollHeight-r.scroller.clientHeight,e.scrollTop)),r.scrollbars.setScrollTop(n.scrollTop),r.scroller.scrollTop=n.scrollTop),null==e.scrollLeft||r.scroller.scrollLeft==e.scrollLeft&&!e.forceScroll||(n.scrollLeft=Math.max(0,Math.min(r.scroller.scrollWidth-Kt(t),e.scrollLeft)),r.scrollbars.setScrollLeft(n.scrollLeft),r.scroller.scrollLeft=n.scrollLeft,x(t)),e.scrollToPos){var i=Mn(t,pt(n,e.scrollToPos.from),pt(n,e.scrollToPos.to),e.scrollToPos.margin);e.scrollToPos.isCursor&&t.state.focused&&Tn(t,i)}var o=e.maybeHiddenMarkers,l=e.maybeUnhiddenMarkers;if(o)for(var s=0;s<o.length;++s)o[s].lines.length||Cs(o[s],"hide");if(l)for(var s=0;s<l.length;++s)l[s].lines.length&&Cs(l[s],"unhide");r.wrapper.offsetHeight&&(n.scrollTop=t.display.scroller.scrollTop),e.changeObjs&&Cs(t,"changes",t,e.changeObjs),e.update&&e.update.finish()}function Tr(e,t){if(e.curOp)return t();mr(e);try{return t()}finally{br(e)}}function Mr(e,t){return function(){if(e.curOp)return t.apply(e,arguments);mr(e);try{return t.apply(e,arguments)}finally{br(e)}}}function Ar(e){return function(){if(this.curOp)return e.apply(this,arguments);mr(this);try{return e.apply(this,arguments)}finally{br(this)}}}function Nr(e){return function(){var t=this.cm;if(!t||t.curOp)return e.apply(this,arguments);mr(t);try{return e.apply(this,arguments)}finally{br(t)}}}function Wr(e,t,r){this.line=t,this.rest=hi(t),this.size=this.rest?Yi(To(this.rest))-r+1:1,this.node=this.text=null,this.hidden=gi(e,t)}function Or(e,t,r){for(var n,i=[],o=t;r>o;o=n){var l=new Wr(e.doc,Ki(e.doc,o),o);n=o+l.size,i.push(l)}return i}function Dr(e,t,r,n){null==t&&(t=e.doc.first),null==r&&(r=e.doc.first+e.doc.size),n||(n=0);var i=e.display;if(n&&r<i.viewTo&&(null==i.updateLineNumbers||i.updateLineNumbers>t)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Ml&&di(e.doc,t)<i.viewTo&&Pr(e);else if(r<=i.viewFrom)Ml&&pi(e.doc,r+n)>i.viewFrom?Pr(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)Pr(e);else if(t<=i.viewFrom){var o=zr(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):Pr(e)}else if(r>=i.viewTo){var o=zr(e,t,t,-1);o?(i.view=i.view.slice(0,o.index),i.viewTo=o.lineN):Pr(e)}else{var l=zr(e,t,t,-1),s=zr(e,r,r+n,1);l&&s?(i.view=i.view.slice(0,l.index).concat(Or(e,l.lineN,s.lineN)).concat(i.view.slice(s.index)),i.viewTo+=n):Pr(e)}var a=i.externalMeasured;a&&(r<a.lineN?a.lineN+=n:t<a.lineN+a.size&&(i.externalMeasured=null))}function Hr(e,t,r){e.curOp.viewChanged=!0;var n=e.display,i=e.display.externalMeasured;if(i&&t>=i.lineN&&t<i.lineN+i.size&&(n.externalMeasured=null),!(t<n.viewFrom||t>=n.viewTo)){var o=n.view[Ir(e,t)];if(null!=o.node){var l=o.changes||(o.changes=[]);-1==Mo(l,r)&&l.push(r)}}}function Pr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function Ir(e,t){if(t>=e.display.viewTo)return null;if(t-=e.display.viewFrom,0>t)return null;for(var r=e.display.view,n=0;n<r.length;n++)if(t-=r[n].size,0>t)return n}function zr(e,t,r,n){var i,o=Ir(e,t),l=e.display.view;if(!Ml||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var s=0,a=e.display.viewFrom;o>s;s++)a+=l[s].size;if(a!=t){if(n>0){if(o==l.length-1)return null;i=a+l[o].size-t,o++}else i=a-t;t+=i,r+=i}for(;di(e.doc,r)!=r;){if(o==(0>n?0:l.length-1))return null;r+=n*l[o-(0>n?1:0)].size,o+=n}return{index:o,lineN:r}}function Er(e,t,r){var n=e.display,i=n.view;0==i.length||t>=n.viewTo||r<=n.viewFrom?(n.view=Or(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=Or(e,t,n.viewFrom).concat(n.view):n.viewFrom<t&&(n.view=n.view.slice(Ir(e,t))),n.viewFrom=t,n.viewTo<r?n.view=n.view.concat(Or(e,n.viewTo,r)):n.viewTo>r&&(n.view=n.view.slice(0,Ir(e,r)))),n.viewTo=r}function Fr(e){for(var t=e.display.view,r=0,n=0;n<t.length;n++){var i=t[n];i.hidden||i.node&&!i.changes||++r}return r}function Rr(e){function t(){o.activeTouch&&(l=setTimeout(function(){o.activeTouch=null},1e3),s=o.activeTouch,s.end=+new Date)}function r(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}function n(e,t){if(null==t.left)return!0;var r=t.left-e.left,n=t.top-e.top;return r*r+n*n>400}function i(t){bo(e,t)||bs(t)}var o=e.display;ws(o.scroller,"mousedown",Mr(e,Vr)),cl&&11>fl?ws(o.scroller,"dblclick",Mr(e,function(t){if(!bo(e,t)){var r=Ur(e,t);if(r&&!Yr(e,t)&&!Gr(e.display,t)){ms(t);var n=e.findWordAt(r);bt(e.doc,n.anchor,n.head)}}})):ws(o.scroller,"dblclick",function(t){bo(e,t)||ms(t)}),kl||ws(o.scroller,"contextmenu",function(t){hn(e,t)});var l,s={end:0};ws(o.scroller,"touchstart",function(e){if(!r(e)){clearTimeout(l);var t=+new Date;o.activeTouch={start:t,moved:!1,prev:t-s.end<=300?s:null},1==e.touches.length&&(o.activeTouch.left=e.touches[0].pageX,o.activeTouch.top=e.touches[0].pageY)}}),ws(o.scroller,"touchmove",function(){o.activeTouch&&(o.activeTouch.moved=!0)}),ws(o.scroller,"touchend",function(r){var i=o.activeTouch;if(i&&!Gr(o,r)&&null!=i.left&&!i.moved&&new Date-i.start<300){var l,s=e.coordsChar(o.activeTouch,"page");l=!i.prev||n(i,i.prev)?new ct(s,s):!i.prev.prev||n(i,i.prev.prev)?e.findWordAt(s):new ct(Al(s.line,0),pt(e.doc,Al(s.line+1,0))),e.setSelection(l.anchor,l.head),e.focus(),ms(r)}t()}),ws(o.scroller,"touchcancel",t),ws(o.scroller,"scroll",function(){o.scroller.clientHeight&&(Zr(e,o.scroller.scrollTop),Qr(e,o.scroller.scrollLeft,!0),Cs(e,"scroll",e))}),ws(o.scroller,"mousewheel",function(t){Jr(e,t)}),ws(o.scroller,"DOMMouseScroll",function(t){Jr(e,t)}),ws(o.wrapper,"scroll",function(){o.wrapper.scrollTop=o.wrapper.scrollLeft=0}),e.options.dragDrop&&(ws(o.scroller,"dragstart",function(t){qr(e,t)}),ws(o.scroller,"dragenter",i),ws(o.scroller,"dragover",i),ws(o.scroller,"drop",Mr(e,$r)));var a=o.input.getField();ws(a,"keyup",function(t){an.call(e,t)}),ws(a,"keydown",Mr(e,ln)),ws(a,"keypress",Mr(e,un)),ws(a,"focus",Do(cn,e)),ws(a,"blur",Do(fn,e))}function Br(e){var t=e.display;(t.lastWrapHeight!=t.wrapper.clientHeight||t.lastWrapWidth!=t.wrapper.clientWidth)&&(t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize())}function Gr(e,t){for(var r=go(t);r!=e.wrapper;r=r.parentNode)if(!r||1==r.nodeType&&"true"==r.getAttribute("cm-ignore-events")||r.parentNode==e.sizer&&r!=e.mover)return!0}function Ur(e,t,r,n){var i=e.display;if(!r&&"true"==go(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(t){return null}var a,u=dr(e,o,l);if(n&&1==u.xRel&&(a=Ki(e.doc,u.line).text).length==u.ch){var c=Ns(a,a.length,e.options.tabSize)-a.length;u=Al(u.line,Math.max(0,Math.round((o-Ut(e.display).left)/vr(e.display))-c))}return u}function Vr(e){var t=this,r=t.display;if(!(r.activeTouch&&r.input.supportsTouch()||bo(t,e))){if(r.shift=e.shiftKey,Gr(r,e))return void(hl||(r.scroller.draggable=!1,setTimeout(function(){r.scroller.draggable=!0},100)));if(!Yr(t,e)){var n=Ur(t,e);switch(window.focus(),vo(e)){case 1:n?Kr(t,e,n):go(e)==r.scroller&&ms(e);break;case 2:hl&&(t.state.lastMiddleDown=+new Date),n&&bt(t.doc,n),setTimeout(function(){r.input.focus()},20),ms(e);break;case 3:kl&&hn(t,e)}}}}function Kr(e,t,r){cl?setTimeout(Do(q,e),0):q(e);var n,i=+new Date;Hl&&Hl.time>i-400&&0==Nl(Hl.pos,r)?n="triple":Dl&&Dl.time>i-400&&0==Nl(Dl.pos,r)?(n="double",Hl={time:i,pos:r}):(n="single",Dl={time:i,pos:r});var o,l=e.doc.sel,s=xl?t.metaKey:t.ctrlKey;e.options.dragDrop&&Us&&!Z(e)&&"single"==n&&(o=l.contains(r))>-1&&!l.ranges[o].empty()?jr(e,t,r,s):Xr(e,t,r,n,s)}function jr(e,t,r,n){var i=e.display,o=Mr(e,function(l){hl&&(i.scroller.draggable=!1),e.state.draggingText=!1,xs(document,"mouseup",o),xs(i.scroller,"drop",o),Math.abs(t.clientX-l.clientX)+Math.abs(t.clientY-l.clientY)<10&&(ms(l),n||bt(e.doc,r),hl||cl&&9==fl?setTimeout(function(){document.body.focus(),i.input.focus()},20):i.input.focus())});hl&&(i.scroller.draggable=!0),e.state.draggingText=o,i.scroller.dragDrop&&i.scroller.dragDrop(),ws(document,"mouseup",o),ws(i.scroller,"drop",o)}function Xr(e,t,r,n,i){function o(t){if(0!=Nl(v,t))if(v=t,"rect"==n){for(var i=[],o=e.options.tabSize,l=Ns(Ki(u,r.line).text,r.ch,o),s=Ns(Ki(u,t.line).text,t.ch,o),a=Math.min(l,s),d=Math.max(l,s),p=Math.min(r.line,t.line),g=Math.min(e.lastLine(),Math.max(r.line,t.line));g>=p;p++){var m=Ki(u,p).text,y=Lo(m,a,o);a==d?i.push(new ct(Al(p,y),Al(p,y))):m.length>y&&i.push(new ct(Al(p,y),Al(p,Lo(m,d,o))))}i.length||i.push(new ct(r,r)),kt(u,ft(h.ranges.slice(0,f).concat(i),f),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b=c,w=b.anchor,x=t;if("single"!=n){if("double"==n)var C=e.findWordAt(t);else var C=new ct(Al(t.line,0),pt(u,Al(t.line+1,0)));Nl(C.anchor,w)>0?(x=C.head,w=$(b.from(),C.anchor)):(x=C.anchor,w=Y(b.to(),C.head))}var i=h.ranges.slice(0);i[f]=new ct(pt(u,w),x),kt(u,ft(i,f),Ms)}}function l(t){var r=++y,i=Ur(e,t,!0,"rect"==n);if(i)if(0!=Nl(i,v)){q(e),o(i);var s=w(a,u);(i.line>=s.to||i.line<s.from)&&setTimeout(Mr(e,function(){y==r&&l(t)}),150)}else{var c=t.clientY<m.top?-20:t.clientY>m.bottom?20:0;c&&setTimeout(Mr(e,function(){y==r&&(a.scroller.scrollTop+=c,l(t))}),50)}}function s(e){y=1/0,ms(e),a.input.focus(),xs(document,"mousemove",b),xs(document,"mouseup",x),u.history.lastSelOrigin=null}var a=e.display,u=e.doc;ms(t);var c,f,h=u.sel,d=h.ranges;if(i&&!t.shiftKey?(f=u.sel.contains(r),c=f>-1?d[f]:new ct(r,r)):c=u.sel.primary(),t.altKey)n="rect",i||(c=new ct(r,r)),r=Ur(e,t,!0,!0),f=-1;else if("double"==n){var p=e.findWordAt(r);c=e.display.shift||u.extend?yt(u,c,p.anchor,p.head):p}else if("triple"==n){var g=new ct(Al(r.line,0),pt(u,Al(r.line+1,0)));c=e.display.shift||u.extend?yt(u,c,g.anchor,g.head):g}else c=yt(u,c,r);i?-1==f?(f=d.length,kt(u,ft(d.concat([c]),f),{scroll:!1,origin:"*mouse"})):d.length>1&&d[f].empty()&&"single"==n?(kt(u,ft(d.slice(0,f).concat(d.slice(f+1)),0)),h=u.sel):xt(u,f,c,Ms):(f=0,kt(u,new ut([c],0),Ms),h=u.sel);var v=r,m=a.wrapper.getBoundingClientRect(),y=0,b=Mr(e,function(e){vo(e)?l(e):s(e)}),x=Mr(e,s);ws(document,"mousemove",b),ws(document,"mouseup",x)}function _r(e,t,r,n,i){try{var o=t.clientX,l=t.clientY}catch(t){return!1}if(o>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;n&&ms(t);var s=e.display,a=s.lineDiv.getBoundingClientRect();if(l>a.bottom||!xo(e,r))return po(t);l-=a.top-s.viewOffset;for(var u=0;u<e.options.gutters.length;++u){var c=s.gutters.childNodes[u];if(c&&c.getBoundingClientRect().right>=o){var f=$i(e.doc,l),h=e.options.gutters[u];return i(e,r,e,f,h,t),po(t)}}}function Yr(e,t){return _r(e,t,"gutterClick",!0,mo)}function $r(e){var t=this;if(!bo(t,e)&&!Gr(t.display,e)){ms(e),cl&&(El=+new Date);var r=Ur(t,e,!0),n=e.dataTransfer.files;if(r&&!Z(t))if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),l=0,s=function(e,n){var s=new FileReader;s.onload=Mr(t,function(){if(o[n]=s.result,++l==i){r=pt(t.doc,r);var e={from:r,to:r,text:Vs(o.join("\n")),origin:"paste"};bn(t.doc,e),Lt(t.doc,ht(r,Vl(e)))}}),s.readAsText(e)},a=0;i>a;++a)s(n[a],a);else{if(t.state.draggingText&&t.doc.sel.contains(r)>-1)return t.state.draggingText(e),void setTimeout(function(){t.display.input.focus()},20);try{var o=e.dataTransfer.getData("Text");if(o){if(t.state.draggingText&&!(xl?e.metaKey:e.ctrlKey))var u=t.listSelections();if(Tt(t.doc,ht(r,r)),u)for(var a=0;a<u.length;++a)kn(t.doc,"",u[a].anchor,u[a].head,"drag");t.replaceSelection(o,"around","paste"),t.display.input.focus()}}catch(e){}}}}function qr(e,t){if(cl&&(!e.state.draggingText||+new Date-El<100))return void bs(t);if(!bo(e,t)&&!Gr(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.setDragImage&&!vl)){var r=zo("img",null,null,"position: fixed; left: 0; top: 0;");r.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",gl&&(r.width=r.height=1,e.display.wrapper.appendChild(r),r._top=r.offsetTop),t.dataTransfer.setDragImage(r,0,0),gl&&r.parentNode.removeChild(r)}}function Zr(e,t){Math.abs(e.doc.scrollTop-t)<2||(e.doc.scrollTop=t,sl||N(e,{top:t}),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t),e.display.scrollbars.setScrollTop(t),sl&&N(e),zt(e,100))}function Qr(e,t,r){(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)||(t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),e.doc.scrollLeft=t,x(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Jr(e,t){var r=Bl(t),n=r.x,i=r.y,o=e.display,l=o.scroller;if(n&&l.scrollWidth>l.clientWidth||i&&l.scrollHeight>l.clientHeight){if(i&&xl&&hl)e:for(var s=t.target,a=o.view;s!=l;s=s.parentNode)for(var u=0;u<a.length;u++)if(a[u].node==s){e.display.currentWheelTarget=s;break e}if(n&&!sl&&!gl&&null!=Rl)return i&&Zr(e,Math.max(0,Math.min(l.scrollTop+i*Rl,l.scrollHeight-l.clientHeight))),Qr(e,Math.max(0,Math.min(l.scrollLeft+n*Rl,l.scrollWidth-l.clientWidth))),ms(t),void(o.wheelStartX=null);if(i&&null!=Rl){var c=i*Rl,f=e.doc.scrollTop,h=f+o.wrapper.clientHeight;0>c?f=Math.max(0,f+c-50):h=Math.min(e.doc.height,h+c+50),N(e,{top:f,bottom:h})}20>Fl&&(null==o.wheelStartX?(o.wheelStartX=l.scrollLeft,o.wheelStartY=l.scrollTop,o.wheelDX=n,o.wheelDY=i,setTimeout(function(){if(null!=o.wheelStartX){var e=l.scrollLeft-o.wheelStartX,t=l.scrollTop-o.wheelStartY,r=t&&o.wheelDY&&t/o.wheelDY||e&&o.wheelDX&&e/o.wheelDX;o.wheelStartX=o.wheelStartY=null,r&&(Rl=(Rl*Fl+r)/(Fl+1),++Fl)}},200)):(o.wheelDX+=n,o.wheelDY+=i))}}function en(e,t,r){if("string"==typeof t&&(t=es[t],!t))return!1;e.display.input.ensurePolled();var n=e.display.shift,i=!1;try{Z(e)&&(e.state.suppressEdits=!0),r&&(e.display.shift=!1),i=t(e)!=ks}finally{e.display.shift=n,e.state.suppressEdits=!1}return i}function tn(e,t,r){for(var n=0;n<e.state.keyMaps.length;n++){var i=rs(t,e.state.keyMaps[n],r,e);if(i)return i}return e.options.extraKeys&&rs(t,e.options.extraKeys,r,e)||rs(t,e.options.keyMap,r,e)}function rn(e,t,r,n){var i=e.state.keySeq;if(i){if(ns(t))return"handled";Gl.set(50,function(){e.state.keySeq==i&&(e.state.keySeq=null,e.display.input.reset())}),t=i+" "+t}var o=tn(e,t,n);return"multi"==o&&(e.state.keySeq=t),"handled"==o&&mo(e,"keyHandled",e,t,r),("handled"==o||"multi"==o)&&(ms(r),It(e)),i&&!o&&/\'$/.test(t)?(ms(r),!0):!!o}function nn(e,t){var r=is(t,!0);return r?t.shiftKey&&!e.state.keySeq?rn(e,"Shift-"+r,t,function(t){return en(e,t,!0)})||rn(e,r,t,function(t){return("string"==typeof t?/^go[A-Z]/.test(t):t.motion)?en(e,t):void 0}):rn(e,r,t,function(t){return en(e,t)}):!1}function on(e,t,r){return rn(e,"'"+r+"'",t,function(t){return en(e,t,!0)})}function ln(e){var t=this;if(q(t),!bo(t,e)){cl&&11>fl&&27==e.keyCode&&(e.returnValue=!1);var r=e.keyCode;t.display.shift=16==r||e.shiftKey;var n=nn(t,e);gl&&(Ul=n?r:null,!n&&88==r&&!js&&(xl?e.metaKey:e.ctrlKey)&&t.replaceSelection("",null,"cut")),18!=r||/\bCodeMirror-crosshair\b/.test(t.display.lineDiv.className)||sn(t)}}function sn(e){function t(e){18!=e.keyCode&&e.altKey||(Rs(r,"CodeMirror-crosshair"),xs(document,"keyup",t),xs(document,"mouseover",t))}var r=e.display.lineDiv;Bs(r,"CodeMirror-crosshair"),ws(document,"keyup",t),ws(document,"mouseover",t)}function an(e){16==e.keyCode&&(this.doc.sel.shift=!1),bo(this,e)}function un(e){var t=this;if(!(Gr(t.display,e)||bo(t,e)||e.ctrlKey&&!e.altKey||xl&&e.metaKey)){var r=e.keyCode,n=e.charCode;if(gl&&r==Ul)return Ul=null,void ms(e);if(!gl||e.which&&!(e.which<10)||!nn(t,e)){var i=String.fromCharCode(null==n?r:n);on(t,e,i)||t.display.input.onKeyPress(e)}}}function cn(e){"nocursor"!=e.options.readOnly&&(e.state.focused||(Cs(e,"focus",e),e.state.focused=!0,Bs(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),hl&&setTimeout(function(){e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),It(e))}function fn(e){e.state.focused&&(Cs(e,"blur",e),e.state.focused=!1,Rs(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150)}function hn(e,t){Gr(e.display,t)||dn(e,t)||e.display.input.onContextMenu(t)}function dn(e,t){return xo(e,"gutterContextMenu")?_r(e,t,"gutterContextMenu",!1,Cs):!1}function pn(e,t){if(Nl(e,t.from)<0)return e;if(Nl(e,t.to)<=0)return Vl(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=Vl(t).ch-t.to.ch),Al(r,n)}function gn(e,t){for(var r=[],n=0;n<e.sel.ranges.length;n++){var i=e.sel.ranges[n];r.push(new ct(pn(i.anchor,t),pn(i.head,t)))}return ft(r,e.sel.primIndex)}function vn(e,t,r){return e.line==t.line?Al(r.line,e.ch-t.ch+r.ch):Al(r.line+(e.line-t.line),e.ch)}function mn(e,t,r){for(var n=[],i=Al(e.first,0),o=i,l=0;l<t.length;l++){var s=t[l],a=vn(s.from,i,o),u=vn(Vl(s),i,o);if(i=s.to,o=u,"around"==r){var c=e.sel.ranges[l],f=Nl(c.head,c.anchor)<0;n[l]=new ct(f?u:a,f?a:u)}else n[l]=new ct(a,a)}return new ut(n,e.sel.primIndex)}function yn(e,t,r){var n={canceled:!1,from:t.from,to:t.to,text:t.text,origin:t.origin,cancel:function(){this.canceled=!0}};return r&&(n.update=function(t,r,n,i){t&&(this.from=pt(e,t)),r&&(this.to=pt(e,r)),n&&(this.text=n),void 0!==i&&(this.origin=i)}),Cs(e,"beforeChange",e,n),e.cm&&Cs(e.cm,"beforeChange",e.cm,n),n.canceled?null:{from:n.from,to:n.to,text:n.text,origin:n.origin}}function bn(e,t,r){if(e.cm){if(!e.cm.curOp)return Mr(e.cm,bn)(e,t,r);if(e.cm.state.suppressEdits)return}if(!(xo(e,"beforeChange")||e.cm&&xo(e.cm,"beforeChange"))||(t=yn(e,t,!0))){var n=Tl&&!r&&ti(e,t.from,t.to);if(n)for(var i=n.length-1;i>=0;--i)wn(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text});else wn(e,t)}}function wn(e,t){if(1!=t.text.length||""!=t.text[0]||0!=Nl(t.from,t.to)){var r=gn(e,t);ro(e,t,r,e.cm?e.cm.curOp.id:0/0),Sn(e,t,r,Qn(e,t));var n=[];Ui(e,function(e,r){r||-1!=Mo(n,e.history)||(ho(e.history,t),n.push(e.history)),Sn(e,t,null,Qn(e,t))})}}function xn(e,t,r){if(!e.cm||!e.cm.state.suppressEdits){for(var n,i=e.history,o=e.sel,l="undo"==t?i.done:i.undone,s="undo"==t?i.undone:i.done,a=0;a<l.length&&(n=l[a],r?!n.ranges||n.equals(e.sel):n.ranges);a++);if(a!=l.length){for(i.lastOrigin=i.lastSelOrigin=null;n=l.pop(),n.ranges;){if(oo(n,s),r&&!n.equals(e.sel))return void kt(e,n,{clearRedo:!1});o=n}var u=[];oo(o,s),s.push({changes:u,generation:i.generation}),i.generation=n.generation||++i.maxGeneration;for(var c=xo(e,"beforeChange")||e.cm&&xo(e.cm,"beforeChange"),a=n.changes.length-1;a>=0;--a){var f=n.changes[a];if(f.origin=t,c&&!yn(e,f,!1))return void(l.length=0);u.push(Ji(e,f));var h=a?gn(e,f):To(l);Sn(e,f,h,ei(e,f)),!a&&e.cm&&e.cm.scrollIntoView({from:f.from,to:Vl(f)});var d=[];Ui(e,function(e,t){t||-1!=Mo(d,e.history)||(ho(e.history,f),d.push(e.history)),Sn(e,f,null,ei(e,f))})}}}}function Cn(e,t){if(0!=t&&(e.first+=t,e.sel=new ut(Ao(e.sel.ranges,function(e){return new ct(Al(e.anchor.line+t,e.anchor.ch),Al(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){Dr(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;n<r.viewTo;n++)Hr(e.cm,n,"gutter")}}function Sn(e,t,r,n){if(e.cm&&!e.cm.curOp)return Mr(e.cm,Sn)(e,t,r,n);if(t.to.line<e.first)return void Cn(e,t.text.length-1-(t.to.line-t.from.line));if(!(t.from.line>e.lastLine())){if(t.from.line<e.first){var i=t.text.length-1-(e.first-t.from.line);Cn(e,i),t={from:Al(e.first,0),to:Al(t.to.line+i,t.to.ch),text:[To(t.text)],origin:t.origin}}var o=e.lastLine();t.to.line>o&&(t={from:t.from,to:Al(o,Ki(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=ji(e,t.from,t.to),r||(r=gn(e,t)),e.cm?Ln(e.cm,t,n):Ri(e,t,n),Tt(e,r,Ts)}}function Ln(e,t,r){var n=e.doc,i=e.display,l=t.from,s=t.to,a=!1,u=l.line;e.options.lineWrapping||(u=Yi(fi(Ki(n,l.line))),n.iter(u,s.line+1,function(e){return e==i.maxLine?(a=!0,!0):void 0})),n.sel.contains(t.from,t.to)>-1&&wo(e),Ri(n,t,r,o(e)),e.options.lineWrapping||(n.iter(u,l.line+t.text.length,function(e){var t=f(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,a=!1)}),a&&(e.curOp.updateMaxLine=!0)),n.frontier=Math.min(n.frontier,l.line),zt(e,400);var c=t.text.length-(s.line-l.line)-1;t.full?Dr(e):l.line!=s.line||1!=t.text.length||Fi(e.doc,t)?Dr(e,l.line,s.line+1,c):Hr(e,l.line,"text");var h=xo(e,"changes"),d=xo(e,"change");if(d||h){var p={from:l,to:s,text:t.text,removed:t.removed,origin:t.origin};d&&mo(e,"change",e,p),h&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(p)}e.display.selForContextMenu=null}function kn(e,t,r,n,i){if(n||(n=r),Nl(n,r)<0){var o=n;n=r,r=o}"string"==typeof t&&(t=Vs(t)),bn(e,{from:r,to:n,text:t,origin:i})}function Tn(e,t){if(!bo(e,"scrollCursorIntoView")){var r=e.display,n=r.sizer.getBoundingClientRect(),i=null;if(t.top+n.top<0?i=!0:t.bottom+n.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!yl){var o=zo("div","​",null,"position: absolute; top: "+(t.top-r.viewOffset-Bt(e.display))+"px; height: "+(t.bottom-t.top+Vt(e)+r.barHeight)+"px; left: "+t.left+"px; width: 2px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}function Mn(e,t,r,n){null==n&&(n=0);for(var i=0;5>i;i++){var o=!1,l=cr(e,t),s=r&&r!=t?cr(e,r):l,a=Nn(e,Math.min(l.left,s.left),Math.min(l.top,s.top)-n,Math.max(l.left,s.left),Math.max(l.bottom,s.bottom)+n),u=e.doc.scrollTop,c=e.doc.scrollLeft;if(null!=a.scrollTop&&(Zr(e,a.scrollTop),Math.abs(e.doc.scrollTop-u)>1&&(o=!0)),null!=a.scrollLeft&&(Qr(e,a.scrollLeft),Math.abs(e.doc.scrollLeft-c)>1&&(o=!0)),!o)break}return l}function An(e,t,r,n,i){var o=Nn(e,t,r,n,i);null!=o.scrollTop&&Zr(e,o.scrollTop),null!=o.scrollLeft&&Qr(e,o.scrollLeft)}function Nn(e,t,r,n,i){var o=e.display,l=gr(e.display);0>r&&(r=0);var s=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:o.scroller.scrollTop,a=jt(e),u={};i-r>a&&(i=r+a);var c=e.doc.height+Gt(o),f=l>r,h=i>c-l;if(s>r)u.scrollTop=f?0:r;else if(i>s+a){var d=Math.min(r,(h?c:i)-a);d!=s&&(u.scrollTop=d)}var p=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:o.scroller.scrollLeft,g=Kt(e)-(e.options.fixedGutter?o.gutters.offsetWidth:0),v=n-t>g;return v&&(n=t+g),10>t?u.scrollLeft=0:p>t?u.scrollLeft=Math.max(0,t-(v?0:10)):n>g+p-3&&(u.scrollLeft=n+(v?0:10)-g),u}function Wn(e,t,r){(null!=t||null!=r)&&Dn(e),null!=t&&(e.curOp.scrollLeft=(null==e.curOp.scrollLeft?e.doc.scrollLeft:e.curOp.scrollLeft)+t),null!=r&&(e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+r)}function On(e){Dn(e);var t=e.getCursor(),r=t,n=t;e.options.lineWrapping||(r=t.ch?Al(t.line,t.ch-1):t,n=Al(t.line,t.ch+1)),e.curOp.scrollToPos={from:r,to:n,margin:e.options.cursorScrollMargin,isCursor:!0}}function Dn(e){var t=e.curOp.scrollToPos;if(t){e.curOp.scrollToPos=null;var r=fr(e,t.from),n=fr(e,t.to),i=Nn(e,Math.min(r.left,n.left),Math.min(r.top,n.top)-t.margin,Math.max(r.right,n.right),Math.max(r.bottom,n.bottom)+t.margin);e.scrollTo(i.scrollLeft,i.scrollTop)}}function Hn(e,t,r,n){var i,o=e.doc;null==r&&(r="add"),"smart"==r&&(o.mode.indent?i=Rt(e,t):r="prev");var l=e.options.tabSize,s=Ki(o,t),a=Ns(s.text,null,l);s.stateAfter&&(s.stateAfter=null);var u,c=s.text.match(/^\s*/)[0];if(n||/\S/.test(s.text)){if("smart"==r&&(u=o.mode.indent(i,s.text.slice(c.length),s.text),u==ks||u>150)){if(!n)return;r="prev"}}else u=0,r="not";"prev"==r?u=t>o.first?Ns(Ki(o,t-1).text,null,l):0:"add"==r?u=a+e.options.indentUnit:"subtract"==r?u=a-e.options.indentUnit:"number"==typeof r&&(u=a+r),u=Math.max(0,u);var f="",h=0;if(e.options.indentWithTabs)for(var d=Math.floor(u/l);d;--d)h+=l,f+=" ";if(u>h&&(f+=ko(u-h)),f!=c)kn(o,f,Al(t,0),Al(t,c.length),"+input");else for(var d=0;d<o.sel.ranges.length;d++){var p=o.sel.ranges[d];if(p.head.line==t&&p.head.ch<c.length){var h=Al(t,c.length);xt(o,d,new ct(h,h));break}}s.stateAfter=null}function Pn(e,t,r,n){var i=t,o=t;return"number"==typeof t?o=Ki(e,dt(e,t)):i=Yi(t),null==i?null:(n(o,i)&&e.cm&&Hr(e.cm,i,r),o)}function In(e,t){for(var r=e.doc.sel.ranges,n=[],i=0;i<r.length;i++){for(var o=t(r[i]);n.length&&Nl(o.from,To(n).to)<=0;){var l=n.pop();if(Nl(l.from,o.from)<0){o.from=l.from;break}}n.push(o)}Tr(e,function(){for(var t=n.length-1;t>=0;t--)kn(e.doc,"",n[t].from,n[t].to,"+delete");On(e)})}function zn(e,t,r,n,i){function o(){var t=s+r;return t<e.first||t>=e.first+e.size?f=!1:(s=t,c=Ki(e,t))}function l(e){var t=(i?ol:ll)(c,a,r,!0);if(null==t){if(e||!o())return f=!1;a=i?(0>r?Qo:Zo)(c):0>r?c.text.length:0}else a=t;return!0}var s=t.line,a=t.ch,u=r,c=Ki(e,s),f=!0;if("char"==n)l();else if("column"==n)l(!0);else if("word"==n||"group"==n)for(var h=null,d="group"==n,p=e.cm&&e.cm.getHelper(t,"wordChars"),g=!0;!(0>r)||l(!g);g=!1){var v=c.text.charAt(a)||"\n",m=Ho(v,p)?"w":d&&"\n"==v?"n":!d||/\s/.test(v)?null:"p";if(!d||g||m||(m="s"),h&&h!=m){0>r&&(r=1,l());break}if(m&&(h=m),r>0&&!l(!g))break}var y=Wt(e,Al(s,a),u,!0);return f||(y.hitSide=!0),y}function En(e,t,r,n){var i,o=e.doc,l=t.left;if("page"==n){var s=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);i=t.top+r*(s-(0>r?1.5:.5)*gr(e.display))}else"line"==n&&(i=r>0?t.bottom+3:t.top-3);for(;;){var a=dr(e,l,i);if(!a.outside)break;if(0>r?0>=i:i>=o.height){a.hitSide=!0;break}i+=5*r}return a}function Fn(t,r,n,i){e.defaults[t]=r,n&&(jl[t]=i?function(e,t,r){r!=Xl&&n(e,t,r)}:n)}function Rn(e){for(var t,r,n,i,o=e.split(/-(?!$)/),e=o[o.length-1],l=0;l<o.length-1;l++){var s=o[l];if(/^(cmd|meta|m)$/i.test(s))i=!0;else if(/^a(lt)?$/i.test(s))t=!0;else if(/^(c|ctrl|control)$/i.test(s))r=!0;else{if(!/^s(hift)$/i.test(s))throw new Error("Unrecognized modifier name: "+s);n=!0}}return t&&(e="Alt-"+e),r&&(e="Ctrl-"+e),i&&(e="Cmd-"+e),n&&(e="Shift-"+e),e}function Bn(e){return"string"==typeof e?ts[e]:e
3
- }function Gn(e,t,r,n,i){if(n&&n.shared)return Un(e,t,r,n,i);if(e.cm&&!e.cm.curOp)return Mr(e.cm,Gn)(e,t,r,n,i);var o=new ss(e,i),l=Nl(t,r);if(n&&Oo(n,o,!1),l>0||0==l&&o.clearWhenEmpty!==!1)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=zo("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(ci(e,t.line,t,r,o)||t.line!=r.line&&ci(e,r.line,t,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Ml=!0}o.addToHistory&&ro(e,{from:t,to:r,origin:"markText"},e.sel,0/0);var s,a=t.line,u=e.cm;if(e.iter(a,r.line+1,function(e){u&&o.collapsed&&!u.options.lineWrapping&&fi(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=t.line&&_i(e,0),$n(e,new Xn(o,a==t.line?t.ch:null,a==r.line?r.ch:null)),++a}),o.collapsed&&e.iter(t.line,r.line+1,function(t){gi(e,t)&&_i(t,0)}),o.clearOnEnter&&ws(o,"beforeCursorEnter",function(){o.clear()}),o.readOnly&&(Tl=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++ls,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)Dr(u,t.line,r.line+1);else if(o.className||o.title||o.startStyle||o.endStyle||o.css)for(var c=t.line;c<=r.line;c++)Hr(u,c,"text");o.atomic&&At(u.doc),mo(u,"markerAdded",u,o)}return o}function Un(e,t,r,n,i){n=Oo(n),n.shared=!1;var o=[Gn(e,t,r,n,i)],l=o[0],s=n.widgetNode;return Ui(e,function(e){s&&(n.widgetNode=s.cloneNode(!0)),o.push(Gn(e,pt(e,t),pt(e,r),n,i));for(var a=0;a<e.linked.length;++a)if(e.linked[a].isParent)return;l=To(o)}),new as(o,l)}function Vn(e){return e.findMarks(Al(e.first,0),e.clipPos(Al(e.lastLine())),function(e){return e.parent})}function Kn(e,t){for(var r=0;r<t.length;r++){var n=t[r],i=n.find(),o=e.clipPos(i.from),l=e.clipPos(i.to);if(Nl(o,l)){var s=Gn(e,o,l,n.primary,n.primary.type);n.markers.push(s),s.parent=n}}}function jn(e){for(var t=0;t<e.length;t++){var r=e[t],n=[r.primary.doc];Ui(r.primary.doc,function(e){n.push(e)});for(var i=0;i<r.markers.length;i++){var o=r.markers[i];-1==Mo(n,o.doc)&&(o.parent=null,r.markers.splice(i--,1))}}}function Xn(e,t,r){this.marker=e,this.from=t,this.to=r}function _n(e,t){if(e)for(var r=0;r<e.length;++r){var n=e[r];if(n.marker==t)return n}}function Yn(e,t){for(var r,n=0;n<e.length;++n)e[n]!=t&&(r||(r=[])).push(e[n]);return r}function $n(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}function qn(e,t,r){if(e)for(var n,i=0;i<e.length;++i){var o=e[i],l=o.marker,s=null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t);if(s||o.from==t&&"bookmark"==l.type&&(!r||!o.marker.insertLeft)){var a=null==o.to||(l.inclusiveRight?o.to>=t:o.to>t);(n||(n=[])).push(new Xn(l,o.from,a?null:o.to))}}return n}function Zn(e,t,r){if(e)for(var n,i=0;i<e.length;++i){var o=e[i],l=o.marker,s=null==o.to||(l.inclusiveRight?o.to>=t:o.to>t);if(s||o.from==t&&"bookmark"==l.type&&(!r||o.marker.insertLeft)){var a=null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t);(n||(n=[])).push(new Xn(l,a?null:o.from-t,null==o.to?null:o.to-t))}}return n}function Qn(e,t){if(t.full)return null;var r=vt(e,t.from.line)&&Ki(e,t.from.line).markedSpans,n=vt(e,t.to.line)&&Ki(e,t.to.line).markedSpans;if(!r&&!n)return null;var i=t.from.ch,o=t.to.ch,l=0==Nl(t.from,t.to),s=qn(r,i,l),a=Zn(n,o,l),u=1==t.text.length,c=To(t.text).length+(u?i:0);if(s)for(var f=0;f<s.length;++f){var h=s[f];if(null==h.to){var d=_n(a,h.marker);d?u&&(h.to=null==d.to?null:d.to+c):h.to=i}}if(a)for(var f=0;f<a.length;++f){var h=a[f];if(null!=h.to&&(h.to+=c),null==h.from){var d=_n(s,h.marker);d||(h.from=c,u&&(s||(s=[])).push(h))}else h.from+=c,u&&(s||(s=[])).push(h)}s&&(s=Jn(s)),a&&a!=s&&(a=Jn(a));var p=[s];if(!u){var g,v=t.text.length-2;if(v>0&&s)for(var f=0;f<s.length;++f)null==s[f].to&&(g||(g=[])).push(new Xn(s[f].marker,null,null));for(var f=0;v>f;++f)p.push(g);p.push(a)}return p}function Jn(e){for(var t=0;t<e.length;++t){var r=e[t];null!=r.from&&r.from==r.to&&r.marker.clearWhenEmpty!==!1&&e.splice(t--,1)}return e.length?e:null}function ei(e,t){var r=ao(e,t),n=Qn(e,t);if(!r)return n;if(!n)return r;for(var i=0;i<r.length;++i){var o=r[i],l=n[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(r[i]=l)}return r}function ti(e,t,r){var n=null;if(e.iter(t.line,r.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var r=e.markedSpans[t].marker;!r.readOnly||n&&-1!=Mo(n,r)||(n||(n=[])).push(r)}}),!n)return null;for(var i=[{from:t,to:r}],o=0;o<n.length;++o)for(var l=n[o],s=l.find(0),a=0;a<i.length;++a){var u=i[a];if(!(Nl(u.to,s.from)<0||Nl(u.from,s.to)>0)){var c=[a,1],f=Nl(u.from,s.from),h=Nl(u.to,s.to);(0>f||!l.inclusiveLeft&&!f)&&c.push({from:u.from,to:s.from}),(h>0||!l.inclusiveRight&&!h)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),a+=c.length-1}}return i}function ri(e){var t=e.markedSpans;if(t){for(var r=0;r<t.length;++r)t[r].marker.detachLine(e);e.markedSpans=null}}function ni(e,t){if(t){for(var r=0;r<t.length;++r)t[r].marker.attachLine(e);e.markedSpans=t}}function ii(e){return e.inclusiveLeft?-1:0}function oi(e){return e.inclusiveRight?1:0}function li(e,t){var r=e.lines.length-t.lines.length;if(0!=r)return r;var n=e.find(),i=t.find(),o=Nl(n.from,i.from)||ii(e)-ii(t);if(o)return-o;var l=Nl(n.to,i.to)||oi(e)-oi(t);return l?l:t.id-e.id}function si(e,t){var r,n=Ml&&e.markedSpans;if(n)for(var i,o=0;o<n.length;++o)i=n[o],i.marker.collapsed&&null==(t?i.from:i.to)&&(!r||li(r,i.marker)<0)&&(r=i.marker);return r}function ai(e){return si(e,!0)}function ui(e){return si(e,!1)}function ci(e,t,r,n,i){var o=Ki(e,t),l=Ml&&o.markedSpans;if(l)for(var s=0;s<l.length;++s){var a=l[s];if(a.marker.collapsed){var u=a.marker.find(0),c=Nl(u.from,r)||ii(a.marker)-ii(i),f=Nl(u.to,n)||oi(a.marker)-oi(i);if(!(c>=0&&0>=f||0>=c&&f>=0)&&(0>=c&&(Nl(u.to,r)>0||a.marker.inclusiveRight&&i.inclusiveLeft)||c>=0&&(Nl(u.from,n)<0||a.marker.inclusiveLeft&&i.inclusiveRight)))return!0}}}function fi(e){for(var t;t=ai(e);)e=t.find(-1,!0).line;return e}function hi(e){for(var t,r;t=ui(e);)e=t.find(1,!0).line,(r||(r=[])).push(e);return r}function di(e,t){var r=Ki(e,t),n=fi(r);return r==n?t:Yi(n)}function pi(e,t){if(t>e.lastLine())return t;var r,n=Ki(e,t);if(!gi(e,n))return t;for(;r=ui(n);)n=r.find(1,!0).line;return Yi(n)+1}function gi(e,t){var r=Ml&&t.markedSpans;if(r)for(var n,i=0;i<r.length;++i)if(n=r[i],n.marker.collapsed){if(null==n.from)return!0;if(!n.marker.widgetNode&&0==n.from&&n.marker.inclusiveLeft&&vi(e,t,n))return!0}}function vi(e,t,r){if(null==r.to){var n=r.marker.find(1,!0);return vi(e,n.line,_n(n.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==t.text.length)return!0;for(var i,o=0;o<t.markedSpans.length;++o)if(i=t.markedSpans[o],i.marker.collapsed&&!i.marker.widgetNode&&i.from==r.to&&(null==i.to||i.to!=r.from)&&(i.marker.inclusiveLeft||r.marker.inclusiveRight)&&vi(e,t,i))return!0}function mi(e,t,r){qi(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&Wn(e,null,r)}function yi(e){if(null!=e.height)return e.height;if(!zs(document.body,e.node)){var t="position: relative;";e.coverGutter&&(t+="margin-left: -"+e.cm.display.gutters.offsetWidth+"px;"),e.noHScroll&&(t+="width: "+e.cm.display.wrapper.clientWidth+"px;"),Fo(e.cm.display.measure,zo("div",[e.node],null,t))}return e.height=e.node.offsetHeight}function bi(e,t,r,n){var i=new us(e,r,n);return i.noHScroll&&(e.display.alignWidgets=!0),Pn(e.doc,t,"widget",function(t){var r=t.widgets||(t.widgets=[]);if(null==i.insertAt?r.push(i):r.splice(Math.min(r.length-1,Math.max(0,i.insertAt)),0,i),i.line=t,!gi(e.doc,t)){var n=qi(t)<e.doc.scrollTop;_i(t,t.height+yi(i)),n&&Wn(e,null,i.height),e.curOp.forceUpdate=!0}return!0}),i}function wi(e,t,r,n){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),ri(e),ni(e,r);var i=n?n(e):1;i!=e.height&&_i(e,i)}function xi(e){e.parent=null,ri(e)}function Ci(e,t){if(e)for(;;){var r=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!r)break;e=e.slice(0,r.index)+e.slice(r.index+r[0].length);var n=r[1]?"bgClass":"textClass";null==t[n]?t[n]=r[2]:new RegExp("(?:^|s)"+r[2]+"(?:$|s)").test(t[n])||(t[n]+=" "+r[2])}return e}function Si(t,r){if(t.blankLine)return t.blankLine(r);if(t.innerMode){var n=e.innerMode(t,r);return n.mode.blankLine?n.mode.blankLine(n.state):void 0}}function Li(t,r,n,i){for(var o=0;10>o;o++){i&&(i[0]=e.innerMode(t,n).mode);var l=t.token(r,n);if(r.pos>r.start)return l}throw new Error("Mode "+t.name+" failed to advance stream.")}function ki(e,t,r,n){function i(e){return{start:f.start,end:f.pos,string:f.current(),type:o||null,state:e?Ql(l.mode,c):c}}var o,l=e.doc,s=l.mode;t=pt(l,t);var a,u=Ki(l,t.line),c=Rt(e,t.line,r),f=new os(u.text,e.options.tabSize);for(n&&(a=[]);(n||f.pos<t.ch)&&!f.eol();)f.start=f.pos,o=Li(s,f,c),n&&a.push(i(!0));return n?a:i()}function Ti(e,t,r,n,i,o,l){var s=r.flattenSpans;null==s&&(s=e.options.flattenSpans);var a,u=0,c=null,f=new os(t,e.options.tabSize),h=e.options.addModeClass&&[null];for(""==t&&Ci(Si(r,n),o);!f.eol();){if(f.pos>e.options.maxHighlightLength?(s=!1,l&&Ni(e,t,n,f.pos),f.pos=t.length,a=null):a=Ci(Li(r,f,n,h),o),h){var d=h[0].name;d&&(a="m-"+(a?d+" "+a:d))}if(!s||c!=a){for(;u<f.start;)u=Math.min(f.start,u+5e4),i(u,c);c=a}f.start=f.pos}for(;u<f.pos;){var p=Math.min(f.pos,u+5e4);i(p,c),u=p}}function Mi(e,t,r,n){var i=[e.state.modeGen],o={};Ti(e,t.text,e.doc.mode,r,function(e,t){i.push(e,t)},o,n);for(var l=0;l<e.state.overlays.length;++l){var s=e.state.overlays[l],a=1,u=0;Ti(e,t.text,s.mode,!0,function(e,t){for(var r=a;e>u;){var n=i[a];n>e&&i.splice(a,1,e,i[a+1],n),a+=2,u=Math.min(e,n)}if(t)if(s.opaque)i.splice(r,a-r,e,"cm-overlay "+t),a=r+2;else for(;a>r;r+=2){var o=i[r+1];i[r+1]=(o?o+" ":"")+"cm-overlay "+t}},o)}return{styles:i,classes:o.bgClass||o.textClass?o:null}}function Ai(e,t,r){if(!t.styles||t.styles[0]!=e.state.modeGen){var n=Mi(e,t,t.stateAfter=Rt(e,Yi(t)));t.styles=n.styles,n.classes?t.styleClasses=n.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.frontier&&e.doc.frontier++}return t.styles}function Ni(e,t,r,n){var i=e.doc.mode,o=new os(t,e.options.tabSize);for(o.start=o.pos=n||0,""==t&&Si(i,r);!o.eol()&&o.pos<=e.options.maxHighlightLength;)Li(i,o,r),o.start=o.pos}function Wi(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?hs:fs;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function Oi(e,t){var r=zo("span",null,null,hl?"padding-right: .1px":null),n={pre:zo("pre",[r]),content:r,col:0,pos:0,cm:e,splitSpaces:(cl||hl)&&e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o,l=i?t.rest[i-1]:t.line;n.pos=0,n.addToken=Hi,Xo(e.display.measure)&&(o=Zi(l))&&(n.addToken=Ii(n.addToken,o)),n.map=[];var s=t!=e.display.externalMeasured&&Yi(l);Ei(l,n,Ai(e,l,s)),l.styleClasses&&(l.styleClasses.bgClass&&(n.bgClass=Go(l.styleClasses.bgClass,n.bgClass||"")),l.styleClasses.textClass&&(n.textClass=Go(l.styleClasses.textClass,n.textClass||""))),0==n.map.length&&n.map.push(0,0,n.content.appendChild(jo(e.display.measure))),0==i?(t.measure.map=n.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(n.map),(t.measure.caches||(t.measure.caches=[])).push({}))}return hl&&/\bcm-tab\b/.test(n.content.lastChild.className)&&(n.content.className="cm-tab-wrap-hack"),Cs(e,"renderLine",e,t.line,n.pre),n.pre.className&&(n.textClass=Go(n.pre.className,n.textClass||"")),n}function Di(e){var t=zo("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function Hi(e,t,r,n,i,o,l){if(t){var s=e.splitSpaces?t.replace(/ {3,}/g,Pi):t,a=e.cm.state.specialChars,u=!1;if(a.test(t))for(var c=document.createDocumentFragment(),f=0;;){a.lastIndex=f;var h=a.exec(t),d=h?h.index-f:t.length-f;if(d){var p=document.createTextNode(s.slice(f,f+d));c.appendChild(cl&&9>fl?zo("span",[p]):p),e.map.push(e.pos,e.pos+d,p),e.col+=d,e.pos+=d}if(!h)break;if(f+=d+1," "==h[0]){var g=e.cm.options.tabSize,v=g-e.col%g,p=c.appendChild(zo("span",ko(v),"cm-tab"));p.setAttribute("role","presentation"),p.setAttribute("cm-text"," "),e.col+=v}else{var p=e.cm.options.specialCharPlaceholder(h[0]);p.setAttribute("cm-text",h[0]),c.appendChild(cl&&9>fl?zo("span",[p]):p),e.col+=1}e.map.push(e.pos,e.pos+1,p),e.pos++}else{e.col+=t.length;var c=document.createTextNode(s);e.map.push(e.pos,e.pos+t.length,c),cl&&9>fl&&(u=!0),e.pos+=t.length}if(r||n||i||u||l){var m=r||"";n&&(m+=n),i&&(m+=i);var y=zo("span",[c],m,l);return o&&(y.title=o),e.content.appendChild(y)}e.content.appendChild(c)}}function Pi(e){for(var t=" ",r=0;r<e.length-2;++r)t+=r%2?" ":" ";return t+=" "}function Ii(e,t){return function(r,n,i,o,l,s,a){i=i?i+" cm-force-border":"cm-force-border";for(var u=r.pos,c=u+n.length;;){for(var f=0;f<t.length;f++){var h=t[f];if(h.to>u&&h.from<=u)break}if(h.to>=c)return e(r,n,i,o,l,s,a);e(r,n.slice(0,h.to-u),i,o,null,s,a),o=null,n=n.slice(h.to-u),u=h.to}}}function zi(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t}function Ei(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var l,s,a,u,c,f,h,d=i.length,p=0,g=1,v="",m=0;;){if(m==p){a=u=c=f=s="",h=null,m=1/0;for(var y=[],b=0;b<n.length;++b){var w=n[b],x=w.marker;w.from<=p&&(null==w.to||w.to>p)?(null!=w.to&&m>w.to&&(m=w.to,u=""),x.className&&(a+=" "+x.className),x.css&&(s=x.css),x.startStyle&&w.from==p&&(c+=" "+x.startStyle),x.endStyle&&w.to==m&&(u+=" "+x.endStyle),x.title&&!f&&(f=x.title),x.collapsed&&(!h||li(h.marker,x)<0)&&(h=w)):w.from>p&&m>w.from&&(m=w.from),"bookmark"==x.type&&w.from==p&&x.widgetNode&&y.push(x)}if(h&&(h.from||0)==p&&(zi(t,(null==h.to?d+1:h.to)-p,h.marker,null==h.from),null==h.to))return;if(!h&&y.length)for(var b=0;b<y.length;++b)zi(t,0,y[b])}if(p>=d)break;for(var C=Math.min(d,m);;){if(v){var S=p+v.length;if(!h){var L=S>C?v.slice(0,C-p):v;t.addToken(t,L,l?l+a:a,c,p+L.length==m?u:"",f,s)}if(S>=C){v=v.slice(C-p),p=C;break}p=S,c=""}v=i.slice(o,o=r[g++]),l=Wi(r[g++],t.cm.options)}}else for(var g=1;g<r.length;g+=2)t.addToken(t,i.slice(o,o=r[g]),Wi(r[g+1],t.cm.options))}function Fi(e,t){return 0==t.from.ch&&0==t.to.ch&&""==To(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function Ri(e,t,r,n){function i(e){return r?r[e]:null}function o(e,r,i){wi(e,r,i,n),mo(e,"change",e,t)}function l(e,t){for(var r=e,o=[];t>r;++r)o.push(new cs(u[r],i(r),n));return o}var s=t.from,a=t.to,u=t.text,c=Ki(e,s.line),f=Ki(e,a.line),h=To(u),d=i(u.length-1),p=a.line-s.line;if(t.full)e.insert(0,l(0,u.length)),e.remove(u.length,e.size-u.length);else if(Fi(e,t)){var g=l(0,u.length-1);o(f,f.text,d),p&&e.remove(s.line,p),g.length&&e.insert(s.line,g)}else if(c==f)if(1==u.length)o(c,c.text.slice(0,s.ch)+h+c.text.slice(a.ch),d);else{var g=l(1,u.length-1);g.push(new cs(h+c.text.slice(a.ch),d,n)),o(c,c.text.slice(0,s.ch)+u[0],i(0)),e.insert(s.line+1,g)}else if(1==u.length)o(c,c.text.slice(0,s.ch)+u[0]+f.text.slice(a.ch),i(0)),e.remove(s.line+1,p);else{o(c,c.text.slice(0,s.ch)+u[0],i(0)),o(f,h+f.text.slice(a.ch),d);var g=l(1,u.length-1);p>1&&e.remove(s.line+1,p-1),e.insert(s.line+1,g)}mo(e,"change",e,t)}function Bi(e){this.lines=e,this.parent=null;for(var t=0,r=0;t<e.length;++t)e[t].parent=this,r+=e[t].height;this.height=r}function Gi(e){this.children=e;for(var t=0,r=0,n=0;n<e.length;++n){var i=e[n];t+=i.chunkSize(),r+=i.height,i.parent=this}this.size=t,this.height=r,this.parent=null}function Ui(e,t,r){function n(e,i,o){if(e.linked)for(var l=0;l<e.linked.length;++l){var s=e.linked[l];if(s.doc!=i){var a=o&&s.sharedHist;(!r||a)&&(t(s.doc,a),n(s.doc,e,a))}}}n(e,null,!0)}function Vi(e,t){if(t.cm)throw new Error("This document is already in use.");e.doc=t,t.cm=e,l(e),r(e),e.options.lineWrapping||h(e),e.options.mode=t.modeOption,Dr(e)}function Ki(e,t){if(t-=e.first,0>t||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(o>t){r=i;break}t-=o}return r.lines[t]}function ji(e,t,r){var n=[],i=t.line;return e.iter(t.line,r.line+1,function(e){var o=e.text;i==r.line&&(o=o.slice(0,r.ch)),i==t.line&&(o=o.slice(t.ch)),n.push(o),++i}),n}function Xi(e,t,r){var n=[];return e.iter(t,r,function(e){n.push(e.text)}),n}function _i(e,t){var r=t-e.height;if(r)for(var n=e;n;n=n.parent)n.height+=r}function Yi(e){if(null==e.parent)return null;for(var t=e.parent,r=Mo(t.lines,e),n=t.parent;n;t=n,n=n.parent)for(var i=0;n.children[i]!=t;++i)r+=n.children[i].chunkSize();return r+t.first}function $i(e,t){var r=e.first;e:do{for(var n=0;n<e.children.length;++n){var i=e.children[n],o=i.height;if(o>t){e=i;continue e}t-=o,r+=i.chunkSize()}return r}while(!e.lines);for(var n=0;n<e.lines.length;++n){var l=e.lines[n],s=l.height;if(s>t)break;t-=s}return r+n}function qi(e){e=fi(e);for(var t=0,r=e.parent,n=0;n<r.lines.length;++n){var i=r.lines[n];if(i==e)break;t+=i.height}for(var o=r.parent;o;r=o,o=r.parent)for(var n=0;n<o.children.length;++n){var l=o.children[n];if(l==r)break;t+=l.height}return t}function Zi(e){var t=e.order;return null==t&&(t=e.order=$s(e.text)),t}function Qi(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function Ji(e,t){var r={from:_(t.from),to:Vl(t),text:ji(e,t.from,t.to)};return lo(e,r,t.from.line,t.to.line+1),Ui(e,function(e){lo(e,r,t.from.line,t.to.line+1)},!0),r}function eo(e){for(;e.length;){var t=To(e);if(!t.ranges)break;e.pop()}}function to(e,t){return t?(eo(e.done),To(e.done)):e.done.length&&!To(e.done).ranges?To(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),To(e.done)):void 0}function ro(e,t,r,n){var i=e.history;i.undone.length=0;var o,l=+new Date;if((i.lastOp==n||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&e.cm&&i.lastModTime>l-e.cm.options.historyEventDelay||"*"==t.origin.charAt(0)))&&(o=to(i,i.lastOp==n))){var s=To(o.changes);0==Nl(t.from,t.to)&&0==Nl(t.from,s.to)?s.to=Vl(t):o.changes.push(Ji(e,t))}else{var a=To(i.done);for(a&&a.ranges||oo(e.sel,i.done),o={changes:[Ji(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=l,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,s||Cs(e,"historyAdded")}function no(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}function io(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||no(e,o,To(i.done),t))?i.done[i.done.length-1]=t:oo(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&n.clearRedo!==!1&&eo(i.undone)}function oo(e,t){var r=To(t);r&&r.ranges&&r.equals(e)||t.push(e)}function lo(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o})}function so(e){if(!e)return null;for(var t,r=0;r<e.length;++r)e[r].marker.explicitlyCleared?t||(t=e.slice(0,r)):t&&t.push(e[r]);return t?t.length?t:null:e}function ao(e,t){var r=t["spans_"+e.id];if(!r)return null;for(var n=0,i=[];n<t.text.length;++n)i.push(so(r[n]));return i}function uo(e,t,r){for(var n=0,i=[];n<e.length;++n){var o=e[n];if(o.ranges)i.push(r?ut.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];i.push({changes:s});for(var a=0;a<l.length;++a){var u,c=l[a];if(s.push({from:c.from,to:c.to,text:c.text}),t)for(var f in c)(u=f.match(/^spans_(\d+)$/))&&Mo(t,Number(u[1]))>-1&&(To(s)[f]=c[f],delete c[f])}}}return i}function co(e,t,r,n){r<e.line?e.line+=n:t<e.line&&(e.line=t,e.ch=0)}function fo(e,t,r,n){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||(o=e[i]=o.deepCopy(),o.copied=!0);for(var s=0;s<o.ranges.length;s++)co(o.ranges[s].anchor,t,r,n),co(o.ranges[s].head,t,r,n)}else{for(var s=0;s<o.changes.length;++s){var a=o.changes[s];if(r<a.from.line)a.from=Al(a.from.line+n,a.from.ch),a.to=Al(a.to.line+n,a.to.ch);else if(t<=a.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function ho(e,t){var r=t.from.line,n=t.to.line,i=t.text.length-(n-r)-1;fo(e.done,r,n,i),fo(e.undone,r,n,i)}function po(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function go(e){return e.target||e.srcElement}function vo(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),xl&&e.ctrlKey&&1==t&&(t=3),t}function mo(e,t){function r(e){return function(){e.apply(null,o)}}var n=e._handlers&&e._handlers[t];if(n){var i,o=Array.prototype.slice.call(arguments,2);Il?i=Il.delayedCallbacks:Ss?i=Ss:(i=Ss=[],setTimeout(yo,0));for(var l=0;l<n.length;++l)i.push(r(n[l]))}}function yo(){var e=Ss;Ss=null;for(var t=0;t<e.length;++t)e[t]()}function bo(e,t,r){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),Cs(e,r||t.type,e,t),po(t)||t.codemirrorIgnore}function wo(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var r=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),n=0;n<t.length;++n)-1==Mo(r,t[n])&&r.push(t[n])}function xo(e,t){var r=e._handlers&&e._handlers[t];return r&&r.length>0}function Co(e){e.prototype.on=function(e,t){ws(this,e,t)},e.prototype.off=function(e,t){xs(this,e,t)}}function So(){this.id=null}function Lo(e,t,r){for(var n=0,i=0;;){var o=e.indexOf(" ",n);-1==o&&(o=e.length);var l=o-n;if(o==e.length||i+l>=t)return n+Math.min(l,t-i);if(i+=o-n,i+=r-i%r,n=o+1,i>=t)return n}}function ko(e){for(;Ws.length<=e;)Ws.push(To(Ws)+" ");return Ws[e]}function To(e){return e[e.length-1]}function Mo(e,t){for(var r=0;r<e.length;++r)if(e[r]==t)return r;return-1}function Ao(e,t){for(var r=[],n=0;n<e.length;n++)r[n]=t(e[n],n);return r}function No(){}function Wo(e,t){var r;return Object.create?r=Object.create(e):(No.prototype=e,r=new No),t&&Oo(t,r),r}function Oo(e,t,r){t||(t={});for(var n in e)!e.hasOwnProperty(n)||r===!1&&t.hasOwnProperty(n)||(t[n]=e[n]);return t}function Do(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function Ho(e,t){return t?t.source.indexOf("\\w")>-1&&Ps(e)?!0:t.test(e):Ps(e)}function Po(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}function Io(e){return e.charCodeAt(0)>=768&&Is.test(e)}function zo(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function Eo(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function Fo(e,t){return Eo(e).appendChild(t)}function Ro(){return document.activeElement}function Bo(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}function Go(e,t){for(var r=e.split(" "),n=0;n<r.length;n++)r[n]&&!Bo(r[n]).test(t)&&(t+=" "+r[n]);return t}function Uo(e){if(document.body.getElementsByClassName)for(var t=document.body.getElementsByClassName("CodeMirror"),r=0;r<t.length;r++){var n=t[r].CodeMirror;n&&e(n)}}function Vo(){Gs||(Ko(),Gs=!0)}function Ko(){var e;ws(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,Uo(Br)},100))}),ws(window,"blur",function(){Uo(fn)})}function jo(e){if(null==Es){var t=zo("span","​");Fo(e,zo("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Es=t.offsetWidth<=1&&t.offsetHeight>2&&!(cl&&8>fl))}var r=Es?zo("span","​"):zo("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}function Xo(e){if(null!=Fs)return Fs;var t=Fo(e,document.createTextNode("AخA")),r=Ds(t,0,1).getBoundingClientRect();if(!r||r.left==r.right)return!1;var n=Ds(t,1,2).getBoundingClientRect();return Fs=n.right-r.right<3}function _o(e){if(null!=Xs)return Xs;var t=Fo(e,zo("span","x")),r=t.getBoundingClientRect(),n=Ds(t,0,1).getBoundingClientRect();return Xs=Math.abs(r.left-n.left)>1}function Yo(e,t,r,n){if(!e)return n(t,r,"ltr");for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<r&&l.to>t||t==r&&l.to==t)&&(n(Math.max(l.from,t),Math.min(l.to,r),1==l.level?"rtl":"ltr"),i=!0)}i||n(t,r,"ltr")}function $o(e){return e.level%2?e.to:e.from}function qo(e){return e.level%2?e.from:e.to}function Zo(e){var t=Zi(e);return t?$o(t[0]):0}function Qo(e){var t=Zi(e);return t?qo(To(t)):e.text.length}function Jo(e,t){var r=Ki(e.doc,t),n=fi(r);n!=r&&(t=Yi(n));var i=Zi(n),o=i?i[0].level%2?Qo(n):Zo(n):0;return Al(t,o)}function el(e,t){for(var r,n=Ki(e.doc,t);r=ui(n);)n=r.find(1,!0).line,t=null;var i=Zi(n),o=i?i[0].level%2?Zo(n):Qo(n):n.text.length;return Al(null==t?Yi(n):t,o)}function tl(e,t){var r=Jo(e,t.line),n=Ki(e.doc,r.line),i=Zi(n);if(!i||0==i[0].level){var o=Math.max(0,n.text.search(/\S/)),l=t.line==r.line&&t.ch<=o&&t.ch;return Al(r.line,l?0:o)}return r}function rl(e,t,r){var n=e[0].level;return t==n?!0:r==n?!1:r>t}function nl(e,t){Ys=null;for(var r,n=0;n<e.length;++n){var i=e[n];if(i.from<t&&i.to>t)return n;if(i.from==t||i.to==t){if(null!=r)return rl(e,i.level,e[r].level)?(i.from!=i.to&&(Ys=r),n):(i.from!=i.to&&(Ys=n),r);r=n}}return r}function il(e,t,r,n){if(!n)return t+r;do t+=r;while(t>0&&Io(e.text.charAt(t)));return t}function ol(e,t,r,n){var i=Zi(e);if(!i)return ll(e,t,r,n);for(var o=nl(i,t),l=i[o],s=il(e,t,l.level%2?-r:r,n);;){if(s>l.from&&s<l.to)return s;if(s==l.from||s==l.to)return nl(i,s)==o?s:(l=i[o+=r],r>0==l.level%2?l.to:l.from);if(l=i[o+=r],!l)return null;s=r>0==l.level%2?il(e,l.to,-1,n):il(e,l.from,1,n)}}function ll(e,t,r,n){var i=t+r;if(n)for(;i>0&&Io(e.text.charAt(i));)i+=r;return 0>i||i>e.text.length?null:i}var sl=/gecko\/\d/i.test(navigator.userAgent),al=/MSIE \d/.test(navigator.userAgent),ul=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent),cl=al||ul,fl=cl&&(al?document.documentMode||6:ul[1]),hl=/WebKit\//.test(navigator.userAgent),dl=hl&&/Qt\/\d+\.\d+/.test(navigator.userAgent),pl=/Chrome\//.test(navigator.userAgent),gl=/Opera\//.test(navigator.userAgent),vl=/Apple Computer/.test(navigator.vendor),ml=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent),yl=/PhantomJS/.test(navigator.userAgent),bl=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent),wl=bl||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),xl=bl||/Mac/.test(navigator.platform),Cl=/win/i.test(navigator.platform),Sl=gl&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);Sl&&(Sl=Number(Sl[1])),Sl&&Sl>=15&&(gl=!1,hl=!0);var Ll=xl&&(dl||gl&&(null==Sl||12.11>Sl)),kl=sl||cl&&fl>=9,Tl=!1,Ml=!1;g.prototype=Oo({update:function(e){var t=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,n=e.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=t?n+"px":"0";var i=e.viewHeight-(t?n:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(r?n:0);this.horiz.firstChild.style.width=e.scrollWidth-e.clientWidth+o+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedOverlay&&e.clientHeight>0&&(0==n&&this.overlayHack(),this.checkedOverlay=!0),{right:r?n:0,bottom:t?n:0}},setScrollLeft:function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e)},setScrollTop:function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e)},overlayHack:function(){var e=xl&&!ml?"12px":"18px";this.horiz.style.minHeight=this.vert.style.minWidth=e;var t=this,r=function(e){go(e)!=t.vert&&go(e)!=t.horiz&&Mr(t.cm,Vr)(e)};ws(this.vert,"mousedown",r),ws(this.horiz,"mousedown",r)},clear:function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)}},g.prototype),v.prototype=Oo({update:function(){return{bottom:0,right:0}},setScrollLeft:function(){},setScrollTop:function(){},clear:function(){}},v.prototype),e.scrollbarModel={"native":g,"null":v},k.prototype.signal=function(e,t){xo(e,t)&&this.events.push(arguments)},k.prototype.finish=function(){for(var e=0;e<this.events.length;e++)Cs.apply(null,this.events[e])};var Al=e.Pos=function(e,t){return this instanceof Al?(this.line=e,void(this.ch=t)):new Al(e,t)},Nl=e.cmpPos=function(e,t){return e.line-t.line||e.ch-t.ch},Wl=null;tt.prototype=Oo({init:function(e){function t(e){if(n.somethingSelected())Wl=n.getSelections(),r.inaccurateSelection&&(r.prevInput="",r.inaccurateSelection=!1,o.value=Wl.join("\n"),Os(o));else{var t=J(n);Wl=t.text,"cut"==e.type?n.setSelections(t.ranges,null,Ts):(r.prevInput="",o.value=t.text.join("\n"),Os(o))}"cut"==e.type&&(n.state.cutIncoming=!0)}var r=this,n=this.cm,i=this.wrapper=rt(),o=this.textarea=i.firstChild;e.wrapper.insertBefore(i,e.wrapper.firstChild),bl&&(o.style.width="0px"),ws(o,"input",function(){cl&&fl>=9&&r.hasSelection&&(r.hasSelection=null),r.poll()}),ws(o,"paste",function(){if(hl&&!n.state.fakedLastChar&&!(new Date-n.state.lastMiddleDown<200)){var e=o.selectionStart,t=o.selectionEnd;o.value+="$",o.selectionEnd=t,o.selectionStart=e,n.state.fakedLastChar=!0}n.state.pasteIncoming=!0,r.fastPoll()}),ws(o,"cut",t),ws(o,"copy",t),ws(e.scroller,"paste",function(t){Gr(e,t)||(n.state.pasteIncoming=!0,r.focus())}),ws(e.lineSpace,"selectstart",function(t){Gr(e,t)||ms(t)})},prepareSelection:function(){var e=this.cm,t=e.display,r=e.doc,n=Dt(e);if(e.options.moveInputWithCursor){var i=cr(e,r.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),l=t.lineDiv.getBoundingClientRect();n.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+l.top-o.top)),n.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+l.left-o.left))}return n},showSelection:function(e){var t=this.cm,r=t.display;Fo(r.cursorDiv,e.cursors),Fo(r.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},reset:function(e){if(!this.contextMenuPending){var t,r,n=this.cm,i=n.doc;if(n.somethingSelected()){this.prevInput="";var o=i.sel.primary();t=js&&(o.to().line-o.from().line>100||(r=n.getSelection()).length>1e3);var l=t?"-":r||n.getSelection();this.textarea.value=l,n.state.focused&&Os(this.textarea),cl&&fl>=9&&(this.hasSelection=l)}else e||(this.prevInput=this.textarea.value="",cl&&fl>=9&&(this.hasSelection=null));this.inaccurateSelection=t}},getField:function(){return this.textarea},supportsTouch:function(){return!1},focus:function(){if("nocursor"!=this.cm.options.readOnly&&(!wl||Ro()!=this.textarea))try{this.textarea.focus()}catch(e){}},blur:function(){this.textarea.blur()},resetPosition:function(){this.wrapper.style.top=this.wrapper.style.left=0},receivedFocus:function(){this.slowPoll()},slowPoll:function(){var e=this;e.pollingFast||e.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},fastPoll:function(){function e(){var n=r.poll();n||t?(r.pollingFast=!1,r.slowPoll()):(t=!0,r.polling.set(60,e))}var t=!1,r=this;r.pollingFast=!0,r.polling.set(20,e)},poll:function(){var e=this.cm,t=this.textarea,r=this.prevInput;if(!e.state.focused||Ks(t)&&!r||Z(e)||e.options.disableInput||e.state.keySeq)return!1;e.state.pasteIncoming&&e.state.fakedLastChar&&(t.value=t.value.substring(0,t.value.length-1),e.state.fakedLastChar=!1);var n=t.value;if(n==r&&!e.somethingSelected())return!1;if(cl&&fl>=9&&this.hasSelection===n||xl&&/[\uf700-\uf7ff]/.test(n))return e.display.input.reset(),!1;8203!=n.charCodeAt(0)||e.doc.sel!=e.display.selForContextMenu||r||(r="​");for(var i=0,o=Math.min(r.length,n.length);o>i&&r.charCodeAt(i)==n.charCodeAt(i);)++i;var l=this;return Tr(e,function(){Q(e,n.slice(i),r.length-i),n.length>1e3||n.indexOf("\n")>-1?t.value=l.prevInput="":l.prevInput=n
4
- }),!0},ensurePolled:function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},onKeyPress:function(){cl&&fl>=9&&(this.hasSelection=null),this.fastPoll()},onContextMenu:function(e){function t(){if(null!=l.selectionStart){var e=i.somethingSelected(),t=l.value="​"+(e?l.value:"");n.prevInput=e?"":"​",l.selectionStart=1,l.selectionEnd=t.length,o.selForContextMenu=i.doc.sel}}function r(){if(n.contextMenuPending=!1,n.wrapper.style.position="relative",l.style.cssText=c,cl&&9>fl&&o.scrollbars.setScrollTop(o.scroller.scrollTop=a),null!=l.selectionStart){(!cl||cl&&9>fl)&&t();var e=0,r=function(){o.selForContextMenu==i.doc.sel&&0==l.selectionStart?Mr(i,es.selectAll)(i):e++<10?o.detectingSelectAll=setTimeout(r,500):o.input.reset()};o.detectingSelectAll=setTimeout(r,200)}}var n=this,i=n.cm,o=i.display,l=n.textarea,s=Ur(i,e),a=o.scroller.scrollTop;if(s&&!gl){var u=i.options.resetSelectionOnContextMenu;u&&-1==i.doc.sel.contains(s)&&Mr(i,kt)(i.doc,ht(s),Ts);var c=l.style.cssText;if(n.wrapper.style.position="absolute",l.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(e.clientY-5)+"px; left: "+(e.clientX-5)+"px; z-index: 1000; background: "+(cl?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",hl)var f=window.scrollY;if(o.input.focus(),hl&&window.scrollTo(null,f),o.input.reset(),i.somethingSelected()||(l.value=n.prevInput=" "),n.contextMenuPending=!0,o.selForContextMenu=i.doc.sel,clearTimeout(o.detectingSelectAll),cl&&fl>=9&&t(),kl){bs(e);var h=function(){xs(window,"mouseup",h),setTimeout(r,20)};ws(window,"mouseup",h)}else setTimeout(r,50)}},setUneditable:No,needsContentAttribute:!1},tt.prototype),nt.prototype=Oo({init:function(e){function t(e){if(n.somethingSelected())Wl=n.getSelections(),"cut"==e.type&&n.replaceSelection("",null,"cut");else{var t=J(n);Wl=t.text,"cut"==e.type&&n.operation(function(){n.setSelections(t.ranges,0,Ts),n.replaceSelection("",null,"cut")})}if(e.clipboardData&&!bl)e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData("text/plain",Wl.join("\n"));else{var r=rt(),i=r.firstChild;n.display.lineSpace.insertBefore(r,n.display.lineSpace.firstChild),i.value=Wl.join("\n");var o=document.activeElement;Os(i),setTimeout(function(){n.display.lineSpace.removeChild(r),o.focus()},50)}}var r=this,n=r.cm,i=r.div=e.lineDiv;i.contentEditable="true",et(i),ws(i,"paste",function(e){var t=e.clipboardData&&e.clipboardData.getData("text/plain");t&&(e.preventDefault(),n.replaceSelection(t,null,"paste"))}),ws(i,"compositionstart",function(e){var t=e.data;if(r.composing={sel:n.doc.sel,data:t,startData:t},t){var i=n.doc.sel.primary(),o=n.getLine(i.head.line),l=o.indexOf(t,Math.max(0,i.head.ch-t.length));l>-1&&l<=i.head.ch&&(r.composing.sel=ht(Al(i.head.line,l),Al(i.head.line,l+t.length)))}}),ws(i,"compositionupdate",function(e){r.composing.data=e.data}),ws(i,"compositionend",function(e){var t=r.composing;t&&(e.data==t.startData||/\u200b/.test(e.data)||(t.data=e.data),setTimeout(function(){t.handled||r.applyComposition(t),r.composing==t&&(r.composing=null)},50))}),ws(i,"touchstart",function(){r.forceCompositionEnd()}),ws(i,"input",function(){r.composing||r.pollContent()||Tr(r.cm,function(){Dr(n)})}),ws(i,"copy",t),ws(i,"cut",t)},prepareSelection:function(){var e=Dt(this.cm,!1);return e.focus=this.cm.state.focused,e},showSelection:function(e){e&&this.cm.display.view.length&&(e.focus&&this.showPrimarySelection(),this.showMultipleSelections(e))},showPrimarySelection:function(){var e=window.getSelection(),t=this.cm.doc.sel.primary(),r=lt(this.cm,e.anchorNode,e.anchorOffset),n=lt(this.cm,e.focusNode,e.focusOffset);if(!r||r.bad||!n||n.bad||0!=Nl($(r,n),t.from())||0!=Nl(Y(r,n),t.to())){var i=it(this.cm,t.from()),o=it(this.cm,t.to());if(i||o){var l=this.cm.display.view,s=e.rangeCount&&e.getRangeAt(0);if(i){if(!o){var a=l[l.length-1].measure,u=a.maps?a.maps[a.maps.length-1]:a.map;o={node:u[u.length-1],offset:u[u.length-2]-u[u.length-3]}}}else i={node:l[0].measure.map[2],offset:0};try{var c=Ds(i.node,i.offset,o.offset,o.node)}catch(f){}c&&(e.removeAllRanges(),e.addRange(c),s&&null==e.anchorNode?e.addRange(s):sl&&this.startGracePeriod()),this.rememberSelection()}}},startGracePeriod:function(){var e=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){e.gracePeriod=!1,e.selectionChanged()&&e.cm.operation(function(){e.cm.curOp.selectionChanged=!0})},20)},showMultipleSelections:function(e){Fo(this.cm.display.cursorDiv,e.cursors),Fo(this.cm.display.selectionDiv,e.selection)},rememberSelection:function(){var e=window.getSelection();this.lastAnchorNode=e.anchorNode,this.lastAnchorOffset=e.anchorOffset,this.lastFocusNode=e.focusNode,this.lastFocusOffset=e.focusOffset},selectionInEditor:function(){var e=window.getSelection();if(!e.rangeCount)return!1;var t=e.getRangeAt(0).commonAncestorContainer;return zs(this.div,t)},focus:function(){"nocursor"!=this.cm.options.readOnly&&this.div.focus()},blur:function(){this.div.blur()},getField:function(){return this.div},supportsTouch:function(){return!0},receivedFocus:function(){function e(){t.cm.state.focused&&(t.pollSelection(),t.polling.set(t.cm.options.pollInterval,e))}var t=this;this.selectionInEditor()?this.pollSelection():Tr(this.cm,function(){t.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,e)},selectionChanged:function(){var e=window.getSelection();return e.anchorNode!=this.lastAnchorNode||e.anchorOffset!=this.lastAnchorOffset||e.focusNode!=this.lastFocusNode||e.focusOffset!=this.lastFocusOffset},pollSelection:function(){if(!this.composing&&!this.gracePeriod&&this.selectionChanged()){var e=window.getSelection(),t=this.cm;this.rememberSelection();var r=lt(t,e.anchorNode,e.anchorOffset),n=lt(t,e.focusNode,e.focusOffset);r&&n&&Tr(t,function(){kt(t.doc,ht(r,n),Ts),(r.bad||n.bad)&&(t.curOp.selectionChanged=!0)})}},pollContent:function(){var e=this.cm,t=e.display,r=e.doc.sel.primary(),n=r.from(),i=r.to();if(n.line<t.viewFrom||i.line>t.viewTo-1)return!1;var o;if(n.line==t.viewFrom||0==(o=Ir(e,n.line)))var l=Yi(t.view[0].line),s=t.view[0].node;else var l=Yi(t.view[o].line),s=t.view[o-1].node.nextSibling;var a=Ir(e,i.line);if(a==t.view.length-1)var u=t.viewTo-1,c=t.view[a].node;else var u=Yi(t.view[a+1].line)-1,c=t.view[a+1].node.previousSibling;for(var f=Vs(at(e,s,c,l,u)),h=ji(e.doc,Al(l,0),Al(u,Ki(e.doc,u).text.length));f.length>1&&h.length>1;)if(To(f)==To(h))f.pop(),h.pop(),u--;else{if(f[0]!=h[0])break;f.shift(),h.shift(),l++}for(var d=0,p=0,g=f[0],v=h[0],m=Math.min(g.length,v.length);m>d&&g.charCodeAt(d)==v.charCodeAt(d);)++d;for(var y=To(f),b=To(h),w=Math.min(y.length-(1==f.length?d:0),b.length-(1==h.length?d:0));w>p&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)++p;f[f.length-1]=y.slice(0,y.length-p),f[0]=f[0].slice(d);var x=Al(l,d),C=Al(u,h.length?To(h).length-p:0);return f.length>1||f[0]||Nl(x,C)?(kn(e.doc,f,x,C,"+input"),!0):void 0},ensurePolled:function(){this.forceCompositionEnd()},reset:function(){this.forceCompositionEnd()},forceCompositionEnd:function(){this.composing&&!this.composing.handled&&(this.applyComposition(this.composing),this.composing.handled=!0,this.div.blur(),this.div.focus())},applyComposition:function(e){e.data&&e.data!=e.startData&&Mr(this.cm,Q)(this.cm,e.data,0,e.sel)},setUneditable:function(e){e.setAttribute("contenteditable","false")},onKeyPress:function(e){e.preventDefault(),Mr(this.cm,Q)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0)},onContextMenu:No,resetPosition:No,needsContentAttribute:!0},nt.prototype),e.inputStyles={textarea:tt,contenteditable:nt},ut.prototype={primary:function(){return this.ranges[this.primIndex]},equals:function(e){if(e==this)return!0;if(e.primIndex!=this.primIndex||e.ranges.length!=this.ranges.length)return!1;for(var t=0;t<this.ranges.length;t++){var r=this.ranges[t],n=e.ranges[t];if(0!=Nl(r.anchor,n.anchor)||0!=Nl(r.head,n.head))return!1}return!0},deepCopy:function(){for(var e=[],t=0;t<this.ranges.length;t++)e[t]=new ct(_(this.ranges[t].anchor),_(this.ranges[t].head));return new ut(e,this.primIndex)},somethingSelected:function(){for(var e=0;e<this.ranges.length;e++)if(!this.ranges[e].empty())return!0;return!1},contains:function(e,t){t||(t=e);for(var r=0;r<this.ranges.length;r++){var n=this.ranges[r];if(Nl(t,n.from())>=0&&Nl(e,n.to())<=0)return r}return-1}},ct.prototype={from:function(){return $(this.anchor,this.head)},to:function(){return Y(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};var Ol,Dl,Hl,Pl={left:0,right:0,top:0,bottom:0},Il=null,zl=0,El=0,Fl=0,Rl=null;cl?Rl=-.53:sl?Rl=15:pl?Rl=-.7:vl&&(Rl=-1/3);var Bl=function(e){var t=e.wheelDeltaX,r=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==r&&e.detail&&e.axis==e.VERTICAL_AXIS?r=e.detail:null==r&&(r=e.wheelDelta),{x:t,y:r}};e.wheelEventPixels=function(e){var t=Bl(e);return t.x*=Rl,t.y*=Rl,t};var Gl=new So,Ul=null,Vl=e.changeEnd=function(e){return e.text?Al(e.from.line+e.text.length-1,To(e.text).length+(1==e.text.length?e.from.ch:0)):e.to};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,t){var r=this.options,n=r[e];(r[e]!=t||"mode"==e)&&(r[e]=t,jl.hasOwnProperty(e)&&Mr(this,jl[e])(this,t,n))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Bn(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,r=0;r<t.length;++r)if(t[r]==e||t[r].name==e)return t.splice(r,1),!0},addOverlay:Ar(function(t,r){var n=t.token?t:e.getMode(this.options,t);if(n.startState)throw new Error("Overlays may not be stateful.");this.state.overlays.push({mode:n,modeSpec:t,opaque:r&&r.opaque}),this.state.modeGen++,Dr(this)}),removeOverlay:Ar(function(e){for(var t=this.state.overlays,r=0;r<t.length;++r){var n=t[r].modeSpec;if(n==e||"string"==typeof e&&n.name==e)return t.splice(r,1),this.state.modeGen++,void Dr(this)}}),indentLine:Ar(function(e,t,r){"string"!=typeof t&&"number"!=typeof t&&(t=null==t?this.options.smartIndent?"smart":"prev":t?"add":"subtract"),vt(this.doc,e)&&Hn(this,e,t,r)}),indentSelection:Ar(function(e){for(var t=this.doc.sel.ranges,r=-1,n=0;n<t.length;n++){var i=t[n];if(i.empty())i.head.line>r&&(Hn(this,i.head.line,e,!0),r=i.head.line,n==this.doc.sel.primIndex&&On(this));else{var o=i.from(),l=i.to(),s=Math.max(r,o.line);r=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1;for(var a=s;r>a;++a)Hn(this,a,e);var u=this.doc.sel.ranges;0==o.ch&&t.length==u.length&&u[n].from().ch>0&&xt(this.doc,n,new ct(o,u[n].to()),Ts)}}}),getTokenAt:function(e,t){return ki(this,e,t)},getLineTokens:function(e,t){return ki(this,Al(e),t,!0)},getTokenTypeAt:function(e){e=pt(this.doc,e);var t,r=Ai(this,Ki(this.doc,e.line)),n=0,i=(r.length-1)/2,o=e.ch;if(0==o)t=r[2];else for(;;){var l=n+i>>1;if((l?r[2*l-1]:0)>=o)i=l;else{if(!(r[2*l+1]<o)){t=r[2*l+2];break}n=l+1}}var s=t?t.indexOf("cm-overlay "):-1;return 0>s?t:0==s?null:t.slice(0,s-1)},getModeAt:function(t){var r=this.doc.mode;return r.innerMode?e.innerMode(r,this.getTokenAt(t).state).mode:r},getHelper:function(e,t){return this.getHelpers(e,t)[0]},getHelpers:function(e,t){var r=[];if(!Zl.hasOwnProperty(t))return r;var n=Zl[t],i=this.getModeAt(e);if("string"==typeof i[t])n[i[t]]&&r.push(n[i[t]]);else if(i[t])for(var o=0;o<i[t].length;o++){var l=n[i[t][o]];l&&r.push(l)}else i.helperType&&n[i.helperType]?r.push(n[i.helperType]):n[i.name]&&r.push(n[i.name]);for(var o=0;o<n._global.length;o++){var s=n._global[o];s.pred(i,this)&&-1==Mo(r,s.val)&&r.push(s.val)}return r},getStateAfter:function(e,t){var r=this.doc;return e=dt(r,null==e?r.first+r.size-1:e),Rt(this,e+1,t)},cursorCoords:function(e,t){var r,n=this.doc.sel.primary();return r=null==e?n.head:"object"==typeof e?pt(this.doc,e):e?n.from():n.to(),cr(this,r,t||"page")},charCoords:function(e,t){return ur(this,pt(this.doc,e),t||"page")},coordsChar:function(e,t){return e=ar(this,e,t||"page"),dr(this,e.left,e.top)},lineAtHeight:function(e,t){return e=ar(this,{top:e,left:0},t||"page").top,$i(this.doc,e+this.display.viewOffset)},heightAtLine:function(e,t){var r=!1,n=this.doc.first+this.doc.size-1;e<this.doc.first?e=this.doc.first:e>n&&(e=n,r=!0);var i=Ki(this.doc,e);return sr(this,i,{top:0,left:0},t||"page").top+(r?this.doc.height-qi(i):0)},defaultTextHeight:function(){return gr(this.display)},defaultCharWidth:function(){return vr(this.display)},setGutterMarker:Ar(function(e,t,r){return Pn(this.doc,e,"gutter",function(e){var n=e.gutterMarkers||(e.gutterMarkers={});return n[t]=r,!r&&Po(n)&&(e.gutterMarkers=null),!0})}),clearGutter:Ar(function(e){var t=this,r=t.doc,n=r.first;r.iter(function(r){r.gutterMarkers&&r.gutterMarkers[e]&&(r.gutterMarkers[e]=null,Hr(t,n,"gutter"),Po(r.gutterMarkers)&&(r.gutterMarkers=null)),++n})}),addLineWidget:Ar(function(e,t,r){return bi(this,e,t,r)}),removeLineWidget:function(e){e.clear()},lineInfo:function(e){if("number"==typeof e){if(!vt(this.doc,e))return null;var t=e;if(e=Ki(this.doc,e),!e)return null}else{var t=Yi(e);if(null==t)return null}return{line:t,handle:e,text:e.text,gutterMarkers:e.gutterMarkers,textClass:e.textClass,bgClass:e.bgClass,wrapClass:e.wrapClass,widgets:e.widgets}},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,r,n,i){var o=this.display;e=cr(this,pt(this.doc,e));var l=e.bottom,s=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),o.sizer.appendChild(t),"over"==n)l=e.top;else if("above"==n||"near"==n){var a=Math.max(o.wrapper.clientHeight,this.doc.height),u=Math.max(o.sizer.clientWidth,o.lineSpace.clientWidth);("above"==n||e.bottom+t.offsetHeight>a)&&e.top>t.offsetHeight?l=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=a&&(l=e.bottom),s+t.offsetWidth>u&&(s=u-t.offsetWidth)}t.style.top=l+"px",t.style.left=t.style.right="","right"==i?(s=o.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?s=0:"middle"==i&&(s=(o.sizer.clientWidth-t.offsetWidth)/2),t.style.left=s+"px"),r&&An(this,s,l,s+t.offsetWidth,l+t.offsetHeight)},triggerOnKeyDown:Ar(ln),triggerOnKeyPress:Ar(un),triggerOnKeyUp:an,execCommand:function(e){return es.hasOwnProperty(e)?es[e](this):void 0},findPosH:function(e,t,r,n){var i=1;0>t&&(i=-1,t=-t);for(var o=0,l=pt(this.doc,e);t>o&&(l=zn(this.doc,l,i,r,n),!l.hitSide);++o);return l},moveH:Ar(function(e,t){var r=this;r.extendSelectionsBy(function(n){return r.display.shift||r.doc.extend||n.empty()?zn(r.doc,n.head,e,t,r.options.rtlMoveVisually):0>e?n.from():n.to()},As)}),deleteH:Ar(function(e,t){var r=this.doc.sel,n=this.doc;r.somethingSelected()?n.replaceSelection("",null,"+delete"):In(this,function(r){var i=zn(n,r.head,e,t,!1);return 0>e?{from:i,to:r.head}:{from:r.head,to:i}})}),findPosV:function(e,t,r,n){var i=1,o=n;0>t&&(i=-1,t=-t);for(var l=0,s=pt(this.doc,e);t>l;++l){var a=cr(this,s,"div");if(null==o?o=a.left:a.left=o,s=En(this,a,i,r),s.hitSide)break}return s},moveV:Ar(function(e,t){var r=this,n=this.doc,i=[],o=!r.display.shift&&!n.extend&&n.sel.somethingSelected();if(n.extendSelectionsBy(function(l){if(o)return 0>e?l.from():l.to();var s=cr(r,l.head,"div");null!=l.goalColumn&&(s.left=l.goalColumn),i.push(s.left);var a=En(r,s,e,t);return"page"==t&&l==n.sel.primary()&&Wn(r,null,ur(r,a,"div").top-s.top),a},As),i.length)for(var l=0;l<n.sel.ranges.length;l++)n.sel.ranges[l].goalColumn=i[l]}),findWordAt:function(e){var t=this.doc,r=Ki(t,e.line).text,n=e.ch,i=e.ch;if(r){var o=this.getHelper(e,"wordChars");(e.xRel<0||i==r.length)&&n?--n:++i;for(var l=r.charAt(n),s=Ho(l,o)?function(e){return Ho(e,o)}:/\s/.test(l)?function(e){return/\s/.test(e)}:function(e){return!/\s/.test(e)&&!Ho(e)};n>0&&s(r.charAt(n-1));)--n;for(;i<r.length&&s(r.charAt(i));)++i}return new ct(Al(e.line,n),Al(e.line,i))},toggleOverwrite:function(e){(null==e||e!=this.state.overwrite)&&((this.state.overwrite=!this.state.overwrite)?Bs(this.display.cursorDiv,"CodeMirror-overwrite"):Rs(this.display.cursorDiv,"CodeMirror-overwrite"),Cs(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==Ro()},scrollTo:Ar(function(e,t){(null!=e||null!=t)&&Dn(this),null!=e&&(this.curOp.scrollLeft=e),null!=t&&(this.curOp.scrollTop=t)}),getScrollInfo:function(){var e=this.display.scroller;return{left:e.scrollLeft,top:e.scrollTop,height:e.scrollHeight-Vt(this)-this.display.barHeight,width:e.scrollWidth-Vt(this)-this.display.barWidth,clientHeight:jt(this),clientWidth:Kt(this)}},scrollIntoView:Ar(function(e,t){if(null==e?(e={from:this.doc.sel.primary().head,to:null},null==t&&(t=this.options.cursorScrollMargin)):"number"==typeof e?e={from:Al(e,0),to:null}:null==e.from&&(e={from:e,to:null}),e.to||(e.to=e.from),e.margin=t||0,null!=e.from.line)Dn(this),this.curOp.scrollToPos=e;else{var r=Nn(this,Math.min(e.from.left,e.to.left),Math.min(e.from.top,e.to.top)-e.margin,Math.max(e.from.right,e.to.right),Math.max(e.from.bottom,e.to.bottom)+e.margin);this.scrollTo(r.scrollLeft,r.scrollTop)}}),setSize:Ar(function(e,t){function r(e){return"number"==typeof e||/^\d+$/.test(String(e))?e+"px":e}var n=this;null!=e&&(n.display.wrapper.style.width=r(e)),null!=t&&(n.display.wrapper.style.height=r(t)),n.options.lineWrapping&&nr(this);var i=n.display.viewFrom;n.doc.iter(i,n.display.viewTo,function(e){if(e.widgets)for(var t=0;t<e.widgets.length;t++)if(e.widgets[t].noHScroll){Hr(n,i,"widget");break}++i}),n.curOp.forceUpdate=!0,Cs(n,"refresh",this)}),operation:function(e){return Tr(this,e)},refresh:Ar(function(){var e=this.display.cachedTextHeight;Dr(this),this.curOp.forceUpdate=!0,ir(this),this.scrollTo(this.doc.scrollLeft,this.doc.scrollTop),c(this),(null==e||Math.abs(e-gr(this.display))>.5)&&l(this),Cs(this,"refresh",this)}),swapDoc:Ar(function(e){var t=this.doc;return t.cm=null,Vi(this,e),ir(this),this.display.input.reset(),this.scrollTo(e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,mo(this,"swapDoc",this,t),t}),getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Co(e);var Kl=e.defaults={},jl=e.optionHandlers={},Xl=e.Init={toString:function(){return"CodeMirror.Init"}};Fn("value","",function(e,t){e.setValue(t)},!0),Fn("mode",null,function(e,t){e.doc.modeOption=t,r(e)},!0),Fn("indentUnit",2,r,!0),Fn("indentWithTabs",!1),Fn("smartIndent",!0),Fn("tabSize",4,function(e){n(e),ir(e),Dr(e)},!0),Fn("specialChars",/[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g,function(t,r,n){t.state.specialChars=new RegExp(r.source+(r.test(" ")?"":"| "),"g"),n!=e.Init&&t.refresh()}),Fn("specialCharPlaceholder",Di,function(e){e.refresh()},!0),Fn("electricChars",!0),Fn("inputStyle",wl?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),Fn("rtlMoveVisually",!Cl),Fn("wholeLineUpdateBefore",!0),Fn("theme","default",function(e){s(e),a(e)},!0),Fn("keyMap","default",function(t,r,n){var i=Bn(r),o=n!=e.Init&&Bn(n);o&&o.detach&&o.detach(t,i),i.attach&&i.attach(t,o||null)}),Fn("extraKeys",null),Fn("lineWrapping",!1,i,!0),Fn("gutters",[],function(e){d(e.options),a(e)},!0),Fn("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?L(e.display)+"px":"0",e.refresh()},!0),Fn("coverGutterNextToScrollbar",!1,function(e){y(e)},!0),Fn("scrollbarStyle","native",function(e){m(e),y(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),Fn("lineNumbers",!1,function(e){d(e.options),a(e)},!0),Fn("firstLineNumber",1,a,!0),Fn("lineNumberFormatter",function(e){return e},a,!0),Fn("showCursorWhenSelecting",!1,Ot,!0),Fn("resetSelectionOnContextMenu",!0),Fn("readOnly",!1,function(e,t){"nocursor"==t?(fn(e),e.display.input.blur(),e.display.disabled=!0):(e.display.disabled=!1,t||e.display.input.reset())}),Fn("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),Fn("dragDrop",!0),Fn("cursorBlinkRate",530),Fn("cursorScrollMargin",0),Fn("cursorHeight",1,Ot,!0),Fn("singleCursorHeightPerLine",!0,Ot,!0),Fn("workTime",100),Fn("workDelay",100),Fn("flattenSpans",!0,n,!0),Fn("addModeClass",!1,n,!0),Fn("pollInterval",100),Fn("undoDepth",200,function(e,t){e.doc.history.undoDepth=t}),Fn("historyEventDelay",1250),Fn("viewportMargin",10,function(e){e.refresh()},!0),Fn("maxHighlightLength",1e4,n,!0),Fn("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),Fn("tabindex",null,function(e,t){e.display.input.getField().tabIndex=t||""}),Fn("autofocus",null);var _l=e.modes={},Yl=e.mimeModes={};e.defineMode=function(t,r){e.defaults.mode||"null"==t||(e.defaults.mode=t),arguments.length>2&&(r.dependencies=Array.prototype.slice.call(arguments,2)),_l[t]=r},e.defineMIME=function(e,t){Yl[e]=t},e.resolveMode=function(t){if("string"==typeof t&&Yl.hasOwnProperty(t))t=Yl[t];else if(t&&"string"==typeof t.name&&Yl.hasOwnProperty(t.name)){var r=Yl[t.name];"string"==typeof r&&(r={name:r}),t=Wo(r,t),t.name=r.name}else if("string"==typeof t&&/^[\w\-]+\/[\w\-]+\+xml$/.test(t))return e.resolveMode("application/xml");return"string"==typeof t?{name:t}:t||{name:"null"}},e.getMode=function(t,r){var r=e.resolveMode(r),n=_l[r.name];if(!n)return e.getMode(t,"text/plain");var i=n(t,r);if($l.hasOwnProperty(r.name)){var o=$l[r.name];for(var l in o)o.hasOwnProperty(l)&&(i.hasOwnProperty(l)&&(i["_"+l]=i[l]),i[l]=o[l])}if(i.name=r.name,r.helperType&&(i.helperType=r.helperType),r.modeProps)for(var l in r.modeProps)i[l]=r.modeProps[l];return i},e.defineMode("null",function(){return{token:function(e){e.skipToEnd()}}}),e.defineMIME("text/plain","null");var $l=e.modeExtensions={};e.extendMode=function(e,t){var r=$l.hasOwnProperty(e)?$l[e]:$l[e]={};Oo(t,r)},e.defineExtension=function(t,r){e.prototype[t]=r},e.defineDocExtension=function(e,t){ps.prototype[e]=t},e.defineOption=Fn;var ql=[];e.defineInitHook=function(e){ql.push(e)};var Zl=e.helpers={};e.registerHelper=function(t,r,n){Zl.hasOwnProperty(t)||(Zl[t]=e[t]={_global:[]}),Zl[t][r]=n},e.registerGlobalHelper=function(t,r,n,i){e.registerHelper(t,r,i),Zl[t]._global.push({pred:n,val:i})};var Ql=e.copyState=function(e,t){if(t===!0)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r},Jl=e.startState=function(e,t,r){return e.startState?e.startState(t,r):!0};e.innerMode=function(e,t){for(;e.innerMode;){var r=e.innerMode(t);if(!r||r.mode==e)break;t=r.state,e=r.mode}return r||{mode:e,state:t}};var es=e.commands={selectAll:function(e){e.setSelection(Al(e.firstLine(),0),Al(e.lastLine()),Ts)},singleSelection:function(e){e.setSelection(e.getCursor("anchor"),e.getCursor("head"),Ts)},killLine:function(e){In(e,function(t){if(t.empty()){var r=Ki(e.doc,t.head.line).text.length;return t.head.ch==r&&t.head.line<e.lastLine()?{from:t.head,to:Al(t.head.line+1,0)}:{from:t.head,to:Al(t.head.line,r)}}return{from:t.from(),to:t.to()}})},deleteLine:function(e){In(e,function(t){return{from:Al(t.from().line,0),to:pt(e.doc,Al(t.to().line+1,0))}})},delLineLeft:function(e){In(e,function(e){return{from:Al(e.from().line,0),to:e.from()}})},delWrappedLineLeft:function(e){In(e,function(t){var r=e.charCoords(t.head,"div").top+5,n=e.coordsChar({left:0,top:r},"div");return{from:n,to:t.from()}})},delWrappedLineRight:function(e){In(e,function(t){var r=e.charCoords(t.head,"div").top+5,n=e.coordsChar({left:e.display.lineDiv.offsetWidth+100,top:r},"div");return{from:t.from(),to:n}})},undo:function(e){e.undo()},redo:function(e){e.redo()},undoSelection:function(e){e.undoSelection()},redoSelection:function(e){e.redoSelection()},goDocStart:function(e){e.extendSelection(Al(e.firstLine(),0))},goDocEnd:function(e){e.extendSelection(Al(e.lastLine()))},goLineStart:function(e){e.extendSelectionsBy(function(t){return Jo(e,t.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(e){e.extendSelectionsBy(function(t){return tl(e,t.head)},{origin:"+move",bias:1})},goLineEnd:function(e){e.extendSelectionsBy(function(t){return el(e,t.head.line)},{origin:"+move",bias:-1})},goLineRight:function(e){e.extendSelectionsBy(function(t){var r=e.charCoords(t.head,"div").top+5;return e.coordsChar({left:e.display.lineDiv.offsetWidth+100,top:r},"div")},As)},goLineLeft:function(e){e.extendSelectionsBy(function(t){var r=e.charCoords(t.head,"div").top+5;return e.coordsChar({left:0,top:r},"div")},As)},goLineLeftSmart:function(e){e.extendSelectionsBy(function(t){var r=e.charCoords(t.head,"div").top+5,n=e.coordsChar({left:0,top:r},"div");return n.ch<e.getLine(n.line).search(/\S/)?tl(e,t.head):n},As)},goLineUp:function(e){e.moveV(-1,"line")},goLineDown:function(e){e.moveV(1,"line")},goPageUp:function(e){e.moveV(-1,"page")},goPageDown:function(e){e.moveV(1,"page")},goCharLeft:function(e){e.moveH(-1,"char")},goCharRight:function(e){e.moveH(1,"char")},goColumnLeft:function(e){e.moveH(-1,"column")},goColumnRight:function(e){e.moveH(1,"column")},goWordLeft:function(e){e.moveH(-1,"word")},goGroupRight:function(e){e.moveH(1,"group")},goGroupLeft:function(e){e.moveH(-1,"group")},goWordRight:function(e){e.moveH(1,"word")},delCharBefore:function(e){e.deleteH(-1,"char")},delCharAfter:function(e){e.deleteH(1,"char")},delWordBefore:function(e){e.deleteH(-1,"word")},delWordAfter:function(e){e.deleteH(1,"word")},delGroupBefore:function(e){e.deleteH(-1,"group")},delGroupAfter:function(e){e.deleteH(1,"group")},indentAuto:function(e){e.indentSelection("smart")},indentMore:function(e){e.indentSelection("add")},indentLess:function(e){e.indentSelection("subtract")},insertTab:function(e){e.replaceSelection(" ")},insertSoftTab:function(e){for(var t=[],r=e.listSelections(),n=e.options.tabSize,i=0;i<r.length;i++){var o=r[i].from(),l=Ns(e.getLine(o.line),o.ch,n);t.push(new Array(n-l%n+1).join(" "))}e.replaceSelections(t)},defaultTab:function(e){e.somethingSelected()?e.indentSelection("add"):e.execCommand("insertTab")},transposeChars:function(e){Tr(e,function(){for(var t=e.listSelections(),r=[],n=0;n<t.length;n++){var i=t[n].head,o=Ki(e.doc,i.line).text;if(o)if(i.ch==o.length&&(i=new Al(i.line,i.ch-1)),i.ch>0)i=new Al(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),Al(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var l=Ki(e.doc,i.line-1).text;l&&e.replaceRange(o.charAt(0)+"\n"+l.charAt(l.length-1),Al(i.line-1,l.length-1),Al(i.line,1),"+transpose")}r.push(new ct(i,i))}e.setSelections(r)})},newlineAndIndent:function(e){Tr(e,function(){for(var t=e.listSelections().length,r=0;t>r;r++){var n=e.listSelections()[r];e.replaceRange("\n",n.anchor,n.head,"+input"),e.indentLine(n.from().line+1,null,!0),On(e)}})},toggleOverwrite:function(e){e.toggleOverwrite()}},ts=e.keyMap={};ts.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},ts.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},ts.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"},ts.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},ts["default"]=xl?ts.macDefault:ts.pcDefault,e.normalizeKeyMap=function(e){var t={};for(var r in e)if(e.hasOwnProperty(r)){var n=e[r];if(/^(name|fallthrough|(de|at)tach)$/.test(r))continue;if("..."==n){delete e[r];continue}for(var i=Ao(r.split(" "),Rn),o=0;o<i.length;o++){var l,s;o==i.length-1?(s=r,l=n):(s=i.slice(0,o+1).join(" "),l="...");var a=t[s];if(a){if(a!=l)throw new Error("Inconsistent bindings for "+s)}else t[s]=l}delete e[r]}for(var u in t)e[u]=t[u];return e};var rs=e.lookupKey=function(e,t,r,n){t=Bn(t);var i=t.call?t.call(e,n):t[e];if(i===!1)return"nothing";if("..."===i)return"multi";if(null!=i&&r(i))return"handled";if(t.fallthrough){if("[object Array]"!=Object.prototype.toString.call(t.fallthrough))return rs(e,t.fallthrough,r,n);for(var o=0;o<t.fallthrough.length;o++){var l=rs(e,t.fallthrough[o],r,n);if(l)return l}}},ns=e.isModifierKey=function(e){var t="string"==typeof e?e:_s[e.keyCode];return"Ctrl"==t||"Alt"==t||"Shift"==t||"Mod"==t},is=e.keyName=function(e,t){if(gl&&34==e.keyCode&&e["char"])return!1;var r=_s[e.keyCode],n=r;return null==n||e.altGraphKey?!1:(e.altKey&&"Alt"!=r&&(n="Alt-"+n),(Ll?e.metaKey:e.ctrlKey)&&"Ctrl"!=r&&(n="Ctrl-"+n),(Ll?e.ctrlKey:e.metaKey)&&"Cmd"!=r&&(n="Cmd-"+n),!t&&e.shiftKey&&"Shift"!=r&&(n="Shift-"+n),n)};e.fromTextArea=function(t,r){function n(){t.value=u.getValue()}if(r=r?Oo(r):{},r.value=t.value,!r.tabindex&&t.tabIndex&&(r.tabindex=t.tabIndex),!r.placeholder&&t.placeholder&&(r.placeholder=t.placeholder),null==r.autofocus){var i=Ro();r.autofocus=i==t||null!=t.getAttribute("autofocus")&&i==document.body}if(t.form&&(ws(t.form,"submit",n),!r.leaveSubmitMethodAlone)){var o=t.form,l=o.submit;try{var s=o.submit=function(){n(),o.submit=l,o.submit(),o.submit=s}}catch(a){}}r.finishInit=function(e){e.save=n,e.getTextArea=function(){return t},e.toTextArea=function(){e.toTextArea=isNaN,n(),t.parentNode.removeChild(e.getWrapperElement()),t.style.display="",t.form&&(xs(t.form,"submit",n),"function"==typeof t.form.submit&&(t.form.submit=l))}},t.style.display="none";var u=e(function(e){t.parentNode.insertBefore(e,t.nextSibling)},r);return u};var os=e.StringStream=function(e,t){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0};os.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.pos<this.string.length?this.string.charAt(this.pos++):void 0},eat:function(e){var t=this.string.charAt(this.pos);if("string"==typeof e)var r=t==e;else var r=t&&(e.test?e.test(t):e(t));return r?(++this.pos,t):void 0},eatWhile:function(e){for(var t=this.pos;this.eat(e););return this.pos>t},eatSpace:function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},skipToEnd:function(){this.pos=this.string.length},skipTo:function(e){var t=this.string.indexOf(e,this.pos);
5
- return t>-1?(this.pos=t,!0):void 0},backUp:function(e){this.pos-=e},column:function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=Ns(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?Ns(this.string,this.lineStart,this.tabSize):0)},indentation:function(){return Ns(this.string,null,this.tabSize)-(this.lineStart?Ns(this.string,this.lineStart,this.tabSize):0)},match:function(e,t,r){if("string"!=typeof e){var n=this.string.slice(this.pos).match(e);return n&&n.index>0?null:(n&&t!==!1&&(this.pos+=n[0].length),n)}var i=function(e){return r?e.toLowerCase():e},o=this.string.substr(this.pos,e.length);return i(o)==i(e)?(t!==!1&&(this.pos+=e.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}}};var ls=0,ss=e.TextMarker=function(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++ls};Co(ss),ss.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&mr(e),xo(this,"clear")){var r=this.find();r&&mo(this,"clear",r.from,r.to)}for(var n=null,i=null,o=0;o<this.lines.length;++o){var l=this.lines[o],s=_n(l.markedSpans,this);e&&!this.collapsed?Hr(e,Yi(l),"text"):e&&(null!=s.to&&(i=Yi(l)),null!=s.from&&(n=Yi(l))),l.markedSpans=Yn(l.markedSpans,s),null==s.from&&this.collapsed&&!gi(this.doc,l)&&e&&_i(l,gr(e.display))}if(e&&this.collapsed&&!e.options.lineWrapping)for(var o=0;o<this.lines.length;++o){var a=fi(this.lines[o]),u=f(a);u>e.display.maxLineLength&&(e.display.maxLine=a,e.display.maxLineLength=u,e.display.maxLineChanged=!0)}null!=n&&e&&this.collapsed&&Dr(e,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&At(e.doc)),e&&mo(e,"markerCleared",e,this),t&&br(e),this.parent&&this.parent.clear()}},ss.prototype.find=function(e,t){null==e&&"bookmark"==this.type&&(e=1);for(var r,n,i=0;i<this.lines.length;++i){var o=this.lines[i],l=_n(o.markedSpans,this);if(null!=l.from&&(r=Al(t?o:Yi(o),l.from),-1==e))return r;if(null!=l.to&&(n=Al(t?o:Yi(o),l.to),1==e))return n}return r&&{from:r,to:n}},ss.prototype.changed=function(){var e=this.find(-1,!0),t=this,r=this.doc.cm;e&&r&&Tr(r,function(){var n=e.line,i=Yi(e.line),o=qt(r,i);if(o&&(rr(o),r.curOp.selectionChanged=r.curOp.forceUpdate=!0),r.curOp.updateMaxLine=!0,!gi(t.doc,n)&&null!=t.height){var l=t.height;t.height=null;var s=yi(t)-l;s&&_i(n,n.height+s)}})},ss.prototype.attachLine=function(e){if(!this.lines.length&&this.doc.cm){var t=this.doc.cm.curOp;t.maybeHiddenMarkers&&-1!=Mo(t.maybeHiddenMarkers,this)||(t.maybeUnhiddenMarkers||(t.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(e)},ss.prototype.detachLine=function(e){if(this.lines.splice(Mo(this.lines,e),1),!this.lines.length&&this.doc.cm){var t=this.doc.cm.curOp;(t.maybeHiddenMarkers||(t.maybeHiddenMarkers=[])).push(this)}};var ls=0,as=e.SharedTextMarker=function(e,t){this.markers=e,this.primary=t;for(var r=0;r<e.length;++r)e[r].parent=this};Co(as),as.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var e=0;e<this.markers.length;++e)this.markers[e].clear();mo(this,"clear")}},as.prototype.find=function(e,t){return this.primary.find(e,t)};var us=e.LineWidget=function(e,t,r){if(r)for(var n in r)r.hasOwnProperty(n)&&(this[n]=r[n]);this.cm=e,this.node=t};Co(us),us.prototype.clear=function(){var e=this.cm,t=this.line.widgets,r=this.line,n=Yi(r);if(null!=n&&t){for(var i=0;i<t.length;++i)t[i]==this&&t.splice(i--,1);t.length||(r.widgets=null);var o=yi(this);Tr(e,function(){mi(e,r,-o),Hr(e,n,"widget"),_i(r,Math.max(0,r.height-o))})}},us.prototype.changed=function(){var e=this.height,t=this.cm,r=this.line;this.height=null;var n=yi(this)-e;n&&Tr(t,function(){t.curOp.forceUpdate=!0,mi(t,r,n),_i(r,r.height+n)})};var cs=e.Line=function(e,t,r){this.text=e,ni(this,t),this.height=r?r(this):1};Co(cs),cs.prototype.lineNo=function(){return Yi(this)};var fs={},hs={};Bi.prototype={chunkSize:function(){return this.lines.length},removeInner:function(e,t){for(var r=e,n=e+t;n>r;++r){var i=this.lines[r];this.height-=i.height,xi(i),mo(i,"delete")}this.lines.splice(e,t)},collapse:function(e){e.push.apply(e,this.lines)},insertInner:function(e,t,r){this.height+=r,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var n=0;n<t.length;++n)t[n].parent=this},iterN:function(e,t,r){for(var n=e+t;n>e;++e)if(r(this.lines[e]))return!0}},Gi.prototype={chunkSize:function(){return this.size},removeInner:function(e,t){this.size-=t;for(var r=0;r<this.children.length;++r){var n=this.children[r],i=n.chunkSize();if(i>e){var o=Math.min(t,i-e),l=n.height;if(n.removeInner(e,o),this.height-=l-n.height,i==o&&(this.children.splice(r--,1),n.parent=null),0==(t-=o))break;e=0}else e-=i}if(this.size-t<25&&(this.children.length>1||!(this.children[0]instanceof Bi))){var s=[];this.collapse(s),this.children=[new Bi(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t<this.children.length;++t)this.children[t].collapse(e)},insertInner:function(e,t,r){this.size+=t.length,this.height+=r;for(var n=0;n<this.children.length;++n){var i=this.children[n],o=i.chunkSize();if(o>=e){if(i.insertInner(e,t,r),i.lines&&i.lines.length>50){for(;i.lines.length>50;){var l=i.lines.splice(i.lines.length-25,25),s=new Bi(l);i.height-=s.height,this.children.splice(n+1,0,s),s.parent=this}this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(!(this.children.length<=10)){var e=this;do{var t=e.children.splice(e.children.length-5,5),r=new Gi(t);if(e.parent){e.size-=r.size,e.height-=r.height;var n=Mo(e.parent.children,e);e.parent.children.splice(n+1,0,r)}else{var i=new Gi(e.children);i.parent=e,e.children=[i,r],e=i}r.parent=e.parent}while(e.children.length>10);e.parent.maybeSpill()}},iterN:function(e,t,r){for(var n=0;n<this.children.length;++n){var i=this.children[n],o=i.chunkSize();if(o>e){var l=Math.min(t,o-e);if(i.iterN(e,l,r))return!0;if(0==(t-=l))break;e=0}else e-=o}}};var ds=0,ps=e.Doc=function(e,t,r){if(!(this instanceof ps))return new ps(e,t,r);null==r&&(r=0),Gi.call(this,[new Bi([new cs("",null)])]),this.first=r,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.frontier=r;var n=Al(r,0);this.sel=ht(n),this.history=new Qi(null),this.id=++ds,this.modeOption=t,"string"==typeof e&&(e=Vs(e)),Ri(this,{from:n,to:n,text:e}),kt(this,ht(n),Ts)};ps.prototype=Wo(Gi.prototype,{constructor:ps,iter:function(e,t,r){r?this.iterN(e-this.first,t-e,r):this.iterN(this.first,this.first+this.size,e)},insert:function(e,t){for(var r=0,n=0;n<t.length;++n)r+=t[n].height;this.insertInner(e-this.first,t,r)},remove:function(e,t){this.removeInner(e-this.first,t)},getValue:function(e){var t=Xi(this,this.first,this.first+this.size);return e===!1?t:t.join(e||"\n")},setValue:Nr(function(e){var t=Al(this.first,0),r=this.first+this.size-1;bn(this,{from:t,to:Al(r,Ki(this,r).text.length),text:Vs(e),origin:"setValue",full:!0},!0),kt(this,ht(t))}),replaceRange:function(e,t,r,n){t=pt(this,t),r=r?pt(this,r):t,kn(this,e,t,r,n)},getRange:function(e,t,r){var n=ji(this,pt(this,e),pt(this,t));return r===!1?n:n.join(r||"\n")},getLine:function(e){var t=this.getLineHandle(e);return t&&t.text},getLineHandle:function(e){return vt(this,e)?Ki(this,e):void 0},getLineNumber:function(e){return Yi(e)},getLineHandleVisualStart:function(e){return"number"==typeof e&&(e=Ki(this,e)),fi(e)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(e){return pt(this,e)},getCursor:function(e){var t,r=this.sel.primary();return t=null==e||"head"==e?r.head:"anchor"==e?r.anchor:"end"==e||"to"==e||e===!1?r.to():r.from()},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Nr(function(e,t,r){Ct(this,pt(this,"number"==typeof e?Al(e,t||0):e),null,r)}),setSelection:Nr(function(e,t,r){Ct(this,pt(this,e),pt(this,t||e),r)}),extendSelection:Nr(function(e,t,r){bt(this,pt(this,e),t&&pt(this,t),r)}),extendSelections:Nr(function(e,t){wt(this,mt(this,e,t))}),extendSelectionsBy:Nr(function(e,t){wt(this,Ao(this.sel.ranges,e),t)}),setSelections:Nr(function(e,t,r){if(e.length){for(var n=0,i=[];n<e.length;n++)i[n]=new ct(pt(this,e[n].anchor),pt(this,e[n].head));null==t&&(t=Math.min(e.length-1,this.sel.primIndex)),kt(this,ft(i,t),r)}}),addSelection:Nr(function(e,t,r){var n=this.sel.ranges.slice(0);n.push(new ct(pt(this,e),pt(this,t||e))),kt(this,ft(n,n.length-1),r)}),getSelection:function(e){for(var t,r=this.sel.ranges,n=0;n<r.length;n++){var i=ji(this,r[n].from(),r[n].to());t=t?t.concat(i):i}return e===!1?t:t.join(e||"\n")},getSelections:function(e){for(var t=[],r=this.sel.ranges,n=0;n<r.length;n++){var i=ji(this,r[n].from(),r[n].to());e!==!1&&(i=i.join(e||"\n")),t[n]=i}return t},replaceSelection:function(e,t,r){for(var n=[],i=0;i<this.sel.ranges.length;i++)n[i]=e;this.replaceSelections(n,t,r||"+input")},replaceSelections:Nr(function(e,t,r){for(var n=[],i=this.sel,o=0;o<i.ranges.length;o++){var l=i.ranges[o];n[o]={from:l.from(),to:l.to(),text:Vs(e[o]),origin:r}}for(var s=t&&"end"!=t&&mn(this,n,t),o=n.length-1;o>=0;o--)bn(this,n[o]);s?Lt(this,s):this.cm&&On(this.cm)}),undo:Nr(function(){xn(this,"undo")}),redo:Nr(function(){xn(this,"redo")}),undoSelection:Nr(function(){xn(this,"undo",!0)}),redoSelection:Nr(function(){xn(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,r=0,n=0;n<e.done.length;n++)e.done[n].ranges||++t;for(var n=0;n<e.undone.length;n++)e.undone[n].ranges||++r;return{undo:t,redo:r}},clearHistory:function(){this.history=new Qi(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(e){return e&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(e){return this.history.generation==(e||this.cleanGeneration)},getHistory:function(){return{done:uo(this.history.done),undone:uo(this.history.undone)}},setHistory:function(e){var t=this.history=new Qi(this.history.maxGeneration);t.done=uo(e.done.slice(0),null,!0),t.undone=uo(e.undone.slice(0),null,!0)},addLineClass:Nr(function(e,t,r){return Pn(this,e,"gutter"==t?"gutter":"class",function(e){var n="text"==t?"textClass":"background"==t?"bgClass":"gutter"==t?"gutterClass":"wrapClass";if(e[n]){if(Bo(r).test(e[n]))return!1;e[n]+=" "+r}else e[n]=r;return!0})}),removeLineClass:Nr(function(e,t,r){return Pn(this,e,"gutter"==t?"gutter":"class",function(e){var n="text"==t?"textClass":"background"==t?"bgClass":"gutter"==t?"gutterClass":"wrapClass",i=e[n];if(!i)return!1;if(null==r)e[n]=null;else{var o=i.match(Bo(r));if(!o)return!1;var l=o.index+o[0].length;e[n]=i.slice(0,o.index)+(o.index&&l!=i.length?" ":"")+i.slice(l)||null}return!0})}),markText:function(e,t,r){return Gn(this,pt(this,e),pt(this,t),r,"range")},setBookmark:function(e,t){var r={replacedWith:t&&(null==t.nodeType?t.widget:t),insertLeft:t&&t.insertLeft,clearWhenEmpty:!1,shared:t&&t.shared};return e=pt(this,e),Gn(this,e,e,r,"bookmark")},findMarksAt:function(e){e=pt(this,e);var t=[],r=Ki(this,e.line).markedSpans;if(r)for(var n=0;n<r.length;++n){var i=r[n];(null==i.from||i.from<=e.ch)&&(null==i.to||i.to>=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,r){e=pt(this,e),t=pt(this,t);var n=[],i=e.line;return this.iter(e.line,t.line+1,function(o){var l=o.markedSpans;if(l)for(var s=0;s<l.length;s++){var a=l[s];i==e.line&&e.ch>a.to||null==a.from&&i!=e.line||i==t.line&&a.from>t.ch||r&&!r(a.marker)||n.push(a.marker.parent||a.marker)}++i}),n},getAllMarks:function(){var e=[];return this.iter(function(t){var r=t.markedSpans;if(r)for(var n=0;n<r.length;++n)null!=r[n].from&&e.push(r[n].marker)}),e},posFromIndex:function(e){var t,r=this.first;return this.iter(function(n){var i=n.text.length+1;return i>e?(t=e,!0):(e-=i,void++r)}),pt(this,Al(r,t))},indexFromPos:function(e){e=pt(this,e);var t=e.ch;return e.line<this.first||e.ch<0?0:(this.iter(this.first,e.line,function(e){t+=e.text.length+1}),t)},copy:function(e){var t=new ps(Xi(this,this.first,this.first+this.size),this.modeOption,this.first);return t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft,t.sel=this.sel,t.extend=!1,e&&(t.history.undoDepth=this.history.undoDepth,t.setHistory(this.getHistory())),t},linkedDoc:function(e){e||(e={});var t=this.first,r=this.first+this.size;null!=e.from&&e.from>t&&(t=e.from),null!=e.to&&e.to<r&&(r=e.to);var n=new ps(Xi(this,t,r),e.mode||this.modeOption,t);return e.sharedHist&&(n.history=this.history),(this.linked||(this.linked=[])).push({doc:n,sharedHist:e.sharedHist}),n.linked=[{doc:this,isParent:!0,sharedHist:e.sharedHist}],Kn(n,Vn(this)),n},unlinkDoc:function(t){if(t instanceof e&&(t=t.doc),this.linked)for(var r=0;r<this.linked.length;++r){var n=this.linked[r];if(n.doc==t){this.linked.splice(r,1),t.unlinkDoc(this),jn(Vn(this));break}}if(t.history==this.history){var i=[t.id];Ui(t,function(e){i.push(e.id)},!0),t.history=new Qi(null),t.history.done=uo(this.history.done,i),t.history.undone=uo(this.history.undone,i)}},iterLinkedDocs:function(e){Ui(this,e)},getMode:function(){return this.mode},getEditor:function(){return this.cm}}),ps.prototype.eachLine=ps.prototype.iter;var gs="iter insert remove copy getEditor".split(" ");for(var vs in ps.prototype)ps.prototype.hasOwnProperty(vs)&&Mo(gs,vs)<0&&(e.prototype[vs]=function(e){return function(){return e.apply(this.doc,arguments)}}(ps.prototype[vs]));Co(ps);var ms=e.e_preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},ys=e.e_stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},bs=e.e_stop=function(e){ms(e),ys(e)},ws=e.on=function(e,t,r){if(e.addEventListener)e.addEventListener(t,r,!1);else if(e.attachEvent)e.attachEvent("on"+t,r);else{var n=e._handlers||(e._handlers={}),i=n[t]||(n[t]=[]);i.push(r)}},xs=e.off=function(e,t,r){if(e.removeEventListener)e.removeEventListener(t,r,!1);else if(e.detachEvent)e.detachEvent("on"+t,r);else{var n=e._handlers&&e._handlers[t];if(!n)return;for(var i=0;i<n.length;++i)if(n[i]==r){n.splice(i,1);break}}},Cs=e.signal=function(e,t){var r=e._handlers&&e._handlers[t];if(r)for(var n=Array.prototype.slice.call(arguments,2),i=0;i<r.length;++i)r[i].apply(null,n)},Ss=null,Ls=30,ks=e.Pass={toString:function(){return"CodeMirror.Pass"}},Ts={scroll:!1},Ms={origin:"*mouse"},As={origin:"+move"};So.prototype.set=function(e,t){clearTimeout(this.id),this.id=setTimeout(t,e)};var Ns=e.countColumn=function(e,t,r,n,i){null==t&&(t=e.search(/[^\s\u00a0]/),-1==t&&(t=e.length));for(var o=n||0,l=i||0;;){var s=e.indexOf(" ",o);if(0>s||s>=t)return l+(t-o);l+=s-o,l+=r-l%r,o=s+1}},Ws=[""],Os=function(e){e.select()};bl?Os=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:cl&&(Os=function(e){try{e.select()}catch(t){}});var Ds,Hs=/[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,Ps=e.isWordChar=function(e){return/\w/.test(e)||e>"€"&&(e.toUpperCase()!=e.toLowerCase()||Hs.test(e))},Is=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;Ds=document.createRange?function(e,t,r,n){var i=document.createRange();return i.setEnd(n||e,r),i.setStart(e,t),i}:function(e,t,r){var n=document.body.createTextRange();try{n.moveToElementText(e.parentNode)}catch(i){return n}return n.collapse(!0),n.moveEnd("character",r),n.moveStart("character",t),n};var zs=e.contains=function(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do if(11==t.nodeType&&(t=t.host),t==e)return!0;while(t=t.parentNode)};cl&&11>fl&&(Ro=function(){try{return document.activeElement}catch(e){return document.body}});var Es,Fs,Rs=e.rmClass=function(e,t){var r=e.className,n=Bo(t).exec(r);if(n){var i=r.slice(n.index+n[0].length);e.className=r.slice(0,n.index)+(i?n[1]+i:"")}},Bs=e.addClass=function(e,t){var r=e.className;Bo(t).test(r)||(e.className+=(r?" ":"")+t)},Gs=!1,Us=function(){if(cl&&9>fl)return!1;var e=zo("div");return"draggable"in e||"dragDrop"in e}(),Vs=e.splitLines=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,r=[],n=e.length;n>=t;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(r.push(o.slice(0,l)),t+=l+1):(r.push(o),t=i+1)}return r}:function(e){return e.split(/\r\n?|\n/)},Ks=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(t){return!1}}:function(e){try{var t=e.ownerDocument.selection.createRange()}catch(r){}return t&&t.parentElement()==e?0!=t.compareEndPoints("StartToEnd",t):!1},js=function(){var e=zo("div");return"oncopy"in e?!0:(e.setAttribute("oncopy","return;"),"function"==typeof e.oncopy)}(),Xs=null,_s={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",107:"=",109:"-",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};e.keyNames=_s,function(){for(var e=0;10>e;e++)_s[e+48]=_s[e+96]=String(e);for(var e=65;90>=e;e++)_s[e]=String.fromCharCode(e);for(var e=1;12>=e;e++)_s[e+111]=_s[e+63235]="F"+e}();var Ys,$s=function(){function e(e){return 247>=e?r.charAt(e):e>=1424&&1524>=e?"R":e>=1536&&1773>=e?n.charAt(e-1536):e>=1774&&2220>=e?"r":e>=8192&&8203>=e?"w":8204==e?"b":"L"}function t(e,t,r){this.level=e,this.from=t,this.to=r}var r="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",n="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm",i=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,o=/[stwN]/,l=/[LRr]/,s=/[Lb1n]/,a=/[1n]/,u="L";return function(r){if(!i.test(r))return!1;for(var n,c=r.length,f=[],h=0;c>h;++h)f.push(n=e(r.charCodeAt(h)));for(var h=0,d=u;c>h;++h){var n=f[h];"m"==n?f[h]=d:d=n}for(var h=0,p=u;c>h;++h){var n=f[h];"1"==n&&"r"==p?f[h]="n":l.test(n)&&(p=n,"r"==n&&(f[h]="R"))}for(var h=1,d=f[0];c-1>h;++h){var n=f[h];"+"==n&&"1"==d&&"1"==f[h+1]?f[h]="1":","!=n||d!=f[h+1]||"1"!=d&&"n"!=d||(f[h]=d),d=n}for(var h=0;c>h;++h){var n=f[h];if(","==n)f[h]="N";else if("%"==n){for(var g=h+1;c>g&&"%"==f[g];++g);for(var v=h&&"!"==f[h-1]||c>g&&"1"==f[g]?"1":"N",m=h;g>m;++m)f[m]=v;h=g-1}}for(var h=0,p=u;c>h;++h){var n=f[h];"L"==p&&"1"==n?f[h]="L":l.test(n)&&(p=n)}for(var h=0;c>h;++h)if(o.test(f[h])){for(var g=h+1;c>g&&o.test(f[g]);++g);for(var y="L"==(h?f[h-1]:u),b="L"==(c>g?f[g]:u),v=y||b?"L":"R",m=h;g>m;++m)f[m]=v;h=g-1}for(var w,x=[],h=0;c>h;)if(s.test(f[h])){var C=h;for(++h;c>h&&s.test(f[h]);++h);x.push(new t(0,C,h))}else{var S=h,L=x.length;for(++h;c>h&&"L"!=f[h];++h);for(var m=S;h>m;)if(a.test(f[m])){m>S&&x.splice(L,0,new t(1,S,m));var k=m;for(++m;h>m&&a.test(f[m]);++m);x.splice(L,0,new t(2,k,m)),S=m}else++m;h>S&&x.splice(L,0,new t(1,S,h))}return 1==x[0].level&&(w=r.match(/^\s+/))&&(x[0].from=w[0].length,x.unshift(new t(0,0,w[0].length))),1==To(x).level&&(w=r.match(/\s+$/))&&(To(x).to-=w[0].length,x.push(new t(0,c-w[0].length,c))),x[0].level!=To(x).level&&x.push(new t(x[0].level,c,c)),x}}();return e.version="5.0.1",e});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,r=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),i=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),o=/Edge\/(\d+)/.exec(e),l=n||i||o,s=l&&(n?document.documentMode||6:+(o||i)[1]),a=!o&&/WebKit\//.test(e),u=a&&/Qt\/\d+\.\d+/.test(e),c=!o&&/Chrome\//.test(e),h=/Opera\//.test(e),f=/Apple Computer/.test(navigator.vendor),d=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),p=/PhantomJS/.test(e),g=f&&(/Mobile\/\w+/.test(e)||navigator.maxTouchPoints>2),v=/Android/.test(e),m=g||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=g||/Mac/.test(t),b=/\bCrOS\b/.test(e),w=/win/i.test(t),x=h&&e.match(/Version\/(\d*\.\d*)/);x&&(x=Number(x[1])),x&&x>=15&&(h=!1,a=!0);var C=y&&(u||h&&(null==x||x<12.11)),S=r||l&&s>=9;function L(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var k,T=function(e,t){var r=e.className,n=L(t).exec(r);if(n){var i=r.slice(n.index+n[0].length);e.className=r.slice(0,n.index)+(i?n[1]+i:"")}};function M(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function N(e,t){return M(e).appendChild(t)}function O(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function A(e,t,r,n){var i=O(e,t,r,n);return i.setAttribute("role","presentation"),i}function D(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do{if(11==t.nodeType&&(t=t.host),t==e)return!0}while(t=t.parentNode)}function W(){var e;try{e=document.activeElement}catch(t){e=document.body||null}for(;e&&e.shadowRoot&&e.shadowRoot.activeElement;)e=e.shadowRoot.activeElement;return e}function H(e,t){var r=e.className;L(t).test(r)||(e.className+=(r?" ":"")+t)}function F(e,t){for(var r=e.split(" "),n=0;n<r.length;n++)r[n]&&!L(r[n]).test(t)&&(t+=" "+r[n]);return t}k=document.createRange?function(e,t,r,n){var i=document.createRange();return i.setEnd(n||e,r),i.setStart(e,t),i}:function(e,t,r){var n=document.body.createTextRange();try{n.moveToElementText(e.parentNode)}catch(e){return n}return n.collapse(!0),n.moveEnd("character",r),n.moveStart("character",t),n};var P=function(e){e.select()};function E(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function I(e,t,r){for(var n in t||(t={}),e)!e.hasOwnProperty(n)||!1===r&&t.hasOwnProperty(n)||(t[n]=e[n]);return t}function R(e,t,r,n,i){null==t&&-1==(t=e.search(/[^\s\u00a0]/))&&(t=e.length);for(var o=n||0,l=i||0;;){var s=e.indexOf("\t",o);if(s<0||s>=t)return l+(t-o);l+=s-o,l+=r-l%r,o=s+1}}g?P=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:l&&(P=function(e){try{e.select()}catch(e){}});var z=function(){this.id=null,this.f=null,this.time=0,this.handler=E(this.onTimeout,this)};function B(e,t){for(var r=0;r<e.length;++r)if(e[r]==t)return r;return-1}z.prototype.onTimeout=function(e){e.id=0,e.time<=+new Date?e.f():setTimeout(e.handler,e.time-+new Date)},z.prototype.set=function(e,t){this.f=t;var r=+new Date+e;(!this.id||r<this.time)&&(clearTimeout(this.id),this.id=setTimeout(this.handler,e),this.time=r)};var G=50,U={toString:function(){return"CodeMirror.Pass"}},V={scroll:!1},K={origin:"*mouse"},j={origin:"+move"};function X(e,t,r){for(var n=0,i=0;;){var o=e.indexOf("\t",n);-1==o&&(o=e.length);var l=o-n;if(o==e.length||i+l>=t)return n+Math.min(l,t-i);if(i+=o-n,n=o+1,(i+=r-i%r)>=t)return n}}var Y=[""];function _(e){for(;Y.length<=e;)Y.push($(Y)+" ");return Y[e]}function $(e){return e[e.length-1]}function q(e,t){for(var r=[],n=0;n<e.length;n++)r[n]=t(e[n],n);return r}function Z(){}function Q(e,t){var r;return Object.create?r=Object.create(e):(Z.prototype=e,r=new Z),t&&I(t,r),r}var J=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function ee(e){return/\w/.test(e)||e>"€"&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ee(e))||t.test(e):ee(e)}function re(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var ne=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return e.charCodeAt(0)>=768&&ne.test(e)}function oe(e,t,r){for(;(r<0?t>0:t<e.length)&&ie(e.charAt(t));)t+=r;return t}function le(e,t,r){for(var n=t>r?-1:1;;){if(t==r)return t;var i=(t+r)/2,o=n<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:r;e(o)?r=o:t=o+n}}var se=null;function ae(e,t,r){var n;se=null;for(var i=0;i<e.length;++i){var o=e[i];if(o.from<t&&o.to>t)return i;o.to==t&&(o.from!=o.to&&"before"==r?n=i:se=i),o.from==t&&(o.from!=o.to&&"before"!=r?n=i:se=i)}return null!=n?n:se}var ue=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";var r=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,n=/[stwN]/,i=/[LRr]/,o=/[Lb1n]/,l=/[1n]/;function s(e,t,r){this.level=e,this.from=t,this.to=r}return function(a,u){var c="ltr"==u?"L":"R";if(0==a.length||"ltr"==u&&!r.test(a))return!1;for(var h,f=a.length,d=[],p=0;p<f;++p)d.push((h=a.charCodeAt(p))<=247?e.charAt(h):1424<=h&&h<=1524?"R":1536<=h&&h<=1785?t.charAt(h-1536):1774<=h&&h<=2220?"r":8192<=h&&h<=8203?"w":8204==h?"b":"L");for(var g=0,v=c;g<f;++g){var m=d[g];"m"==m?d[g]=v:v=m}for(var y=0,b=c;y<f;++y){var w=d[y];"1"==w&&"r"==b?d[y]="n":i.test(w)&&(b=w,"r"==w&&(d[y]="R"))}for(var x=1,C=d[0];x<f-1;++x){var S=d[x];"+"==S&&"1"==C&&"1"==d[x+1]?d[x]="1":","!=S||C!=d[x+1]||"1"!=C&&"n"!=C||(d[x]=C),C=S}for(var L=0;L<f;++L){var k=d[L];if(","==k)d[L]="N";else if("%"==k){var T=void 0;for(T=L+1;T<f&&"%"==d[T];++T);for(var M=L&&"!"==d[L-1]||T<f&&"1"==d[T]?"1":"N",N=L;N<T;++N)d[N]=M;L=T-1}}for(var O=0,A=c;O<f;++O){var D=d[O];"L"==A&&"1"==D?d[O]="L":i.test(D)&&(A=D)}for(var W=0;W<f;++W)if(n.test(d[W])){var H=void 0;for(H=W+1;H<f&&n.test(d[H]);++H);for(var F="L"==(W?d[W-1]:c),P=F==("L"==(H<f?d[H]:c))?F?"L":"R":c,E=W;E<H;++E)d[E]=P;W=H-1}for(var I,R=[],z=0;z<f;)if(o.test(d[z])){var B=z;for(++z;z<f&&o.test(d[z]);++z);R.push(new s(0,B,z))}else{var G=z,U=R.length,V="rtl"==u?1:0;for(++z;z<f&&"L"!=d[z];++z);for(var K=G;K<z;)if(l.test(d[K])){G<K&&(R.splice(U,0,new s(1,G,K)),U+=V);var j=K;for(++K;K<z&&l.test(d[K]);++K);R.splice(U,0,new s(2,j,K)),U+=V,G=K}else++K;G<z&&R.splice(U,0,new s(1,G,z))}return"ltr"==u&&(1==R[0].level&&(I=a.match(/^\s+/))&&(R[0].from=I[0].length,R.unshift(new s(0,0,I[0].length))),1==$(R).level&&(I=a.match(/\s+$/))&&($(R).to-=I[0].length,R.push(new s(0,f-I[0].length,f)))),"rtl"==u?R.reverse():R}}();function ce(e,t){var r=e.order;return null==r&&(r=e.order=ue(e.text,t)),r}var he=[],fe=function(e,t,r){if(e.addEventListener)e.addEventListener(t,r,!1);else if(e.attachEvent)e.attachEvent("on"+t,r);else{var n=e._handlers||(e._handlers={});n[t]=(n[t]||he).concat(r)}};function de(e,t){return e._handlers&&e._handlers[t]||he}function pe(e,t,r){if(e.removeEventListener)e.removeEventListener(t,r,!1);else if(e.detachEvent)e.detachEvent("on"+t,r);else{var n=e._handlers,i=n&&n[t];if(i){var o=B(i,r);o>-1&&(n[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function ge(e,t){var r=de(e,t);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i<r.length;++i)r[i].apply(null,n)}function ve(e,t,r){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),ge(e,r||t.type,e,t),Ce(t)||t.codemirrorIgnore}function me(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var r=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),n=0;n<t.length;++n)-1==B(r,t[n])&&r.push(t[n])}function ye(e,t){return de(e,t).length>0}function be(e){e.prototype.on=function(e,t){fe(this,e,t)},e.prototype.off=function(e,t){pe(this,e,t)}}function we(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function xe(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Ce(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Se(e){we(e),xe(e)}function Le(e){return e.target||e.srcElement}function ke(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Te,Me,Ne=function(){if(l&&s<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();function Oe(e){if(null==Te){var t=O("span","​");N(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Te=t.offsetWidth<=1&&t.offsetHeight>2&&!(l&&s<8))}var r=Te?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}function Ae(e){if(null!=Me)return Me;var t=N(e,document.createTextNode("AخA")),r=k(t,0,1).getBoundingClientRect(),n=k(t,1,2).getBoundingClientRect();return M(e),!(!r||r.left==r.right)&&(Me=n.right-r.right<3)}var De,We=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,r=[],n=e.length;t<=n;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(r.push(o.slice(0,l)),t+=l+1):(r.push(o),t=i+1)}return r}:function(e){return e.split(/\r\n?|\n/)},He=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Fe="oncopy"in(De=O("div"))||(De.setAttribute("oncopy","return;"),"function"==typeof De.oncopy),Pe=null;var Ee={},Ie={};function Re(e){if("string"==typeof e&&Ie.hasOwnProperty(e))e=Ie[e];else if(e&&"string"==typeof e.name&&Ie.hasOwnProperty(e.name)){var t=Ie[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Re("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Re("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function ze(e,t){t=Re(t);var r=Ee[t.name];if(!r)return ze(e,"text/plain");var n=r(e,t);if(Be.hasOwnProperty(t.name)){var i=Be[t.name];for(var o in i)i.hasOwnProperty(o)&&(n.hasOwnProperty(o)&&(n["_"+o]=n[o]),n[o]=i[o])}if(n.name=t.name,t.helperType&&(n.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)n[l]=t.modeProps[l];return n}var Be={};function Ge(e,t){I(t,Be.hasOwnProperty(e)?Be[e]:Be[e]={})}function Ue(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}function Ve(e,t){for(var r;e.innerMode&&(r=e.innerMode(t))&&r.mode!=e;)t=r.state,e=r.mode;return r||{mode:e,state:t}}function Ke(e,t,r){return!e.startState||e.startState(t,r)}var je=function(e,t,r){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=r};function Xe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(t<o){r=i;break}t-=o}return r.lines[t]}function Ye(e,t,r){var n=[],i=t.line;return e.iter(t.line,r.line+1,function(e){var o=e.text;i==r.line&&(o=o.slice(0,r.ch)),i==t.line&&(o=o.slice(t.ch)),n.push(o),++i}),n}function _e(e,t,r){var n=[];return e.iter(t,r,function(e){n.push(e.text)}),n}function $e(e,t){var r=t-e.height;if(r)for(var n=e;n;n=n.parent)n.height+=r}function qe(e){if(null==e.parent)return null;for(var t=e.parent,r=B(t.lines,e),n=t.parent;n;t=n,n=n.parent)for(var i=0;n.children[i]!=t;++i)r+=n.children[i].chunkSize();return r+t.first}function Ze(e,t){var r=e.first;e:do{for(var n=0;n<e.children.length;++n){var i=e.children[n],o=i.height;if(t<o){e=i;continue e}t-=o,r+=i.chunkSize()}return r}while(!e.lines);for(var l=0;l<e.lines.length;++l){var s=e.lines[l].height;if(t<s)break;t-=s}return r+l}function Qe(e,t){return t>=e.first&&t<e.first+e.size}function Je(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function et(e,t,r){if(void 0===r&&(r=null),!(this instanceof et))return new et(e,t,r);this.line=e,this.ch=t,this.sticky=r}function tt(e,t){return e.line-t.line||e.ch-t.ch}function rt(e,t){return e.sticky==t.sticky&&0==tt(e,t)}function nt(e){return et(e.line,e.ch)}function it(e,t){return tt(e,t)<0?t:e}function ot(e,t){return tt(e,t)<0?e:t}function lt(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function st(e,t){if(t.line<e.first)return et(e.first,0);var r=e.first+e.size-1;return t.line>r?et(r,Xe(e,r).text.length):function(e,t){var r=e.ch;return null==r||r>t?et(e.line,t):r<0?et(e.line,0):e}(t,Xe(e,t.line).text.length)}function at(e,t){for(var r=[],n=0;n<t.length;n++)r[n]=st(e,t[n]);return r}je.prototype.eol=function(){return this.pos>=this.string.length},je.prototype.sol=function(){return this.pos==this.lineStart},je.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},je.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},je.prototype.eat=function(e){var t=this.string.charAt(this.pos);if("string"==typeof e?t==e:t&&(e.test?e.test(t):e(t)))return++this.pos,t},je.prototype.eatWhile=function(e){for(var t=this.pos;this.eat(e););return this.pos>t},je.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},je.prototype.skipToEnd=function(){this.pos=this.string.length},je.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},je.prototype.backUp=function(e){this.pos-=e},je.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=R(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},je.prototype.indentation=function(){return R(this.string,null,this.tabSize)-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},je.prototype.match=function(e,t,r){if("string"!=typeof e){var n=this.string.slice(this.pos).match(e);return n&&n.index>0?null:(n&&!1!==t&&(this.pos+=n[0].length),n)}var i=function(e){return r?e.toLowerCase():e};if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},je.prototype.current=function(){return this.string.slice(this.start,this.pos)},je.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},je.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},je.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var ut=function(e,t){this.state=e,this.lookAhead=t},ct=function(e,t,r,n){this.state=t,this.doc=e,this.line=r,this.maxLookAhead=n||0,this.baseTokens=null,this.baseTokenPos=1};function ht(e,t,r,n){var i=[e.state.modeGen],o={};wt(e,t.text,e.doc.mode,r,function(e,t){return i.push(e,t)},o,n);for(var l=r.state,s=function(n){r.baseTokens=i;var s=e.state.overlays[n],a=1,u=0;r.state=!0,wt(e,t.text,s.mode,r,function(e,t){for(var r=a;u<e;){var n=i[a];n>e&&i.splice(a,1,e,i[a+1],n),a+=2,u=Math.min(e,n)}if(t)if(s.opaque)i.splice(r,a-r,e,"overlay "+t),a=r+2;else for(;r<a;r+=2){var o=i[r+1];i[r+1]=(o?o+" ":"")+"overlay "+t}},o),r.state=l,r.baseTokens=null,r.baseTokenPos=1},a=0;a<e.state.overlays.length;++a)s(a);return{styles:i,classes:o.bgClass||o.textClass?o:null}}function ft(e,t,r){if(!t.styles||t.styles[0]!=e.state.modeGen){var n=dt(e,qe(t)),i=t.text.length>e.options.maxHighlightLength&&Ue(e.doc.mode,n.state),o=ht(e,t,n);i&&(n.state=i),t.stateAfter=n.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function dt(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return new ct(n,!0,t);var o=function(e,t,r){for(var n,i,o=e.doc,l=r?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>l;--s){if(s<=o.first)return o.first;var a=Xe(o,s-1),u=a.stateAfter;if(u&&(!r||s+(u instanceof ut?u.lookAhead:0)<=o.modeFrontier))return s;var c=R(a.text,null,e.options.tabSize);(null==i||n>c)&&(i=s-1,n=c)}return i}(e,t,r),l=o>n.first&&Xe(n,o-1).stateAfter,s=l?ct.fromSaved(n,l,o):new ct(n,Ke(n.mode),o);return n.iter(o,t,function(r){pt(e,r.text,s);var n=s.line;r.stateAfter=n==t-1||n%5==0||n>=i.viewFrom&&n<i.viewTo?s.save():null,s.nextLine()}),r&&(n.modeFrontier=s.line),s}function pt(e,t,r,n){var i=e.doc.mode,o=new je(t,e.options.tabSize,r);for(o.start=o.pos=n||0,""==t&&gt(i,r.state);!o.eol();)vt(i,o,r.state),o.start=o.pos}function gt(e,t){if(e.blankLine)return e.blankLine(t);if(e.innerMode){var r=Ve(e,t);return r.mode.blankLine?r.mode.blankLine(r.state):void 0}}function vt(e,t,r,n){for(var i=0;i<10;i++){n&&(n[0]=Ve(e,r).mode);var o=e.token(t,r);if(t.pos>t.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}ct.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},ct.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},ct.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},ct.fromSaved=function(e,t,r){return t instanceof ut?new ct(e,Ue(e.mode,t.state),r,t.lookAhead):new ct(e,Ue(e.mode,t),r)},ct.prototype.save=function(e){var t=!1!==e?Ue(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new ut(t,this.maxLookAhead):t};var mt=function(e,t,r){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=r};function yt(e,t,r,n){var i,o,l=e.doc,s=l.mode,a=Xe(l,(t=st(l,t)).line),u=dt(e,t.line,r),c=new je(a.text,e.options.tabSize,u);for(n&&(o=[]);(n||c.pos<t.ch)&&!c.eol();)c.start=c.pos,i=vt(s,c,u.state),n&&o.push(new mt(c,i,Ue(l.mode,u.state)));return n?o:new mt(c,i,u.state)}function bt(e,t){if(e)for(;;){var r=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!r)break;e=e.slice(0,r.index)+e.slice(r.index+r[0].length);var n=r[1]?"bgClass":"textClass";null==t[n]?t[n]=r[2]:new RegExp("(?:^|\\s)"+r[2]+"(?:$|\\s)").test(t[n])||(t[n]+=" "+r[2])}return e}function wt(e,t,r,n,i,o,l){var s=r.flattenSpans;null==s&&(s=e.options.flattenSpans);var a,u=0,c=null,h=new je(t,e.options.tabSize,n),f=e.options.addModeClass&&[null];for(""==t&&bt(gt(r,n.state),o);!h.eol();){if(h.pos>e.options.maxHighlightLength?(s=!1,l&&pt(e,t,n,h.pos),h.pos=t.length,a=null):a=bt(vt(r,h,n.state,f),o),f){var d=f[0].name;d&&(a="m-"+(a?d+" "+a:d))}if(!s||c!=a){for(;u<h.start;)i(u=Math.min(h.start,u+5e3),c);c=a}h.start=h.pos}for(;u<h.pos;){var p=Math.min(h.pos,u+5e3);i(p,c),u=p}}var xt=!1,Ct=!1;function St(e,t,r){this.marker=e,this.from=t,this.to=r}function Lt(e,t){if(e)for(var r=0;r<e.length;++r){var n=e[r];if(n.marker==t)return n}}function kt(e,t){for(var r,n=0;n<e.length;++n)e[n]!=t&&(r||(r=[])).push(e[n]);return r}function Tt(e,t){if(t.full)return null;var r=Qe(e,t.from.line)&&Xe(e,t.from.line).markedSpans,n=Qe(e,t.to.line)&&Xe(e,t.to.line).markedSpans;if(!r&&!n)return null;var i=t.from.ch,o=t.to.ch,l=0==tt(t.from,t.to),s=function(e,t,r){var n;if(e)for(var i=0;i<e.length;++i){var o=e[i],l=o.marker;if(null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t)||o.from==t&&"bookmark"==l.type&&(!r||!o.marker.insertLeft)){var s=null==o.to||(l.inclusiveRight?o.to>=t:o.to>t);(n||(n=[])).push(new St(l,o.from,s?null:o.to))}}return n}(r,i,l),a=function(e,t,r){var n;if(e)for(var i=0;i<e.length;++i){var o=e[i],l=o.marker;if(null==o.to||(l.inclusiveRight?o.to>=t:o.to>t)||o.from==t&&"bookmark"==l.type&&(!r||o.marker.insertLeft)){var s=null==o.from||(l.inclusiveLeft?o.from<=t:o.from<t);(n||(n=[])).push(new St(l,s?null:o.from-t,null==o.to?null:o.to-t))}}return n}(n,o,l),u=1==t.text.length,c=$(t.text).length+(u?i:0);if(s)for(var h=0;h<s.length;++h){var f=s[h];if(null==f.to){var d=Lt(a,f.marker);d?u&&(f.to=null==d.to?null:d.to+c):f.to=i}}if(a)for(var p=0;p<a.length;++p){var g=a[p];if(null!=g.to&&(g.to+=c),null==g.from)Lt(s,g.marker)||(g.from=c,u&&(s||(s=[])).push(g));else g.from+=c,u&&(s||(s=[])).push(g)}s&&(s=Mt(s)),a&&a!=s&&(a=Mt(a));var v=[s];if(!u){var m,y=t.text.length-2;if(y>0&&s)for(var b=0;b<s.length;++b)null==s[b].to&&(m||(m=[])).push(new St(s[b].marker,null,null));for(var w=0;w<y;++w)v.push(m);v.push(a)}return v}function Mt(e){for(var t=0;t<e.length;++t){var r=e[t];null!=r.from&&r.from==r.to&&!1!==r.marker.clearWhenEmpty&&e.splice(t--,1)}return e.length?e:null}function Nt(e){var t=e.markedSpans;if(t){for(var r=0;r<t.length;++r)t[r].marker.detachLine(e);e.markedSpans=null}}function Ot(e,t){if(t){for(var r=0;r<t.length;++r)t[r].marker.attachLine(e);e.markedSpans=t}}function At(e){return e.inclusiveLeft?-1:0}function Dt(e){return e.inclusiveRight?1:0}function Wt(e,t){var r=e.lines.length-t.lines.length;if(0!=r)return r;var n=e.find(),i=t.find(),o=tt(n.from,i.from)||At(e)-At(t);if(o)return-o;var l=tt(n.to,i.to)||Dt(e)-Dt(t);return l||t.id-e.id}function Ht(e,t){var r,n=Ct&&e.markedSpans;if(n)for(var i=void 0,o=0;o<n.length;++o)(i=n[o]).marker.collapsed&&null==(t?i.from:i.to)&&(!r||Wt(r,i.marker)<0)&&(r=i.marker);return r}function Ft(e){return Ht(e,!0)}function Pt(e){return Ht(e,!1)}function Et(e,t){var r,n=Ct&&e.markedSpans;if(n)for(var i=0;i<n.length;++i){var o=n[i];o.marker.collapsed&&(null==o.from||o.from<t)&&(null==o.to||o.to>t)&&(!r||Wt(r,o.marker)<0)&&(r=o.marker)}return r}function It(e,t,r,n,i){var o=Xe(e,t),l=Ct&&o.markedSpans;if(l)for(var s=0;s<l.length;++s){var a=l[s];if(a.marker.collapsed){var u=a.marker.find(0),c=tt(u.from,r)||At(a.marker)-At(i),h=tt(u.to,n)||Dt(a.marker)-Dt(i);if(!(c>=0&&h<=0||c<=0&&h>=0)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.to,r)>=0:tt(u.to,r)>0)||c>=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.from,n)<=0:tt(u.from,n)<0)))return!0}}}function Rt(e){for(var t;t=Ft(e);)e=t.find(-1,!0).line;return e}function zt(e,t){var r=Xe(e,t),n=Rt(r);return r==n?t:qe(n)}function Bt(e,t){if(t>e.lastLine())return t;var r,n=Xe(e,t);if(!Gt(e,n))return t;for(;r=Pt(n);)n=r.find(1,!0).line;return qe(n)+1}function Gt(e,t){var r=Ct&&t.markedSpans;if(r)for(var n=void 0,i=0;i<r.length;++i)if((n=r[i]).marker.collapsed){if(null==n.from)return!0;if(!n.marker.widgetNode&&0==n.from&&n.marker.inclusiveLeft&&Ut(e,t,n))return!0}}function Ut(e,t,r){if(null==r.to){var n=r.marker.find(1,!0);return Ut(e,n.line,Lt(n.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==t.text.length)return!0;for(var i=void 0,o=0;o<t.markedSpans.length;++o)if((i=t.markedSpans[o]).marker.collapsed&&!i.marker.widgetNode&&i.from==r.to&&(null==i.to||i.to!=r.from)&&(i.marker.inclusiveLeft||r.marker.inclusiveRight)&&Ut(e,t,i))return!0}function Vt(e){for(var t=0,r=(e=Rt(e)).parent,n=0;n<r.lines.length;++n){var i=r.lines[n];if(i==e)break;t+=i.height}for(var o=r.parent;o;o=(r=o).parent)for(var l=0;l<o.children.length;++l){var s=o.children[l];if(s==r)break;t+=s.height}return t}function Kt(e){if(0==e.height)return 0;for(var t,r=e.text.length,n=e;t=Ft(n);){var i=t.find(0,!0);n=i.from.line,r+=i.from.ch-i.to.ch}for(n=e;t=Pt(n);){var o=t.find(0,!0);r-=n.text.length-o.from.ch,r+=(n=o.to.line).text.length-o.to.ch}return r}function jt(e){var t=e.display,r=e.doc;t.maxLine=Xe(r,r.first),t.maxLineLength=Kt(t.maxLine),t.maxLineChanged=!0,r.iter(function(e){var r=Kt(e);r>t.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)})}var Xt=function(e,t,r){this.text=e,Ot(this,t),this.height=r?r(this):1};function Yt(e){e.parent=null,Nt(e)}Xt.prototype.lineNo=function(){return qe(this)},be(Xt);var _t={},$t={};function qt(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?$t:_t;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function Zt(e,t){var r=A("span",null,null,a?"padding-right: .1px":null),n={pre:A("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,l=void 0;n.pos=0,n.addToken=Jt,Ae(e.display.measure)&&(l=ce(o,e.doc.direction))&&(n.addToken=er(n.addToken,l)),n.map=[],rr(o,n,ft(e,o,t!=e.display.externalMeasured&&qe(o))),o.styleClasses&&(o.styleClasses.bgClass&&(n.bgClass=F(o.styleClasses.bgClass,n.bgClass||"")),o.styleClasses.textClass&&(n.textClass=F(o.styleClasses.textClass,n.textClass||""))),0==n.map.length&&n.map.push(0,0,n.content.appendChild(Oe(e.display.measure))),0==i?(t.measure.map=n.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(n.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(a){var s=n.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(n.content.className="cm-tab-wrap-hack")}return ge(e,"renderLine",e,t.line,n.pre),n.pre.className&&(n.textClass=F(n.pre.className,n.textClass||"")),n}function Qt(e){var t=O("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function Jt(e,t,r,n,i,o,a){if(t){var u,c=e.splitSpaces?function(e,t){if(e.length>1&&!/ /.test(e))return e;for(var r=t,n="",i=0;i<e.length;i++){var o=e.charAt(i);" "!=o||!r||i!=e.length-1&&32!=e.charCodeAt(i+1)||(o=" "),n+=o,r=" "==o}return n}(t,e.trailingSpace):t,h=e.cm.state.specialChars,f=!1;if(h.test(t)){u=document.createDocumentFragment();for(var d=0;;){h.lastIndex=d;var p=h.exec(t),g=p?p.index-d:t.length-d;if(g){var v=document.createTextNode(c.slice(d,d+g));l&&s<9?u.appendChild(O("span",[v])):u.appendChild(v),e.map.push(e.pos,e.pos+g,v),e.col+=g,e.pos+=g}if(!p)break;d+=g+1;var m=void 0;if("\t"==p[0]){var y=e.cm.options.tabSize,b=y-e.col%y;(m=u.appendChild(O("span",_(b),"cm-tab"))).setAttribute("role","presentation"),m.setAttribute("cm-text","\t"),e.col+=b}else"\r"==p[0]||"\n"==p[0]?((m=u.appendChild(O("span","\r"==p[0]?"␍":"␤","cm-invalidchar"))).setAttribute("cm-text",p[0]),e.col+=1):((m=e.cm.options.specialCharPlaceholder(p[0])).setAttribute("cm-text",p[0]),l&&s<9?u.appendChild(O("span",[m])):u.appendChild(m),e.col+=1);e.map.push(e.pos,e.pos+1,m),e.pos++}}else e.col+=t.length,u=document.createTextNode(c),e.map.push(e.pos,e.pos+t.length,u),l&&s<9&&(f=!0),e.pos+=t.length;if(e.trailingSpace=32==c.charCodeAt(t.length-1),r||n||i||f||o||a){var w=r||"";n&&(w+=n),i&&(w+=i);var x=O("span",[u],w,o);if(a)for(var C in a)a.hasOwnProperty(C)&&"style"!=C&&"class"!=C&&x.setAttribute(C,a[C]);return e.content.appendChild(x)}e.content.appendChild(u)}}function er(e,t){return function(r,n,i,o,l,s,a){i=i?i+" cm-force-border":"cm-force-border";for(var u=r.pos,c=u+n.length;;){for(var h=void 0,f=0;f<t.length&&!((h=t[f]).to>u&&h.from<=u);f++);if(h.to>=c)return e(r,n,i,o,l,s,a);e(r,n.slice(0,h.to-u),i,o,null,s,a),o=null,n=n.slice(h.to-u),u=h.to}}}function tr(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function rr(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var l,s,a,u,c,h,f,d=i.length,p=0,g=1,v="",m=0;;){if(m==p){a=u=c=s="",f=null,h=null,m=1/0;for(var y=[],b=void 0,w=0;w<n.length;++w){var x=n[w],C=x.marker;if("bookmark"==C.type&&x.from==p&&C.widgetNode)y.push(C);else if(x.from<=p&&(null==x.to||x.to>p||C.collapsed&&x.to==p&&x.from==p)){if(null!=x.to&&x.to!=p&&m>x.to&&(m=x.to,u=""),C.className&&(a+=" "+C.className),C.css&&(s=(s?s+";":"")+C.css),C.startStyle&&x.from==p&&(c+=" "+C.startStyle),C.endStyle&&x.to==m&&(b||(b=[])).push(C.endStyle,x.to),C.title&&((f||(f={})).title=C.title),C.attributes)for(var S in C.attributes)(f||(f={}))[S]=C.attributes[S];C.collapsed&&(!h||Wt(h.marker,C)<0)&&(h=x)}else x.from>p&&m>x.from&&(m=x.from)}if(b)for(var L=0;L<b.length;L+=2)b[L+1]==m&&(u+=" "+b[L]);if(!h||h.from==p)for(var k=0;k<y.length;++k)tr(t,0,y[k]);if(h&&(h.from||0)==p){if(tr(t,(null==h.to?d+1:h.to)-p,h.marker,null==h.from),null==h.to)return;h.to==p&&(h=!1)}}if(p>=d)break;for(var T=Math.min(d,m);;){if(v){var M=p+v.length;if(!h){var N=M>T?v.slice(0,T-p):v;t.addToken(t,N,l?l+a:a,c,p+N.length==m?u:"",s,f)}if(M>=T){v=v.slice(T-p),p=T;break}p=M,c=""}v=i.slice(o,o=r[g++]),l=qt(r[g++],t.cm.options)}}else for(var O=1;O<r.length;O+=2)t.addToken(t,i.slice(o,o=r[O]),qt(r[O+1],t.cm.options))}function nr(e,t,r){this.line=t,this.rest=function(e){for(var t,r;t=Pt(e);)e=t.find(1,!0).line,(r||(r=[])).push(e);return r}(t),this.size=this.rest?qe($(this.rest))-r+1:1,this.node=this.text=null,this.hidden=Gt(e,t)}function ir(e,t,r){for(var n,i=[],o=t;o<r;o=n){var l=new nr(e.doc,Xe(e.doc,o),o);n=o+l.size,i.push(l)}return i}var or=null;var lr=null;function sr(e,t){var r=de(e,t);if(r.length){var n,i=Array.prototype.slice.call(arguments,2);or?n=or.delayedCallbacks:lr?n=lr:(n=lr=[],setTimeout(ar,0));for(var o=function(e){n.push(function(){return r[e].apply(null,i)})},l=0;l<r.length;++l)o(l)}}function ar(){var e=lr;lr=null;for(var t=0;t<e.length;++t)e[t]()}function ur(e,t,r,n){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?fr(e,t):"gutter"==o?pr(e,t,r,n):"class"==o?dr(e,t):"widget"==o&&gr(e,t,n)}t.changes=null}function cr(e){return e.node==e.text&&(e.node=O("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),l&&s<8&&(e.node.style.zIndex=2)),e.node}function hr(e,t){var r=e.display.externalMeasured;return r&&r.line==t.line?(e.display.externalMeasured=null,t.measure=r.measure,r.built):Zt(e,t)}function fr(e,t){var r=t.text.className,n=hr(e,t);t.text==t.node&&(t.node=n.pre),t.text.parentNode.replaceChild(n.pre,t.text),t.text=n.pre,n.bgClass!=t.bgClass||n.textClass!=t.textClass?(t.bgClass=n.bgClass,t.textClass=n.textClass,dr(e,t)):r&&(t.text.className=r)}function dr(e,t){!function(e,t){var r=t.bgClass?t.bgClass+" "+(t.line.bgClass||""):t.line.bgClass;if(r&&(r+=" CodeMirror-linebackground"),t.background)r?t.background.className=r:(t.background.parentNode.removeChild(t.background),t.background=null);else if(r){var n=cr(t);t.background=n.insertBefore(O("div",null,r),n.firstChild),e.display.input.setUneditable(t.background)}}(e,t),t.line.wrapClass?cr(t).className=t.line.wrapClass:t.node!=t.text&&(t.node.className="");var r=t.textClass?t.textClass+" "+(t.line.textClass||""):t.line.textClass;t.text.className=r||""}function pr(e,t,r,n){if(t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null),t.gutterBackground&&(t.node.removeChild(t.gutterBackground),t.gutterBackground=null),t.line.gutterClass){var i=cr(t);t.gutterBackground=O("div",null,"CodeMirror-gutter-background "+t.line.gutterClass,"left: "+(e.options.fixedGutter?n.fixedPos:-n.gutterTotalWidth)+"px; width: "+n.gutterTotalWidth+"px"),e.display.input.setUneditable(t.gutterBackground),i.insertBefore(t.gutterBackground,t.text)}var o=t.line.gutterMarkers;if(e.options.lineNumbers||o){var l=cr(t),s=t.gutter=O("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?n.fixedPos:-n.gutterTotalWidth)+"px");if(e.display.input.setUneditable(s),l.insertBefore(s,t.text),t.line.gutterClass&&(s.className+=" "+t.line.gutterClass),!e.options.lineNumbers||o&&o["CodeMirror-linenumbers"]||(t.lineNumber=s.appendChild(O("div",Je(e.options,r),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+n.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),o)for(var a=0;a<e.display.gutterSpecs.length;++a){var u=e.display.gutterSpecs[a].className,c=o.hasOwnProperty(u)&&o[u];c&&s.appendChild(O("div",[c],"CodeMirror-gutter-elt","left: "+n.gutterLeft[u]+"px; width: "+n.gutterWidth[u]+"px"))}}}function gr(e,t,r){t.alignable&&(t.alignable=null);for(var n=L("CodeMirror-linewidget"),i=t.node.firstChild,o=void 0;i;i=o)o=i.nextSibling,n.test(i.className)&&t.node.removeChild(i);mr(e,t,r)}function vr(e,t,r,n){var i=hr(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),dr(e,t),pr(e,t,r,n),mr(e,t,n),t.node}function mr(e,t,r){if(yr(e,t.line,t,r,!0),t.rest)for(var n=0;n<t.rest.length;n++)yr(e,t.rest[n],t,r,!1)}function yr(e,t,r,n,i){if(t.widgets)for(var o=cr(r),l=0,s=t.widgets;l<s.length;++l){var a=s[l],u=O("div",[a.node],"CodeMirror-linewidget"+(a.className?" "+a.className:""));a.handleMouseEvents||u.setAttribute("cm-ignore-events","true"),br(a,u,r,n),e.display.input.setUneditable(u),i&&a.above?o.insertBefore(u,r.gutter||r.text):o.appendChild(u),sr(a,"redraw")}}function br(e,t,r,n){if(e.noHScroll){(r.alignable||(r.alignable=[])).push(t);var i=n.wrapperWidth;t.style.left=n.fixedPos+"px",e.coverGutter||(i-=n.gutterTotalWidth,t.style.paddingLeft=n.gutterTotalWidth+"px"),t.style.width=i+"px"}e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-n.gutterTotalWidth+"px"))}function wr(e){if(null!=e.height)return e.height;var t=e.doc.cm;if(!t)return 0;if(!D(document.body,e.node)){var r="position: relative;";e.coverGutter&&(r+="margin-left: -"+t.display.gutters.offsetWidth+"px;"),e.noHScroll&&(r+="width: "+t.display.wrapper.clientWidth+"px;"),N(t.display.measure,O("div",[e.node],null,r))}return e.height=e.node.parentNode.offsetHeight}function xr(e,t){for(var r=Le(t);r!=e.wrapper;r=r.parentNode)if(!r||1==r.nodeType&&"true"==r.getAttribute("cm-ignore-events")||r.parentNode==e.sizer&&r!=e.mover)return!0}function Cr(e){return e.lineSpace.offsetTop}function Sr(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function Lr(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=N(e.measure,O("pre","x","CodeMirror-line-like")),r=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,n={left:parseInt(r.paddingLeft),right:parseInt(r.paddingRight)};return isNaN(n.left)||isNaN(n.right)||(e.cachedPaddingH=n),n}function kr(e){return G-e.display.nativeBarWidth}function Tr(e){return e.display.scroller.clientWidth-kr(e)-e.display.barWidth}function Mr(e){return e.display.scroller.clientHeight-kr(e)-e.display.barHeight}function Nr(e,t,r){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var n=0;n<e.rest.length;n++)if(e.rest[n]==t)return{map:e.measure.maps[n],cache:e.measure.caches[n]};for(var i=0;i<e.rest.length;i++)if(qe(e.rest[i])>r)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Or(e,t,r,n){return Wr(e,Dr(e,t),r,n)}function Ar(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[an(e,t)];var r=e.display.externalMeasured;return r&&t>=r.lineN&&t<r.lineN+r.size?r:void 0}function Dr(e,t){var r=qe(t),n=Ar(e,r);n&&!n.text?n=null:n&&n.changes&&(ur(e,n,r,rn(e)),e.curOp.forceUpdate=!0),n||(n=function(e,t){var r=qe(t=Rt(t)),n=e.display.externalMeasured=new nr(e.doc,t,r);n.lineN=r;var i=n.built=Zt(e,n);return n.text=i.pre,N(e.display.lineMeasure,i.pre),n}(e,t));var i=Nr(n,t,r);return{line:t,view:n,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function Wr(e,t,r,n,i){t.before&&(r=-1);var o,a=r+(n||"");return t.cache.hasOwnProperty(a)?o=t.cache[a]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||(!function(e,t,r){var n=e.options.lineWrapping,i=n&&Tr(e);if(!t.measure.heights||n&&t.measure.width!=i){var o=t.measure.heights=[];if(n){t.measure.width=i;for(var l=t.text.firstChild.getClientRects(),s=0;s<l.length-1;s++){var a=l[s],u=l[s+1];Math.abs(a.bottom-u.bottom)>2&&o.push((a.bottom+u.top)/2-r.top)}}o.push(r.bottom-r.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,r,n){var i,o=Pr(t.map,r,n),a=o.node,u=o.start,c=o.end,h=o.collapse;if(3==a.nodeType){for(var f=0;f<4;f++){for(;u&&ie(t.line.text.charAt(o.coverStart+u));)--u;for(;o.coverStart+c<o.coverEnd&&ie(t.line.text.charAt(o.coverStart+c));)++c;if((i=l&&s<9&&0==u&&c==o.coverEnd-o.coverStart?a.parentNode.getBoundingClientRect():Er(k(a,u,c).getClientRects(),n)).left||i.right||0==u)break;c=u,u-=1,h="right"}l&&s<11&&(i=function(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!function(e){if(null!=Pe)return Pe;var t=N(e,O("span","x")),r=t.getBoundingClientRect(),n=k(t,0,1).getBoundingClientRect();return Pe=Math.abs(r.left-n.left)>1}(e))return t;var r=screen.logicalXDPI/screen.deviceXDPI,n=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*r,right:t.right*r,top:t.top*n,bottom:t.bottom*n}}(e.display.measure,i))}else{var d;u>0&&(h=n="right"),i=e.options.lineWrapping&&(d=a.getClientRects()).length>1?d["right"==n?d.length-1:0]:a.getBoundingClientRect()}if(l&&s<9&&!u&&(!i||!i.left&&!i.right)){var p=a.parentNode.getClientRects()[0];i=p?{left:p.left,right:p.left+tn(e.display),top:p.top,bottom:p.bottom}:Fr}for(var g=i.top-t.rect.top,v=i.bottom-t.rect.top,m=(g+v)/2,y=t.view.measure.heights,b=0;b<y.length-1&&!(m<y[b]);b++);var w=b?y[b-1]:0,x=y[b],C={left:("right"==h?i.right:i.left)-t.rect.left,right:("left"==h?i.left:i.right)-t.rect.left,top:w,bottom:x};i.left||i.right||(C.bogus=!0);e.options.singleCursorHeightPerLine||(C.rtop=g,C.rbottom=v);return C}(e,t,r,n)).bogus||(t.cache[a]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}var Hr,Fr={left:0,right:0,top:0,bottom:0};function Pr(e,t,r){for(var n,i,o,l,s,a,u=0;u<e.length;u+=3)if(s=e[u],a=e[u+1],t<s?(i=0,o=1,l="left"):t<a?o=(i=t-s)+1:(u==e.length-3||t==a&&e[u+3]>t)&&(i=(o=a-s)-1,t>=a&&(l="right")),null!=i){if(n=e[u+2],s==a&&r==(n.insertLeft?"left":"right")&&(l=r),"left"==r&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)n=e[2+(u-=3)],l="left";if("right"==r&&i==a-s)for(;u<e.length-3&&e[u+3]==e[u+4]&&!e[u+5].insertLeft;)n=e[(u+=3)+2],l="right";break}return{node:n,start:i,end:o,collapse:l,coverStart:s,coverEnd:a}}function Er(e,t){var r=Fr;if("left"==t)for(var n=0;n<e.length&&(r=e[n]).left==r.right;n++);else for(var i=e.length-1;i>=0&&(r=e[i]).left==r.right;i--);return r}function Ir(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function Rr(e){e.display.externalMeasure=null,M(e.display.lineMeasure);for(var t=0;t<e.display.view.length;t++)Ir(e.display.view[t])}function zr(e){Rr(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function Br(){return c&&v?-(document.body.getBoundingClientRect().left-parseInt(getComputedStyle(document.body).marginLeft)):window.pageXOffset||(document.documentElement||document.body).scrollLeft}function Gr(){return c&&v?-(document.body.getBoundingClientRect().top-parseInt(getComputedStyle(document.body).marginTop)):window.pageYOffset||(document.documentElement||document.body).scrollTop}function Ur(e){var t=0;if(e.widgets)for(var r=0;r<e.widgets.length;++r)e.widgets[r].above&&(t+=wr(e.widgets[r]));return t}function Vr(e,t,r,n,i){if(!i){var o=Ur(t);r.top+=o,r.bottom+=o}if("line"==n)return r;n||(n="local");var l=Vt(t);if("local"==n?l+=Cr(e.display):l-=e.display.viewOffset,"page"==n||"window"==n){var s=e.display.lineSpace.getBoundingClientRect();l+=s.top+("window"==n?0:Gr());var a=s.left+("window"==n?0:Br());r.left+=a,r.right+=a}return r.top+=l,r.bottom+=l,r}function Kr(e,t,r){if("div"==r)return t;var n=t.left,i=t.top;if("page"==r)n-=Br(),i-=Gr();else if("local"==r||!r){var o=e.display.sizer.getBoundingClientRect();n+=o.left,i+=o.top}var l=e.display.lineSpace.getBoundingClientRect();return{left:n-l.left,top:i-l.top}}function jr(e,t,r,n,i){return n||(n=Xe(e.doc,t.line)),Vr(e,n,Or(e,n,t.ch,i),r)}function Xr(e,t,r,n,i,o){function l(t,l){var s=Wr(e,i,t,l?"right":"left",o);return l?s.left=s.right:s.right=s.left,Vr(e,n,s,r)}n=n||Xe(e.doc,t.line),i||(i=Dr(e,n));var s=ce(n,e.doc.direction),a=t.ch,u=t.sticky;if(a>=n.text.length?(a=n.text.length,u="before"):a<=0&&(a=0,u="after"),!s)return l("before"==u?a-1:a,"before"==u);function c(e,t,r){return l(r?e-1:e,1==s[t].level!=r)}var h=ae(s,a,u),f=se,d=c(a,h,"before"==u);return null!=f&&(d.other=c(a,f,"before"!=u)),d}function Yr(e,t){var r=0;t=st(e.doc,t),e.options.lineWrapping||(r=tn(e.display)*t.ch);var n=Xe(e.doc,t.line),i=Vt(n)+Cr(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function _r(e,t,r,n,i){var o=et(e,t,r);return o.xRel=i,n&&(o.outside=n),o}function $r(e,t,r){var n=e.doc;if((r+=e.display.viewOffset)<0)return _r(n.first,0,null,-1,-1);var i=Ze(n,r),o=n.first+n.size-1;if(i>o)return _r(n.first+n.size-1,Xe(n,o).text.length,null,1,1);t<0&&(t=0);for(var l=Xe(n,i);;){var s=Jr(e,l,i,t,r),a=Et(l,s.ch+(s.xRel>0||s.outside>0?1:0));if(!a)return s;var u=a.find(1);if(u.line==i)return u;l=Xe(n,i=u.line)}}function qr(e,t,r,n){n-=Ur(t);var i=t.text.length,o=le(function(t){return Wr(e,r,t-1).bottom<=n},i,0);return{begin:o,end:i=le(function(t){return Wr(e,r,t).top>n},o,i)}}function Zr(e,t,r,n){return r||(r=Dr(e,t)),qr(e,t,r,Vr(e,t,Wr(e,r,n),"line").top)}function Qr(e,t,r,n){return!(e.bottom<=r)&&(e.top>r||(n?e.left:e.right)>t)}function Jr(e,t,r,n,i){i-=Vt(t);var o=Dr(e,t),l=Ur(t),s=0,a=t.text.length,u=!0,c=ce(t,e.doc.direction);if(c){var h=(e.options.lineWrapping?function(e,t,r,n,i,o,l){var s=qr(e,t,n,l),a=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,h=null,f=0;f<i.length;f++){var d=i[f];if(!(d.from>=u||d.to<=a)){var p=1!=d.level,g=Wr(e,n,p?Math.min(u,d.to)-1:Math.max(a,d.from)).right,v=g<o?o-g+1e9:g-o;(!c||h>v)&&(c=d,h=v)}}c||(c=i[i.length-1]);c.from<a&&(c={from:a,to:c.to,level:c.level});c.to>u&&(c={from:c.from,to:u,level:c.level});return c}:function(e,t,r,n,i,o,l){var s=le(function(s){var a=i[s],u=1!=a.level;return Qr(Xr(e,et(r,u?a.to:a.from,u?"before":"after"),"line",t,n),o,l,!0)},0,i.length-1),a=i[s];if(s>0){var u=1!=a.level,c=Xr(e,et(r,u?a.from:a.to,u?"after":"before"),"line",t,n);Qr(c,o,l,!0)&&c.top>l&&(a=i[s-1])}return a})(e,t,r,o,c,n,i);s=(u=1!=h.level)?h.from:h.to-1,a=u?h.to:h.from-1}var f,d,p=null,g=null,v=le(function(t){var r=Wr(e,o,t);return r.top+=l,r.bottom+=l,!!Qr(r,n,i,!1)&&(r.top<=i&&r.left<=n&&(p=t,g=r),!0)},s,a),m=!1;if(g){var y=n-g.left<g.right-n,b=y==u;v=p+(b?0:1),d=b?"after":"before",f=y?g.left:g.right}else{u||v!=a&&v!=s||v++,d=0==v?"after":v==t.text.length?"before":Wr(e,o,v-(u?1:0)).bottom+l<=i==u?"after":"before";var w=Xr(e,et(r,v,d),"line",t,o);f=w.left,m=i<w.top?-1:i>=w.bottom?1:0}return _r(r,v=oe(t.text,v,1),d,m,n-f)}function en(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Hr){Hr=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Hr.appendChild(document.createTextNode("x")),Hr.appendChild(O("br"));Hr.appendChild(document.createTextNode("x"))}N(e.measure,Hr);var r=Hr.offsetHeight/50;return r>3&&(e.cachedTextHeight=r),M(e.measure),r||1}function tn(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),r=O("pre",[t],"CodeMirror-line-like");N(e.measure,r);var n=t.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function rn(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;r[s]=o.offsetLeft+o.clientLeft+i,n[s]=o.clientWidth}return{fixedPos:nn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function nn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function on(e){var t=en(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/tn(e.display)-3);return function(i){if(Gt(e.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l<i.widgets.length;l++)i.widgets[l].height&&(o+=i.widgets[l].height);return r?o+(Math.ceil(i.text.length/n)||1)*t:o+t}}function ln(e){var t=e.doc,r=on(e);t.iter(function(e){var t=r(e);t!=e.height&&$e(e,t)})}function sn(e,t,r,n){var i=e.display;if(!r&&"true"==Le(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(e){return null}var a,u=$r(e,o,l);if(n&&u.xRel>0&&(a=Xe(e.doc,u.line).text).length==u.ch){var c=R(a,a.length,e.options.tabSize)-a.length;u=et(u.line,Math.max(0,Math.round((o-Lr(e.display).left)/tn(e.display))-c))}return u}function an(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var r=e.display.view,n=0;n<r.length;n++)if((t-=r[n].size)<0)return n}function un(e,t,r,n){null==t&&(t=e.doc.first),null==r&&(r=e.doc.first+e.doc.size),n||(n=0);var i=e.display;if(n&&r<i.viewTo&&(null==i.updateLineNumbers||i.updateLineNumbers>t)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Ct&&zt(e.doc,t)<i.viewTo&&hn(e);else if(r<=i.viewFrom)Ct&&Bt(e.doc,r+n)>i.viewFrom?hn(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)hn(e);else if(t<=i.viewFrom){var o=fn(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):hn(e)}else if(r>=i.viewTo){var l=fn(e,t,t,-1);l?(i.view=i.view.slice(0,l.index),i.viewTo=l.lineN):hn(e)}else{var s=fn(e,t,t,-1),a=fn(e,r,r+n,1);s&&a?(i.view=i.view.slice(0,s.index).concat(ir(e,s.lineN,a.lineN)).concat(i.view.slice(a.index)),i.viewTo+=n):hn(e)}var u=i.externalMeasured;u&&(r<u.lineN?u.lineN+=n:t<u.lineN+u.size&&(i.externalMeasured=null))}function cn(e,t,r){e.curOp.viewChanged=!0;var n=e.display,i=e.display.externalMeasured;if(i&&t>=i.lineN&&t<i.lineN+i.size&&(n.externalMeasured=null),!(t<n.viewFrom||t>=n.viewTo)){var o=n.view[an(e,t)];if(null!=o.node){var l=o.changes||(o.changes=[]);-1==B(l,r)&&l.push(r)}}}function hn(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function fn(e,t,r,n){var i,o=an(e,t),l=e.display.view;if(!Ct||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var s=e.display.viewFrom,a=0;a<o;a++)s+=l[a].size;if(s!=t){if(n>0){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,r+=i}for(;zt(e.doc,r)!=r;){if(o==(n<0?0:l.length-1))return null;r+=n*l[o-(n<0?1:0)].size,o+=n}return{index:o,lineN:r}}function dn(e){for(var t=e.display.view,r=0,n=0;n<t.length;n++){var i=t[n];i.hidden||i.node&&!i.changes||++r}return r}function pn(e){e.display.input.showSelection(e.display.input.prepareSelection())}function gn(e,t){void 0===t&&(t=!0);for(var r=e.doc,n={},i=n.cursors=document.createDocumentFragment(),o=n.selection=document.createDocumentFragment(),l=0;l<r.sel.ranges.length;l++)if(t||l!=r.sel.primIndex){var s=r.sel.ranges[l];if(!(s.from().line>=e.display.viewTo||s.to().line<e.display.viewFrom)){var a=s.empty();(a||e.options.showCursorWhenSelecting)&&vn(e,s.head,i),a||yn(e,s,o)}}return n}function vn(e,t,r){var n=Xr(e,t,"div",null,null,!e.options.singleCursorHeightPerLine),i=r.appendChild(O("div"," ","CodeMirror-cursor"));if(i.style.left=n.left+"px",i.style.top=n.top+"px",i.style.height=Math.max(0,n.bottom-n.top)*e.options.cursorHeight+"px",n.other){var o=r.appendChild(O("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));o.style.display="",o.style.left=n.other.left+"px",o.style.top=n.other.top+"px",o.style.height=.85*(n.other.bottom-n.other.top)+"px"}}function mn(e,t){return e.top-t.top||e.left-t.left}function yn(e,t,r){var n=e.display,i=e.doc,o=document.createDocumentFragment(),l=Lr(e.display),s=l.left,a=Math.max(n.sizerWidth,Tr(e)-n.sizer.offsetLeft)-l.right,u="ltr"==i.direction;function c(e,t,r,n){t<0&&(t=0),t=Math.round(t),n=Math.round(n),o.appendChild(O("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==r?a-e:r)+"px;\n height: "+(n-t)+"px"))}function h(t,r,n){var o,l,h=Xe(i,t),f=h.text.length;function d(r,n){return jr(e,et(t,r),"div",h,n)}function p(t,r,n){var i=Zr(e,h,null,t),o="ltr"==r==("after"==n)?"left":"right";return d("after"==n?i.begin:i.end-(/\s/.test(h.text.charAt(i.end-1))?2:1),o)[o]}var g=ce(h,i.direction);return function(e,t,r,n){if(!e)return n(t,r,"ltr",0);for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<r&&l.to>t||t==r&&l.to==t)&&(n(Math.max(l.from,t),Math.min(l.to,r),1==l.level?"rtl":"ltr",o),i=!0)}i||n(t,r,"ltr")}(g,r||0,null==n?f:n,function(e,t,i,h){var v="ltr"==i,m=d(e,v?"left":"right"),y=d(t-1,v?"right":"left"),b=null==r&&0==e,w=null==n&&t==f,x=0==h,C=!g||h==g.length-1;if(y.top-m.top<=3){var S=(u?w:b)&&C,L=(u?b:w)&&x?s:(v?m:y).left,k=S?a:(v?y:m).right;c(L,m.top,k-L,m.bottom)}else{var T,M,N,O;v?(T=u&&b&&x?s:m.left,M=u?a:p(e,i,"before"),N=u?s:p(t,i,"after"),O=u&&w&&C?a:y.right):(T=u?p(e,i,"before"):s,M=!u&&b&&x?a:m.right,N=!u&&w&&C?s:y.left,O=u?p(t,i,"after"):a),c(T,m.top,M-T,m.bottom),m.bottom<y.top&&c(s,m.bottom,null,y.top),c(N,y.top,O-N,y.bottom)}(!o||mn(m,o)<0)&&(o=m),mn(y,o)<0&&(o=y),(!l||mn(m,l)<0)&&(l=m),mn(y,l)<0&&(l=y)}),{start:o,end:l}}var f=t.from(),d=t.to();if(f.line==d.line)h(f.line,f.ch,d.ch);else{var p=Xe(i,f.line),g=Xe(i,d.line),v=Rt(p)==Rt(g),m=h(f.line,f.ch,v?p.text.length+1:null).end,y=h(d.line,v?0:null,d.ch).start;v&&(m.top<y.top-2?(c(m.right,m.top,null,m.bottom),c(s,y.top,y.left,y.bottom)):c(m.right,m.top,y.left-m.right,m.bottom)),m.bottom<y.top&&c(s,m.bottom,null,y.top)}r.appendChild(o)}function bn(e){if(e.state.focused){var t=e.display;clearInterval(t.blinker);var r=!0;t.cursorDiv.style.visibility="",e.options.cursorBlinkRate>0?t.blinker=setInterval(function(){e.hasFocus()||Sn(e),t.cursorDiv.style.visibility=(r=!r)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function wn(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||Cn(e))}function xn(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&Sn(e))},100)}function Cn(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ge(e,"focus",e,t),e.state.focused=!0,H(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),a&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),bn(e))}function Sn(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ge(e,"blur",e,t),e.state.focused=!1,T(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function Ln(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=0;n<t.view.length;n++){var i=t.view[n],o=e.options.lineWrapping,a=void 0,u=0;if(!i.hidden){if(l&&s<8){var c=i.node.offsetTop+i.node.offsetHeight;a=c-r,r=c}else{var h=i.node.getBoundingClientRect();a=h.bottom-h.top,!o&&i.text.firstChild&&(u=i.text.firstChild.getBoundingClientRect().right-h.left-1)}var f=i.line.height-a;if((f>.005||f<-.005)&&($e(i.line,a),kn(i.line),i.rest))for(var d=0;d<i.rest.length;d++)kn(i.rest[d]);if(u>e.display.sizerWidth){var p=Math.ceil(u/tn(e.display));p>e.display.maxLineLength&&(e.display.maxLineLength=p,e.display.maxLine=i.line,e.display.maxLineChanged=!0)}}}}function kn(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t){var r=e.widgets[t],n=r.node.parentNode;n&&(r.height=n.offsetHeight)}}function Tn(e,t,r){var n=r&&null!=r.top?Math.max(0,r.top):e.scroller.scrollTop;n=Math.floor(n-Cr(e));var i=r&&null!=r.bottom?r.bottom:n+e.wrapper.clientHeight,o=Ze(t,n),l=Ze(t,i);if(r&&r.ensure){var s=r.ensure.from.line,a=r.ensure.to.line;s<o?(o=s,l=Ze(t,Vt(Xe(t,s))+e.wrapper.clientHeight)):Math.min(a,t.lastLine())>=l&&(o=Ze(t,Vt(Xe(t,a))-e.wrapper.clientHeight),l=a)}return{from:o,to:Math.max(l,o+1)}}function Mn(e,t){var r=e.display,n=en(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:r.scroller.scrollTop,o=Mr(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s=e.doc.height+Sr(r),a=t.top<n,u=t.bottom>s-n;if(t.top<i)l.scrollTop=a?0:t.top;else if(t.bottom>i+o){var c=Math.min(t.top,(u?s:t.bottom)-o);c!=i&&(l.scrollTop=c)}var h=e.options.fixedGutter?0:r.gutters.offsetWidth,f=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:r.scroller.scrollLeft-h,d=Tr(e)-r.gutters.offsetWidth,p=t.right-t.left>d;return p&&(t.right=t.left+d),t.left<10?l.scrollLeft=0:t.left<f?l.scrollLeft=Math.max(0,t.left+h-(p?0:10)):t.right>d+f-3&&(l.scrollLeft=t.right+(p?0:10)-d),l}function Nn(e,t){null!=t&&(Dn(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function On(e){Dn(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function An(e,t,r){null==t&&null==r||Dn(e),null!=t&&(e.curOp.scrollLeft=t),null!=r&&(e.curOp.scrollTop=r)}function Dn(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Wn(e,Yr(e,t.from),Yr(e,t.to),t.margin))}function Wn(e,t,r,n){var i=Mn(e,{left:Math.min(t.left,r.left),top:Math.min(t.top,r.top)-n,right:Math.max(t.right,r.right),bottom:Math.max(t.bottom,r.bottom)+n});An(e,i.scrollLeft,i.scrollTop)}function Hn(e,t){Math.abs(e.doc.scrollTop-t)<2||(r||oi(e,{top:t}),Fn(e,t,!0),r&&oi(e),ei(e,100))}function Fn(e,t,r){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),(e.display.scroller.scrollTop!=t||r)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Pn(e,t,r,n){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!n||(e.doc.scrollLeft=t,ai(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function En(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Sr(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+kr(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}var In=function(e,t,r){this.cm=r;var n=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");n.tabIndex=i.tabIndex=-1,e(n),e(i),fe(n,"scroll",function(){n.clientHeight&&t(n.scrollTop,"vertical")}),fe(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,l&&s<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};In.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,n=e.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=t?n+"px":"0";var i=e.viewHeight-(t?n:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(r?n:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==n&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?n:0,bottom:t?n:0}},In.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},In.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},In.prototype.zeroWidthHack=function(){var e=y&&!d?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new z,this.disableVert=new z},In.prototype.enableZeroWidthBar=function(e,t,r){e.style.pointerEvents="auto",t.set(1e3,function n(){var i=e.getBoundingClientRect();("vert"==r?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,n)})},In.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var Rn=function(){};function zn(e,t){t||(t=En(e));var r=e.display.barWidth,n=e.display.barHeight;Bn(e,t);for(var i=0;i<4&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&Ln(e),Bn(e,En(e)),r=e.display.barWidth,n=e.display.barHeight}function Bn(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",r.heightForcer.style.borderBottom=n.bottom+"px solid transparent",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}Rn.prototype.update=function(){return{bottom:0,right:0}},Rn.prototype.setScrollLeft=function(){},Rn.prototype.setScrollTop=function(){},Rn.prototype.clear=function(){};var Gn={native:In,null:Rn};function Un(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&T(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Gn[e.options.scrollbarStyle](function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),fe(t,"mousedown",function(){e.state.focused&&setTimeout(function(){return e.display.input.focus()},0)}),t.setAttribute("cm-not-content","true")},function(t,r){"horizontal"==r?Pn(e,t):Hn(e,t)},e),e.display.scrollbars.addClass&&H(e.display.wrapper,e.display.scrollbars.addClass)}var Vn=0;function Kn(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Vn},t=e.curOp,or?or.ops.push(t):t.ownsGroup=or={ops:[t],delayedCallbacks:[]}}function jn(e){var t=e.curOp;t&&function(e,t){var r=e.ownsGroup;if(r)try{!function(e){var t=e.delayedCallbacks,r=0;do{for(;r<t.length;r++)t[r].call(null);for(var n=0;n<e.ops.length;n++){var i=e.ops[n];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++].call(null,i.cm)}}while(r<t.length)}(r)}finally{or=null,t(r)}}(t,function(e){for(var t=0;t<e.ops.length;t++)e.ops[t].cm.curOp=null;!function(e){for(var t=e.ops,r=0;r<t.length;r++)Xn(t[r]);for(var n=0;n<t.length;n++)(i=t[n]).updatedDisplay=i.mustUpdate&&ni(i.cm,i.update);var i;for(var o=0;o<t.length;o++)Yn(t[o]);for(var l=0;l<t.length;l++)_n(t[l]);for(var s=0;s<t.length;s++)$n(t[s])}(e)})}function Xn(e){var t=e.cm,r=t.display;!function(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=kr(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=kr(e)+"px",t.scrollbarsClipped=!0)}(t),e.updateMaxLine&&jt(t),e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<r.viewFrom||e.scrollToPos.to.line>=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ri(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Yn(e){var t=e.cm,r=t.display;e.updatedDisplay&&Ln(t),e.barMeasure=En(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Or(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+kr(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Tr(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection())}function _n(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&Pn(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1);var r=e.focus&&e.focus==W();e.preparedSelection&&t.display.input.showSelection(e.preparedSelection,r),(e.updatedDisplay||e.startHeight!=t.doc.height)&&zn(t,e.barMeasure),e.updatedDisplay&&si(t,e.barMeasure),e.selectionChanged&&bn(t),t.state.focused&&e.updateInput&&t.display.input.reset(e.typing),r&&wn(e.cm)}function $n(e){var t=e.cm,r=t.display,n=t.doc;(e.updatedDisplay&&ii(t,e.update),null==r.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(r.wheelStartX=r.wheelStartY=null),null!=e.scrollTop&&Fn(t,e.scrollTop,e.forceScroll),null!=e.scrollLeft&&Pn(t,e.scrollLeft,!0,!0),e.scrollToPos)&&function(e,t){if(!ve(e,"scrollCursorIntoView")){var r=e.display,n=r.sizer.getBoundingClientRect(),i=null;if(t.top+n.top<0?i=!0:t.bottom+n.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!p){var o=O("div","​",null,"position: absolute;\n top: "+(t.top-r.viewOffset-Cr(e.display))+"px;\n height: "+(t.bottom-t.top+kr(e)+r.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}(t,function(e,t,r,n){var i;null==n&&(n=0),e.options.lineWrapping||t!=r||(r="before"==(t=t.ch?et(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?et(t.line,t.ch+1,"before"):t);for(var o=0;o<5;o++){var l=!1,s=Xr(e,t),a=r&&r!=t?Xr(e,r):s,u=Mn(e,i={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-n,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+n}),c=e.doc.scrollTop,h=e.doc.scrollLeft;if(null!=u.scrollTop&&(Hn(e,u.scrollTop),Math.abs(e.doc.scrollTop-c)>1&&(l=!0)),null!=u.scrollLeft&&(Pn(e,u.scrollLeft),Math.abs(e.doc.scrollLeft-h)>1&&(l=!0)),!l)break}return i}(t,st(n,e.scrollToPos.from),st(n,e.scrollToPos.to),e.scrollToPos.margin));var i=e.maybeHiddenMarkers,o=e.maybeUnhiddenMarkers;if(i)for(var l=0;l<i.length;++l)i[l].lines.length||ge(i[l],"hide");if(o)for(var s=0;s<o.length;++s)o[s].lines.length&&ge(o[s],"unhide");r.wrapper.offsetHeight&&(n.scrollTop=t.display.scroller.scrollTop),e.changeObjs&&ge(t,"changes",t,e.changeObjs),e.update&&e.update.finish()}function qn(e,t){if(e.curOp)return t();Kn(e);try{return t()}finally{jn(e)}}function Zn(e,t){return function(){if(e.curOp)return t.apply(e,arguments);Kn(e);try{return t.apply(e,arguments)}finally{jn(e)}}}function Qn(e){return function(){if(this.curOp)return e.apply(this,arguments);Kn(this);try{return e.apply(this,arguments)}finally{jn(this)}}}function Jn(e){return function(){var t=this.cm;if(!t||t.curOp)return e.apply(this,arguments);Kn(t);try{return e.apply(this,arguments)}finally{jn(t)}}}function ei(e,t){e.doc.highlightFrontier<e.display.viewTo&&e.state.highlight.set(t,E(ti,e))}function ti(e){var t=e.doc;if(!(t.highlightFrontier>=e.display.viewTo)){var r=+new Date+e.options.workTime,n=dt(e,t.highlightFrontier),i=[];t.iter(n.line,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(n.line>=e.display.viewFrom){var l=o.styles,s=o.text.length>e.options.maxHighlightLength?Ue(t.mode,n.state):null,a=ht(e,o,n,!0);s&&(n.state=s),o.styles=a.styles;var u=o.styleClasses,c=a.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var h=!l||l.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),f=0;!h&&f<l.length;++f)h=l[f]!=o.styles[f];h&&i.push(n.line),o.stateAfter=n.save(),n.nextLine()}else o.text.length<=e.options.maxHighlightLength&&pt(e,o.text,n),o.stateAfter=n.line%5==0?n.save():null,n.nextLine();if(+new Date>r)return ei(e,e.options.workDelay),!0}),t.highlightFrontier=n.line,t.modeFrontier=Math.max(t.modeFrontier,n.line),i.length&&qn(e,function(){for(var t=0;t<i.length;t++)cn(e,i[t],"text")})}}var ri=function(e,t,r){var n=e.display;this.viewport=t,this.visible=Tn(n,e.doc,t),this.editorIsHidden=!n.wrapper.offsetWidth,this.wrapperHeight=n.wrapper.clientHeight,this.wrapperWidth=n.wrapper.clientWidth,this.oldDisplayWidth=Tr(e),this.force=r,this.dims=rn(e),this.events=[]};function ni(e,t){var r=e.display,n=e.doc;if(t.editorIsHidden)return hn(e),!1;if(!t.force&&t.visible.from>=r.viewFrom&&t.visible.to<=r.viewTo&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&0==dn(e))return!1;ui(e)&&(hn(e),t.dims=rn(e));var i=n.first+n.size,o=Math.max(t.visible.from-e.options.viewportMargin,n.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);r.viewFrom<o&&o-r.viewFrom<20&&(o=Math.max(n.first,r.viewFrom)),r.viewTo>l&&r.viewTo-l<20&&(l=Math.min(i,r.viewTo)),Ct&&(o=zt(e.doc,o),l=Bt(e.doc,l));var s=o!=r.viewFrom||l!=r.viewTo||r.lastWrapHeight!=t.wrapperHeight||r.lastWrapWidth!=t.wrapperWidth;!function(e,t,r){var n=e.display;0==n.view.length||t>=n.viewTo||r<=n.viewFrom?(n.view=ir(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=ir(e,t,n.viewFrom).concat(n.view):n.viewFrom<t&&(n.view=n.view.slice(an(e,t))),n.viewFrom=t,n.viewTo<r?n.view=n.view.concat(ir(e,n.viewTo,r)):n.viewTo>r&&(n.view=n.view.slice(0,an(e,r)))),n.viewTo=r}(e,o,l),r.viewOffset=Vt(Xe(e.doc,r.viewFrom)),e.display.mover.style.top=r.viewOffset+"px";var u=dn(e);if(!s&&0==u&&!t.force&&r.renderedView==r.view&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo))return!1;var c=function(e){if(e.hasFocus())return null;var t=W();if(!t||!D(e.display.lineDiv,t))return null;var r={activeElt:t};if(window.getSelection){var n=window.getSelection();n.anchorNode&&n.extend&&D(e.display.lineDiv,n.anchorNode)&&(r.anchorNode=n.anchorNode,r.anchorOffset=n.anchorOffset,r.focusNode=n.focusNode,r.focusOffset=n.focusOffset)}return r}(e);return u>4&&(r.lineDiv.style.display="none"),function(e,t,r){var n=e.display,i=e.options.lineNumbers,o=n.lineDiv,l=o.firstChild;function s(t){var r=t.nextSibling;return a&&y&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var u=n.view,c=n.viewFrom,h=0;h<u.length;h++){var f=u[h];if(f.hidden);else if(f.node&&f.node.parentNode==o){for(;l!=f.node;)l=s(l);var d=i&&null!=t&&t<=c&&f.lineNumber;f.changes&&(B(f.changes,"gutter")>-1&&(d=!1),ur(e,f,c,r)),d&&(M(f.lineNumber),f.lineNumber.appendChild(document.createTextNode(Je(e.options,c)))),l=f.node.nextSibling}else{var p=vr(e,f,c,r);o.insertBefore(p,l)}c+=f.size}for(;l;)l=s(l)}(e,r.updateLineNumbers,t.dims),u>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,function(e){if(e&&e.activeElt&&e.activeElt!=W()&&(e.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(e.activeElt.nodeName)&&e.anchorNode&&D(document.body,e.anchorNode)&&D(document.body,e.focusNode))){var t=window.getSelection(),r=document.createRange();r.setEnd(e.anchorNode,e.anchorOffset),r.collapse(!1),t.removeAllRanges(),t.addRange(r),t.extend(e.focusNode,e.focusOffset)}}(c),M(r.cursorDiv),M(r.selectionDiv),r.gutters.style.height=r.sizer.style.minHeight=0,s&&(r.lastWrapHeight=t.wrapperHeight,r.lastWrapWidth=t.wrapperWidth,ei(e,400)),r.updateLineNumbers=null,!0}function ii(e,t){for(var r=t.viewport,n=!0;;n=!1){if(n&&e.options.lineWrapping&&t.oldDisplayWidth!=Tr(e))n&&(t.visible=Tn(e.display,e.doc,r));else if(r&&null!=r.top&&(r={top:Math.min(e.doc.height+Sr(e.display)-Mr(e),r.top)}),t.visible=Tn(e.display,e.doc,r),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!ni(e,t))break;Ln(e);var i=En(e);pn(e),zn(e,i),si(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function oi(e,t){var r=new ri(e,t);if(ni(e,r)){Ln(e),ii(e,r);var n=En(e);pn(e),zn(e,n),si(e,n),r.finish()}}function li(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function si(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+kr(e)+"px"}function ai(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=nn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",l=0;l<r.length;l++)if(!r[l].hidden){e.options.fixedGutter&&(r[l].gutter&&(r[l].gutter.style.left=o),r[l].gutterBackground&&(r[l].gutterBackground.style.left=o));var s=r[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=n+i+"px")}}function ui(e){if(!e.options.lineNumbers)return!1;var t=e.doc,r=Je(e.options,t.first+t.size-1),n=e.display;if(r.length!=n.lineNumChars){var i=n.measure.appendChild(O("div",[O("div",r)],"CodeMirror-linenumber CodeMirror-gutter-elt")),o=i.firstChild.offsetWidth,l=i.offsetWidth-o;return n.lineGutter.style.width="",n.lineNumInnerWidth=Math.max(o,n.lineGutter.offsetWidth-l)+1,n.lineNumWidth=n.lineNumInnerWidth+l,n.lineNumChars=n.lineNumInnerWidth?r.length:-1,n.lineGutter.style.width=n.lineNumWidth+"px",li(e.display),!0}return!1}function ci(e,t){for(var r=[],n=!1,i=0;i<e.length;i++){var o=e[i],l=null;if("string"!=typeof o&&(l=o.style,o=o.className),"CodeMirror-linenumbers"==o){if(!t)continue;n=!0}r.push({className:o,style:l})}return t&&!n&&r.push({className:"CodeMirror-linenumbers",style:null}),r}function hi(e){var t=e.gutters,r=e.gutterSpecs;M(t),e.lineGutter=null;for(var n=0;n<r.length;++n){var i=r[n],o=i.className,l=i.style,s=t.appendChild(O("div",null,"CodeMirror-gutter "+o));l&&(s.style.cssText=l),"CodeMirror-linenumbers"==o&&(e.lineGutter=s,s.style.width=(e.lineNumWidth||1)+"px")}t.style.display=r.length?"":"none",li(e)}function fi(e){hi(e.display),un(e),ai(e)}function di(e,t,n,i){var o=this;this.input=n,o.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),o.scrollbarFiller.setAttribute("cm-not-content","true"),o.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),o.gutterFiller.setAttribute("cm-not-content","true"),o.lineDiv=A("div",null,"CodeMirror-code"),o.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),o.cursorDiv=O("div",null,"CodeMirror-cursors"),o.measure=O("div",null,"CodeMirror-measure"),o.lineMeasure=O("div",null,"CodeMirror-measure"),o.lineSpace=A("div",[o.measure,o.lineMeasure,o.selectionDiv,o.cursorDiv,o.lineDiv],null,"position: relative; outline: none");var u=A("div",[o.lineSpace],"CodeMirror-lines");o.mover=O("div",[u],null,"position: relative"),o.sizer=O("div",[o.mover],"CodeMirror-sizer"),o.sizerWidth=null,o.heightForcer=O("div",null,null,"position: absolute; height: "+G+"px; width: 1px;"),o.gutters=O("div",null,"CodeMirror-gutters"),o.lineGutter=null,o.scroller=O("div",[o.sizer,o.heightForcer,o.gutters],"CodeMirror-scroll"),o.scroller.setAttribute("tabIndex","-1"),o.wrapper=O("div",[o.scrollbarFiller,o.gutterFiller,o.scroller],"CodeMirror"),l&&s<8&&(o.gutters.style.zIndex=-1,o.scroller.style.paddingRight=0),a||r&&m||(o.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(o.wrapper):e(o.wrapper)),o.viewFrom=o.viewTo=t.first,o.reportedViewFrom=o.reportedViewTo=t.first,o.view=[],o.renderedView=null,o.externalMeasured=null,o.viewOffset=0,o.lastWrapHeight=o.lastWrapWidth=0,o.updateLineNumbers=null,o.nativeBarWidth=o.barHeight=o.barWidth=0,o.scrollbarsClipped=!1,o.lineNumWidth=o.lineNumInnerWidth=o.lineNumChars=null,o.alignWidgets=!1,o.cachedCharWidth=o.cachedTextHeight=o.cachedPaddingH=null,o.maxLine=null,o.maxLineLength=0,o.maxLineChanged=!1,o.wheelDX=o.wheelDY=o.wheelStartX=o.wheelStartY=null,o.shift=!1,o.selForContextMenu=null,o.activeTouch=null,o.gutterSpecs=ci(i.gutters,i.lineNumbers),hi(o),n.init(o)}ri.prototype.signal=function(e,t){ye(e,t)&&this.events.push(arguments)},ri.prototype.finish=function(){for(var e=0;e<this.events.length;e++)ge.apply(null,this.events[e])};var pi=0,gi=null;function vi(e){var t=e.wheelDeltaX,r=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==r&&e.detail&&e.axis==e.VERTICAL_AXIS?r=e.detail:null==r&&(r=e.wheelDelta),{x:t,y:r}}function mi(e){var t=vi(e);return t.x*=gi,t.y*=gi,t}function yi(e,t){var n=vi(t),i=n.x,o=n.y,l=e.display,s=l.scroller,u=s.scrollWidth>s.clientWidth,c=s.scrollHeight>s.clientHeight;if(i&&u||o&&c){if(o&&y&&a)e:for(var f=t.target,d=l.view;f!=s;f=f.parentNode)for(var p=0;p<d.length;p++)if(d[p].node==f){e.display.currentWheelTarget=f;break e}if(i&&!r&&!h&&null!=gi)return o&&c&&Hn(e,Math.max(0,s.scrollTop+o*gi)),Pn(e,Math.max(0,s.scrollLeft+i*gi)),(!o||o&&c)&&we(t),void(l.wheelStartX=null);if(o&&null!=gi){var g=o*gi,v=e.doc.scrollTop,m=v+l.wrapper.clientHeight;g<0?v=Math.max(0,v+g-50):m=Math.min(e.doc.height,m+g+50),oi(e,{top:v,bottom:m})}pi<20&&(null==l.wheelStartX?(l.wheelStartX=s.scrollLeft,l.wheelStartY=s.scrollTop,l.wheelDX=i,l.wheelDY=o,setTimeout(function(){if(null!=l.wheelStartX){var e=s.scrollLeft-l.wheelStartX,t=s.scrollTop-l.wheelStartY,r=t&&l.wheelDY&&t/l.wheelDY||e&&l.wheelDX&&e/l.wheelDX;l.wheelStartX=l.wheelStartY=null,r&&(gi=(gi*pi+r)/(pi+1),++pi)}},200)):(l.wheelDX+=i,l.wheelDY+=o))}}l?gi=-.53:r?gi=15:c?gi=-.7:f&&(gi=-1/3);var bi=function(e,t){this.ranges=e,this.primIndex=t};bi.prototype.primary=function(){return this.ranges[this.primIndex]},bi.prototype.equals=function(e){if(e==this)return!0;if(e.primIndex!=this.primIndex||e.ranges.length!=this.ranges.length)return!1;for(var t=0;t<this.ranges.length;t++){var r=this.ranges[t],n=e.ranges[t];if(!rt(r.anchor,n.anchor)||!rt(r.head,n.head))return!1}return!0},bi.prototype.deepCopy=function(){for(var e=[],t=0;t<this.ranges.length;t++)e[t]=new wi(nt(this.ranges[t].anchor),nt(this.ranges[t].head));return new bi(e,this.primIndex)},bi.prototype.somethingSelected=function(){for(var e=0;e<this.ranges.length;e++)if(!this.ranges[e].empty())return!0;return!1},bi.prototype.contains=function(e,t){t||(t=e);for(var r=0;r<this.ranges.length;r++){var n=this.ranges[r];if(tt(t,n.from())>=0&&tt(e,n.to())<=0)return r}return-1};var wi=function(e,t){this.anchor=e,this.head=t};function xi(e,t,r){var n=e&&e.options.selectionsMayTouch,i=t[r];t.sort(function(e,t){return tt(e.from(),t.from())}),r=B(t,i);for(var o=1;o<t.length;o++){var l=t[o],s=t[o-1],a=tt(s.to(),l.from());if(n&&!l.empty()?a>0:a>=0){var u=ot(s.from(),l.from()),c=it(s.to(),l.to()),h=s.empty()?l.from()==l.head:s.from()==s.head;o<=r&&--r,t.splice(--o,2,new wi(h?c:u,h?u:c))}}return new bi(t,r)}function Ci(e,t){return new bi([new wi(e,t||e)],0)}function Si(e){return e.text?et(e.from.line+e.text.length-1,$(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function Li(e,t){if(tt(e,t.from)<0)return e;if(tt(e,t.to)<=0)return Si(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=Si(t).ch-t.to.ch),et(r,n)}function ki(e,t){for(var r=[],n=0;n<e.sel.ranges.length;n++){var i=e.sel.ranges[n];r.push(new wi(Li(i.anchor,t),Li(i.head,t)))}return xi(e.cm,r,e.sel.primIndex)}function Ti(e,t,r){return e.line==t.line?et(r.line,e.ch-t.ch+r.ch):et(r.line+(e.line-t.line),e.ch)}function Mi(e){e.doc.mode=ze(e.options,e.doc.modeOption),Ni(e)}function Ni(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.modeFrontier=e.doc.highlightFrontier=e.doc.first,ei(e,100),e.state.modeGen++,e.curOp&&un(e)}function Oi(e,t){return 0==t.from.ch&&0==t.to.ch&&""==$(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function Ai(e,t,r,n){function i(e){return r?r[e]:null}function o(e,r,i){!function(e,t,r,n){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),Nt(e),Ot(e,r);var i=n?n(e):1;i!=e.height&&$e(e,i)}(e,r,i,n),sr(e,"change",e,t)}function l(e,t){for(var r=[],o=e;o<t;++o)r.push(new Xt(u[o],i(o),n));return r}var s=t.from,a=t.to,u=t.text,c=Xe(e,s.line),h=Xe(e,a.line),f=$(u),d=i(u.length-1),p=a.line-s.line;if(t.full)e.insert(0,l(0,u.length)),e.remove(u.length,e.size-u.length);else if(Oi(e,t)){var g=l(0,u.length-1);o(h,h.text,d),p&&e.remove(s.line,p),g.length&&e.insert(s.line,g)}else if(c==h)if(1==u.length)o(c,c.text.slice(0,s.ch)+f+c.text.slice(a.ch),d);else{var v=l(1,u.length-1);v.push(new Xt(f+c.text.slice(a.ch),d,n)),o(c,c.text.slice(0,s.ch)+u[0],i(0)),e.insert(s.line+1,v)}else if(1==u.length)o(c,c.text.slice(0,s.ch)+u[0]+h.text.slice(a.ch),i(0)),e.remove(s.line+1,p);else{o(c,c.text.slice(0,s.ch)+u[0],i(0)),o(h,f+h.text.slice(a.ch),d);var m=l(1,u.length-1);p>1&&e.remove(s.line+1,p-1),e.insert(s.line+1,m)}sr(e,"change",e,t)}function Di(e,t,r){!function e(n,i,o){if(n.linked)for(var l=0;l<n.linked.length;++l){var s=n.linked[l];if(s.doc!=i){var a=o&&s.sharedHist;r&&!a||(t(s.doc,a),e(s.doc,n,a))}}}(e,null,!0)}function Wi(e,t){if(t.cm)throw new Error("This document is already in use.");e.doc=t,t.cm=e,ln(e),Mi(e),Hi(e),e.options.lineWrapping||jt(e),e.options.mode=t.modeOption,un(e)}function Hi(e){("rtl"==e.doc.direction?H:T)(e.display.lineDiv,"CodeMirror-rtl")}function Fi(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function Pi(e,t){var r={from:nt(t.from),to:Si(t),text:Ye(e,t.from,t.to)};return Bi(e,r,t.from.line,t.to.line+1),Di(e,function(e){return Bi(e,r,t.from.line,t.to.line+1)},!0),r}function Ei(e){for(;e.length;){if(!$(e).ranges)break;e.pop()}}function Ii(e,t,r,n){var i=e.history;i.undone.length=0;var o,l,s=+new Date;if((i.lastOp==n||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>s-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=function(e,t){return t?(Ei(e.done),$(e.done)):e.done.length&&!$(e.done).ranges?$(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),$(e.done)):void 0}(i,i.lastOp==n)))l=$(o.changes),0==tt(t.from,t.to)&&0==tt(t.from,l.to)?l.to=Si(t):o.changes.push(Pi(e,t));else{var a=$(i.done);for(a&&a.ranges||zi(e.sel,i.done),o={changes:[Pi(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,l||ge(e,"historyAdded")}function Ri(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||function(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}(e,o,$(i.done),t))?i.done[i.done.length-1]=t:zi(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&!1!==n.clearRedo&&Ei(i.undone)}function zi(e,t){var r=$(t);r&&r.ranges&&r.equals(e)||t.push(e)}function Bi(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o})}function Gi(e){if(!e)return null;for(var t,r=0;r<e.length;++r)e[r].marker.explicitlyCleared?t||(t=e.slice(0,r)):t&&t.push(e[r]);return t?t.length?t:null:e}function Ui(e,t){var r=function(e,t){var r=t["spans_"+e.id];if(!r)return null;for(var n=[],i=0;i<t.text.length;++i)n.push(Gi(r[i]));return n}(e,t),n=Tt(e,t);if(!r)return n;if(!n)return r;for(var i=0;i<r.length;++i){var o=r[i],l=n[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(r[i]=l)}return r}function Vi(e,t,r){for(var n=[],i=0;i<e.length;++i){var o=e[i];if(o.ranges)n.push(r?bi.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];n.push({changes:s});for(var a=0;a<l.length;++a){var u=l[a],c=void 0;if(s.push({from:u.from,to:u.to,text:u.text}),t)for(var h in u)(c=h.match(/^spans_(\d+)$/))&&B(t,Number(c[1]))>-1&&($(s)[h]=u[h],delete u[h])}}}return n}function Ki(e,t,r,n){if(n){var i=e.anchor;if(r){var o=tt(t,i)<0;o!=tt(r,i)<0?(i=t,t=r):o!=tt(t,r)<0&&(t=r)}return new wi(i,t)}return new wi(r||t,t)}function ji(e,t,r,n,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),qi(e,new bi([Ki(e.sel.primary(),t,r,i)],0),n)}function Xi(e,t,r){for(var n=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o<e.sel.ranges.length;o++)n[o]=Ki(e.sel.ranges[o],t[o],null,i);qi(e,xi(e.cm,n,e.sel.primIndex),r)}function Yi(e,t,r,n){var i=e.sel.ranges.slice(0);i[t]=r,qi(e,xi(e.cm,i,e.sel.primIndex),n)}function _i(e,t,r,n){qi(e,Ci(t,r),n)}function $i(e,t,r){var n=e.history.done,i=$(n);i&&i.ranges?(n[n.length-1]=t,Zi(e,t,r)):qi(e,t,r)}function qi(e,t,r){Zi(e,t,r),Ri(e,e.sel,e.cm?e.cm.curOp.id:NaN,r)}function Zi(e,t,r){(ye(e,"beforeSelectionChange")||e.cm&&ye(e.cm,"beforeSelectionChange"))&&(t=function(e,t,r){var n={ranges:t.ranges,update:function(t){this.ranges=[];for(var r=0;r<t.length;r++)this.ranges[r]=new wi(st(e,t[r].anchor),st(e,t[r].head))},origin:r&&r.origin};return ge(e,"beforeSelectionChange",e,n),e.cm&&ge(e.cm,"beforeSelectionChange",e.cm,n),n.ranges!=t.ranges?xi(e.cm,n.ranges,n.ranges.length-1):t}(e,t,r));var n=r&&r.bias||(tt(t.primary().head,e.sel.primary().head)<0?-1:1);Qi(e,eo(e,t,n,!0)),r&&!1===r.scroll||!e.cm||"nocursor"==e.cm.getOption("readOnly")||On(e.cm)}function Qi(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=1,e.cm.curOp.selectionChanged=!0,me(e.cm)),sr(e,"cursorActivity",e))}function Ji(e){Qi(e,eo(e,e.sel,null,!1))}function eo(e,t,r,n){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=t.ranges.length==e.sel.ranges.length&&e.sel.ranges[o],a=ro(e,l.anchor,s&&s.anchor,r,n),u=ro(e,l.head,s&&s.head,r,n);(i||a!=l.anchor||u!=l.head)&&(i||(i=t.ranges.slice(0,o)),i[o]=new wi(a,u))}return i?xi(e.cm,i,t.primIndex):t}function to(e,t,r,n,i){var o=Xe(e,t.line);if(o.markedSpans)for(var l=0;l<o.markedSpans.length;++l){var s=o.markedSpans[l],a=s.marker,u="selectLeft"in a?!a.selectLeft:a.inclusiveLeft,c="selectRight"in a?!a.selectRight:a.inclusiveRight;if((null==s.from||(u?s.from<=t.ch:s.from<t.ch))&&(null==s.to||(c?s.to>=t.ch:s.to>t.ch))){if(i&&(ge(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(r){var h=a.find(n<0?1:-1),f=void 0;if((n<0?c:u)&&(h=no(e,h,-n,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(f=tt(h,r))&&(n<0?f<0:f>0))return to(e,h,t,n,i)}var d=a.find(n<0?-1:1);return(n<0?u:c)&&(d=no(e,d,n,d.line==t.line?o:null)),d?to(e,d,t,n,i):null}}return t}function ro(e,t,r,n,i){var o=n||1,l=to(e,t,r,o,i)||!i&&to(e,t,r,o,!0)||to(e,t,r,-o,i)||!i&&to(e,t,r,-o,!0);return l||(e.cantEdit=!0,et(e.first,0))}function no(e,t,r,n){return r<0&&0==t.ch?t.line>e.first?st(e,et(t.line-1)):null:r>0&&t.ch==(n||Xe(e,t.line)).text.length?t.line<e.first+e.size-1?et(t.line+1,0):null:new et(t.line,t.ch+r)}function io(e){e.setSelection(et(e.firstLine(),0),et(e.lastLine()),V)}function oo(e,t,r){var n={canceled:!1,from:t.from,to:t.to,text:t.text,origin:t.origin,cancel:function(){return n.canceled=!0}};return r&&(n.update=function(t,r,i,o){t&&(n.from=st(e,t)),r&&(n.to=st(e,r)),i&&(n.text=i),void 0!==o&&(n.origin=o)}),ge(e,"beforeChange",e,n),e.cm&&ge(e.cm,"beforeChange",e.cm,n),n.canceled?(e.cm&&(e.cm.curOp.updateInput=2),null):{from:n.from,to:n.to,text:n.text,origin:n.origin}}function lo(e,t,r){if(e.cm){if(!e.cm.curOp)return Zn(e.cm,lo)(e,t,r);if(e.cm.state.suppressEdits)return}if(!(ye(e,"beforeChange")||e.cm&&ye(e.cm,"beforeChange"))||(t=oo(e,t,!0))){var n=xt&&!r&&function(e,t,r){var n=null;if(e.iter(t.line,r.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var r=e.markedSpans[t].marker;!r.readOnly||n&&-1!=B(n,r)||(n||(n=[])).push(r)}}),!n)return null;for(var i=[{from:t,to:r}],o=0;o<n.length;++o)for(var l=n[o],s=l.find(0),a=0;a<i.length;++a){var u=i[a];if(!(tt(u.to,s.from)<0||tt(u.from,s.to)>0)){var c=[a,1],h=tt(u.from,s.from),f=tt(u.to,s.to);(h<0||!l.inclusiveLeft&&!h)&&c.push({from:u.from,to:s.from}),(f>0||!l.inclusiveRight&&!f)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),a+=c.length-3}}return i}(e,t.from,t.to);if(n)for(var i=n.length-1;i>=0;--i)so(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text,origin:t.origin});else so(e,t)}}function so(e,t){if(1!=t.text.length||""!=t.text[0]||0!=tt(t.from,t.to)){var r=ki(e,t);Ii(e,t,r,e.cm?e.cm.curOp.id:NaN),co(e,t,r,Tt(e,t));var n=[];Di(e,function(e,r){r||-1!=B(n,e.history)||(go(e.history,t),n.push(e.history)),co(e,t,null,Tt(e,t))})}}function ao(e,t,r){var n=e.cm&&e.cm.state.suppressEdits;if(!n||r){for(var i,o=e.history,l=e.sel,s="undo"==t?o.done:o.undone,a="undo"==t?o.undone:o.done,u=0;u<s.length&&(i=s[u],r?!i.ranges||i.equals(e.sel):i.ranges);u++);if(u!=s.length){for(o.lastOrigin=o.lastSelOrigin=null;;){if(!(i=s.pop()).ranges){if(n)return void s.push(i);break}if(zi(i,a),r&&!i.equals(e.sel))return void qi(e,i,{clearRedo:!1});l=i}var c=[];zi(l,a),a.push({changes:c,generation:o.generation}),o.generation=i.generation||++o.maxGeneration;for(var h=ye(e,"beforeChange")||e.cm&&ye(e.cm,"beforeChange"),f=function(r){var n=i.changes[r];if(n.origin=t,h&&!oo(e,n,!1))return s.length=0,{};c.push(Pi(e,n));var o=r?ki(e,n):$(s);co(e,n,o,Ui(e,n)),!r&&e.cm&&e.cm.scrollIntoView({from:n.from,to:Si(n)});var l=[];Di(e,function(e,t){t||-1!=B(l,e.history)||(go(e.history,n),l.push(e.history)),co(e,n,null,Ui(e,n))})},d=i.changes.length-1;d>=0;--d){var p=f(d);if(p)return p.v}}}}function uo(e,t){if(0!=t&&(e.first+=t,e.sel=new bi(q(e.sel.ranges,function(e){return new wi(et(e.anchor.line+t,e.anchor.ch),et(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){un(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;n<r.viewTo;n++)cn(e.cm,n,"gutter")}}function co(e,t,r,n){if(e.cm&&!e.cm.curOp)return Zn(e.cm,co)(e,t,r,n);if(t.to.line<e.first)uo(e,t.text.length-1-(t.to.line-t.from.line));else if(!(t.from.line>e.lastLine())){if(t.from.line<e.first){var i=t.text.length-1-(e.first-t.from.line);uo(e,i),t={from:et(e.first,0),to:et(t.to.line+i,t.to.ch),text:[$(t.text)],origin:t.origin}}var o=e.lastLine();t.to.line>o&&(t={from:t.from,to:et(o,Xe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Ye(e,t.from,t.to),r||(r=ki(e,t)),e.cm?function(e,t,r){var n=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=qe(Rt(Xe(n,o.line))),n.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0,!0}));n.sel.contains(t.from,t.to)>-1&&me(e);Ai(n,t,r,on(e)),e.options.lineWrapping||(n.iter(a,o.line+t.text.length,function(e){var t=Kt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontier<t-10)){for(var r=e.first,n=t-1;n>r;n--){var i=Xe(e,n).stateAfter;if(i&&(!(i instanceof ut)||n+i.lookAhead<t)){r=n+1;break}}e.highlightFrontier=Math.min(e.highlightFrontier,r)}})(n,o.line),ei(e,400);var u=t.text.length-(l.line-o.line)-1;t.full?un(e):o.line!=l.line||1!=t.text.length||Oi(e.doc,t)?un(e,o.line,l.line+1,u):cn(e,o.line,"text");var c=ye(e,"changes"),h=ye(e,"change");if(h||c){var f={from:o,to:l,text:t.text,removed:t.removed,origin:t.origin};h&&sr(e,"change",e,f),c&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(f)}e.display.selForContextMenu=null}(e.cm,t,n):Ai(e,t,n),Zi(e,r,V),e.cantEdit&&ro(e,et(e.firstLine(),0))&&(e.cantEdit=!1)}}function ho(e,t,r,n,i){var o;n||(n=r),tt(n,r)<0&&(r=(o=[n,r])[0],n=o[1]),"string"==typeof t&&(t=e.splitLines(t)),lo(e,{from:r,to:n,text:t,origin:i})}function fo(e,t,r,n){r<e.line?e.line+=n:t<e.line&&(e.line=t,e.ch=0)}function po(e,t,r,n){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||((o=e[i]=o.deepCopy()).copied=!0);for(var s=0;s<o.ranges.length;s++)fo(o.ranges[s].anchor,t,r,n),fo(o.ranges[s].head,t,r,n)}else{for(var a=0;a<o.changes.length;++a){var u=o.changes[a];if(r<u.from.line)u.from=et(u.from.line+n,u.from.ch),u.to=et(u.to.line+n,u.to.ch);else if(t<=u.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function go(e,t){var r=t.from.line,n=t.to.line,i=t.text.length-(n-r)-1;po(e.done,r,n,i),po(e.undone,r,n,i)}function vo(e,t,r,n){var i=t,o=t;return"number"==typeof t?o=Xe(e,lt(e,t)):i=qe(t),null==i?null:(n(o,i)&&e.cm&&cn(e.cm,i,r),o)}function mo(e){this.lines=e,this.parent=null;for(var t=0,r=0;r<e.length;++r)e[r].parent=this,t+=e[r].height;this.height=t}function yo(e){this.children=e;for(var t=0,r=0,n=0;n<e.length;++n){var i=e[n];t+=i.chunkSize(),r+=i.height,i.parent=this}this.size=t,this.height=r,this.parent=null}wi.prototype.from=function(){return ot(this.anchor,this.head)},wi.prototype.to=function(){return it(this.anchor,this.head)},wi.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch},mo.prototype={chunkSize:function(){return this.lines.length},removeInner:function(e,t){for(var r=e,n=e+t;r<n;++r){var i=this.lines[r];this.height-=i.height,Yt(i),sr(i,"delete")}this.lines.splice(e,t)},collapse:function(e){e.push.apply(e,this.lines)},insertInner:function(e,t,r){this.height+=r,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var n=0;n<t.length;++n)t[n].parent=this},iterN:function(e,t,r){for(var n=e+t;e<n;++e)if(r(this.lines[e]))return!0}},yo.prototype={chunkSize:function(){return this.size},removeInner:function(e,t){this.size-=t;for(var r=0;r<this.children.length;++r){var n=this.children[r],i=n.chunkSize();if(e<i){var o=Math.min(t,i-e),l=n.height;if(n.removeInner(e,o),this.height-=l-n.height,i==o&&(this.children.splice(r--,1),n.parent=null),0==(t-=o))break;e=0}else e-=i}if(this.size-t<25&&(this.children.length>1||!(this.children[0]instanceof mo))){var s=[];this.collapse(s),this.children=[new mo(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t<this.children.length;++t)this.children[t].collapse(e)},insertInner:function(e,t,r){this.size+=t.length,this.height+=r;for(var n=0;n<this.children.length;++n){var i=this.children[n],o=i.chunkSize();if(e<=o){if(i.insertInner(e,t,r),i.lines&&i.lines.length>50){for(var l=i.lines.length%25+25,s=l;s<i.lines.length;){var a=new mo(i.lines.slice(s,s+=25));i.height-=a.height,this.children.splice(++n,0,a),a.parent=this}i.lines=i.lines.slice(0,l),this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(!(this.children.length<=10)){var e=this;do{var t=new yo(e.children.splice(e.children.length-5,5));if(e.parent){e.size-=t.size,e.height-=t.height;var r=B(e.parent.children,e);e.parent.children.splice(r+1,0,t)}else{var n=new yo(e.children);n.parent=e,e.children=[n,t],e=n}t.parent=e.parent}while(e.children.length>10);e.parent.maybeSpill()}},iterN:function(e,t,r){for(var n=0;n<this.children.length;++n){var i=this.children[n],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e);if(i.iterN(e,l,r))return!0;if(0==(t-=l))break;e=0}else e-=o}}};var bo=function(e,t,r){if(r)for(var n in r)r.hasOwnProperty(n)&&(this[n]=r[n]);this.doc=e,this.node=t};function wo(e,t,r){Vt(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&Nn(e,r)}bo.prototype.clear=function(){var e=this.doc.cm,t=this.line.widgets,r=this.line,n=qe(r);if(null!=n&&t){for(var i=0;i<t.length;++i)t[i]==this&&t.splice(i--,1);t.length||(r.widgets=null);var o=wr(this);$e(r,Math.max(0,r.height-o)),e&&(qn(e,function(){wo(e,r,-o),cn(e,n,"widget")}),sr(e,"lineWidgetCleared",e,this,n))}},bo.prototype.changed=function(){var e=this,t=this.height,r=this.doc.cm,n=this.line;this.height=null;var i=wr(this)-t;i&&(Gt(this.doc,n)||$e(n,n.height+i),r&&qn(r,function(){r.curOp.forceUpdate=!0,wo(r,n,i),sr(r,"lineWidgetChanged",r,e,qe(n))}))},be(bo);var xo=0,Co=function(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++xo};function So(e,t,r,n,i){if(n&&n.shared)return function(e,t,r,n,i){(n=I(n)).shared=!1;var o=[So(e,t,r,n,i)],l=o[0],s=n.widgetNode;return Di(e,function(e){s&&(n.widgetNode=s.cloneNode(!0)),o.push(So(e,st(e,t),st(e,r),n,i));for(var a=0;a<e.linked.length;++a)if(e.linked[a].isParent)return;l=$(o)}),new Lo(o,l)}(e,t,r,n,i);if(e.cm&&!e.cm.curOp)return Zn(e.cm,So)(e,t,r,n,i);var o=new Co(e,i),l=tt(t,r);if(n&&I(n,o,!1),l>0||0==l&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(It(e,t.line,t,r,o)||t.line!=r.line&&It(e,r.line,t,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Ct=!0}o.addToHistory&&Ii(e,{from:t,to:r,origin:"markText"},e.sel,NaN);var s,a=t.line,u=e.cm;if(e.iter(a,r.line+1,function(e){u&&o.collapsed&&!u.options.lineWrapping&&Rt(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=t.line&&$e(e,0),function(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}(e,new St(o,a==t.line?t.ch:null,a==r.line?r.ch:null)),++a}),o.collapsed&&e.iter(t.line,r.line+1,function(t){Gt(e,t)&&$e(t,0)}),o.clearOnEnter&&fe(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(xt=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++xo,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)un(u,t.line,r.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=t.line;c<=r.line;c++)cn(u,c,"text");o.atomic&&Ji(u.doc),sr(u,"markerAdded",u,o)}return o}Co.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Kn(e),ye(this,"clear")){var r=this.find();r&&sr(this,"clear",r.from,r.to)}for(var n=null,i=null,o=0;o<this.lines.length;++o){var l=this.lines[o],s=Lt(l.markedSpans,this);e&&!this.collapsed?cn(e,qe(l),"text"):e&&(null!=s.to&&(i=qe(l)),null!=s.from&&(n=qe(l))),l.markedSpans=kt(l.markedSpans,s),null==s.from&&this.collapsed&&!Gt(this.doc,l)&&e&&$e(l,en(e.display))}if(e&&this.collapsed&&!e.options.lineWrapping)for(var a=0;a<this.lines.length;++a){var u=Rt(this.lines[a]),c=Kt(u);c>e.display.maxLineLength&&(e.display.maxLine=u,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=n&&e&&this.collapsed&&un(e,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&Ji(e.doc)),e&&sr(e,"markerCleared",e,this,n,i),t&&jn(e),this.parent&&this.parent.clear()}},Co.prototype.find=function(e,t){var r,n;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i<this.lines.length;++i){var o=this.lines[i],l=Lt(o.markedSpans,this);if(null!=l.from&&(r=et(t?o:qe(o),l.from),-1==e))return r;if(null!=l.to&&(n=et(t?o:qe(o),l.to),1==e))return n}return r&&{from:r,to:n}},Co.prototype.changed=function(){var e=this,t=this.find(-1,!0),r=this,n=this.doc.cm;t&&n&&qn(n,function(){var i=t.line,o=qe(t.line),l=Ar(n,o);if(l&&(Ir(l),n.curOp.selectionChanged=n.curOp.forceUpdate=!0),n.curOp.updateMaxLine=!0,!Gt(r.doc,i)&&null!=r.height){var s=r.height;r.height=null;var a=wr(r)-s;a&&$e(i,i.height+a)}sr(n,"markerChanged",n,e)})},Co.prototype.attachLine=function(e){if(!this.lines.length&&this.doc.cm){var t=this.doc.cm.curOp;t.maybeHiddenMarkers&&-1!=B(t.maybeHiddenMarkers,this)||(t.maybeUnhiddenMarkers||(t.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(e)},Co.prototype.detachLine=function(e){if(this.lines.splice(B(this.lines,e),1),!this.lines.length&&this.doc.cm){var t=this.doc.cm.curOp;(t.maybeHiddenMarkers||(t.maybeHiddenMarkers=[])).push(this)}},be(Co);var Lo=function(e,t){this.markers=e,this.primary=t;for(var r=0;r<e.length;++r)e[r].parent=this};function ko(e){return e.findMarks(et(e.first,0),e.clipPos(et(e.lastLine())),function(e){return e.parent})}function To(e){for(var t=function(t){var r=e[t],n=[r.primary.doc];Di(r.primary.doc,function(e){return n.push(e)});for(var i=0;i<r.markers.length;i++){var o=r.markers[i];-1==B(n,o.doc)&&(o.parent=null,r.markers.splice(i--,1))}},r=0;r<e.length;r++)t(r)}Lo.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var e=0;e<this.markers.length;++e)this.markers[e].clear();sr(this,"clear")}},Lo.prototype.find=function(e,t){return this.primary.find(e,t)},be(Lo);var Mo=0,No=function(e,t,r,n,i){if(!(this instanceof No))return new No(e,t,r,n,i);null==r&&(r=0),yo.call(this,[new mo([new Xt("",null)])]),this.first=r,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.modeFrontier=this.highlightFrontier=r;var o=et(r,0);this.sel=Ci(o),this.history=new Fi(null),this.id=++Mo,this.modeOption=t,this.lineSep=n,this.direction="rtl"==i?"rtl":"ltr",this.extend=!1,"string"==typeof e&&(e=this.splitLines(e)),Ai(this,{from:o,to:o,text:e}),qi(this,Ci(o),V)};No.prototype=Q(yo.prototype,{constructor:No,iter:function(e,t,r){r?this.iterN(e-this.first,t-e,r):this.iterN(this.first,this.first+this.size,e)},insert:function(e,t){for(var r=0,n=0;n<t.length;++n)r+=t[n].height;this.insertInner(e-this.first,t,r)},remove:function(e,t){this.removeInner(e-this.first,t)},getValue:function(e){var t=_e(this,this.first,this.first+this.size);return!1===e?t:t.join(e||this.lineSeparator())},setValue:Jn(function(e){var t=et(this.first,0),r=this.first+this.size-1;lo(this,{from:t,to:et(r,Xe(this,r).text.length),text:this.splitLines(e),origin:"setValue",full:!0},!0),this.cm&&An(this.cm,0,0),qi(this,Ci(t),V)}),replaceRange:function(e,t,r,n){ho(this,e,t=st(this,t),r=r?st(this,r):t,n)},getRange:function(e,t,r){var n=Ye(this,st(this,e),st(this,t));return!1===r?n:n.join(r||this.lineSeparator())},getLine:function(e){var t=this.getLineHandle(e);return t&&t.text},getLineHandle:function(e){if(Qe(this,e))return Xe(this,e)},getLineNumber:function(e){return qe(e)},getLineHandleVisualStart:function(e){return"number"==typeof e&&(e=Xe(this,e)),Rt(e)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(e){return st(this,e)},getCursor:function(e){var t=this.sel.primary();return null==e||"head"==e?t.head:"anchor"==e?t.anchor:"end"==e||"to"==e||!1===e?t.to():t.from()},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Jn(function(e,t,r){_i(this,st(this,"number"==typeof e?et(e,t||0):e),null,r)}),setSelection:Jn(function(e,t,r){_i(this,st(this,e),st(this,t||e),r)}),extendSelection:Jn(function(e,t,r){ji(this,st(this,e),t&&st(this,t),r)}),extendSelections:Jn(function(e,t){Xi(this,at(this,e),t)}),extendSelectionsBy:Jn(function(e,t){Xi(this,at(this,q(this.sel.ranges,e)),t)}),setSelections:Jn(function(e,t,r){if(e.length){for(var n=[],i=0;i<e.length;i++)n[i]=new wi(st(this,e[i].anchor),st(this,e[i].head));null==t&&(t=Math.min(e.length-1,this.sel.primIndex)),qi(this,xi(this.cm,n,t),r)}}),addSelection:Jn(function(e,t,r){var n=this.sel.ranges.slice(0);n.push(new wi(st(this,e),st(this,t||e))),qi(this,xi(this.cm,n,n.length-1),r)}),getSelection:function(e){for(var t,r=this.sel.ranges,n=0;n<r.length;n++){var i=Ye(this,r[n].from(),r[n].to());t=t?t.concat(i):i}return!1===e?t:t.join(e||this.lineSeparator())},getSelections:function(e){for(var t=[],r=this.sel.ranges,n=0;n<r.length;n++){var i=Ye(this,r[n].from(),r[n].to());!1!==e&&(i=i.join(e||this.lineSeparator())),t[n]=i}return t},replaceSelection:function(e,t,r){for(var n=[],i=0;i<this.sel.ranges.length;i++)n[i]=e;this.replaceSelections(n,t,r||"+input")},replaceSelections:Jn(function(e,t,r){for(var n=[],i=this.sel,o=0;o<i.ranges.length;o++){var l=i.ranges[o];n[o]={from:l.from(),to:l.to(),text:this.splitLines(e[o]),origin:r}}for(var s=t&&"end"!=t&&function(e,t,r){for(var n=[],i=et(e.first,0),o=i,l=0;l<t.length;l++){var s=t[l],a=Ti(s.from,i,o),u=Ti(Si(s),i,o);if(i=s.to,o=u,"around"==r){var c=e.sel.ranges[l],h=tt(c.head,c.anchor)<0;n[l]=new wi(h?u:a,h?a:u)}else n[l]=new wi(a,a)}return new bi(n,e.sel.primIndex)}(this,n,t),a=n.length-1;a>=0;a--)lo(this,n[a]);s?$i(this,s):this.cm&&On(this.cm)}),undo:Jn(function(){ao(this,"undo")}),redo:Jn(function(){ao(this,"redo")}),undoSelection:Jn(function(){ao(this,"undo",!0)}),redoSelection:Jn(function(){ao(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,r=0,n=0;n<e.done.length;n++)e.done[n].ranges||++t;for(var i=0;i<e.undone.length;i++)e.undone[i].ranges||++r;return{undo:t,redo:r}},clearHistory:function(){var e=this;this.history=new Fi(this.history.maxGeneration),Di(this,function(t){return t.history=e.history},!0)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(e){return e&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(e){return this.history.generation==(e||this.cleanGeneration)},getHistory:function(){return{done:Vi(this.history.done),undone:Vi(this.history.undone)}},setHistory:function(e){var t=this.history=new Fi(this.history.maxGeneration);t.done=Vi(e.done.slice(0),null,!0),t.undone=Vi(e.undone.slice(0),null,!0)},setGutterMarker:Jn(function(e,t,r){return vo(this,e,"gutter",function(e){var n=e.gutterMarkers||(e.gutterMarkers={});return n[t]=r,!r&&re(n)&&(e.gutterMarkers=null),!0})}),clearGutter:Jn(function(e){var t=this;this.iter(function(r){r.gutterMarkers&&r.gutterMarkers[e]&&vo(t,r,"gutter",function(){return r.gutterMarkers[e]=null,re(r.gutterMarkers)&&(r.gutterMarkers=null),!0})})}),lineInfo:function(e){var t;if("number"==typeof e){if(!Qe(this,e))return null;if(t=e,!(e=Xe(this,e)))return null}else if(null==(t=qe(e)))return null;return{line:t,handle:e,text:e.text,gutterMarkers:e.gutterMarkers,textClass:e.textClass,bgClass:e.bgClass,wrapClass:e.wrapClass,widgets:e.widgets}},addLineClass:Jn(function(e,t,r){return vo(this,e,"gutter"==t?"gutter":"class",function(e){var n="text"==t?"textClass":"background"==t?"bgClass":"gutter"==t?"gutterClass":"wrapClass";if(e[n]){if(L(r).test(e[n]))return!1;e[n]+=" "+r}else e[n]=r;return!0})}),removeLineClass:Jn(function(e,t,r){return vo(this,e,"gutter"==t?"gutter":"class",function(e){var n="text"==t?"textClass":"background"==t?"bgClass":"gutter"==t?"gutterClass":"wrapClass",i=e[n];if(!i)return!1;if(null==r)e[n]=null;else{var o=i.match(L(r));if(!o)return!1;var l=o.index+o[0].length;e[n]=i.slice(0,o.index)+(o.index&&l!=i.length?" ":"")+i.slice(l)||null}return!0})}),addLineWidget:Jn(function(e,t,r){return function(e,t,r,n){var i=new bo(e,r,n),o=e.cm;return o&&i.noHScroll&&(o.display.alignWidgets=!0),vo(e,t,"widget",function(t){var r=t.widgets||(t.widgets=[]);if(null==i.insertAt?r.push(i):r.splice(Math.min(r.length,Math.max(0,i.insertAt)),0,i),i.line=t,o&&!Gt(e,t)){var n=Vt(t)<e.scrollTop;$e(t,t.height+wr(i)),n&&Nn(o,i.height),o.curOp.forceUpdate=!0}return!0}),o&&sr(o,"lineWidgetAdded",o,i,"number"==typeof t?t:qe(t)),i}(this,e,t,r)}),removeLineWidget:function(e){e.clear()},markText:function(e,t,r){return So(this,st(this,e),st(this,t),r,r&&r.type||"range")},setBookmark:function(e,t){var r={replacedWith:t&&(null==t.nodeType?t.widget:t),insertLeft:t&&t.insertLeft,clearWhenEmpty:!1,shared:t&&t.shared,handleMouseEvents:t&&t.handleMouseEvents};return So(this,e=st(this,e),e,r,"bookmark")},findMarksAt:function(e){var t=[],r=Xe(this,(e=st(this,e)).line).markedSpans;if(r)for(var n=0;n<r.length;++n){var i=r[n];(null==i.from||i.from<=e.ch)&&(null==i.to||i.to>=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,r){e=st(this,e),t=st(this,t);var n=[],i=e.line;return this.iter(e.line,t.line+1,function(o){var l=o.markedSpans;if(l)for(var s=0;s<l.length;s++){var a=l[s];null!=a.to&&i==e.line&&e.ch>=a.to||null==a.from&&i!=e.line||null!=a.from&&i==t.line&&a.from>=t.ch||r&&!r(a.marker)||n.push(a.marker.parent||a.marker)}++i}),n},getAllMarks:function(){var e=[];return this.iter(function(t){var r=t.markedSpans;if(r)for(var n=0;n<r.length;++n)null!=r[n].from&&e.push(r[n].marker)}),e},posFromIndex:function(e){var t,r=this.first,n=this.lineSeparator().length;return this.iter(function(i){var o=i.text.length+n;if(o>e)return t=e,!0;e-=o,++r}),st(this,et(r,t))},indexFromPos:function(e){var t=(e=st(this,e)).ch;if(e.line<this.first||e.ch<0)return 0;var r=this.lineSeparator().length;return this.iter(this.first,e.line,function(e){t+=e.text.length+r}),t},copy:function(e){var t=new No(_e(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft,t.sel=this.sel,t.extend=!1,e&&(t.history.undoDepth=this.history.undoDepth,t.setHistory(this.getHistory())),t},linkedDoc:function(e){e||(e={});var t=this.first,r=this.first+this.size;null!=e.from&&e.from>t&&(t=e.from),null!=e.to&&e.to<r&&(r=e.to);var n=new No(_e(this,t,r),e.mode||this.modeOption,t,this.lineSep,this.direction);return e.sharedHist&&(n.history=this.history),(this.linked||(this.linked=[])).push({doc:n,sharedHist:e.sharedHist}),n.linked=[{doc:this,isParent:!0,sharedHist:e.sharedHist}],function(e,t){for(var r=0;r<t.length;r++){var n=t[r],i=n.find(),o=e.clipPos(i.from),l=e.clipPos(i.to);if(tt(o,l)){var s=So(e,o,l,n.primary,n.primary.type);n.markers.push(s),s.parent=n}}}(n,ko(this)),n},unlinkDoc:function(e){if(e instanceof Ll&&(e=e.doc),this.linked)for(var t=0;t<this.linked.length;++t){if(this.linked[t].doc==e){this.linked.splice(t,1),e.unlinkDoc(this),To(ko(this));break}}if(e.history==this.history){var r=[e.id];Di(e,function(e){return r.push(e.id)},!0),e.history=new Fi(null),e.history.done=Vi(this.history.done,r),e.history.undone=Vi(this.history.undone,r)}},iterLinkedDocs:function(e){Di(this,e)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(e){return this.lineSep?e.split(this.lineSep):We(e)},lineSeparator:function(){return this.lineSep||"\n"},setDirection:Jn(function(e){var t;("rtl"!=e&&(e="ltr"),e!=this.direction)&&(this.direction=e,this.iter(function(e){return e.order=null}),this.cm&&qn(t=this.cm,function(){Hi(t),un(t)}))})}),No.prototype.eachLine=No.prototype.iter;var Oo=0;function Ao(e){var t=this;if(Do(t),!ve(t,e)&&!xr(t.display,e)){we(e),l&&(Oo=+new Date);var r=sn(t,e,!0),n=e.dataTransfer.files;if(r&&!t.isReadOnly())if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),s=0,a=function(){++s==i&&Zn(t,function(){var e={from:r=st(t.doc,r),to:r,text:t.doc.splitLines(o.filter(function(e){return null!=e}).join(t.doc.lineSeparator())),origin:"paste"};lo(t.doc,e),$i(t.doc,Ci(st(t.doc,r),st(t.doc,Si(e))))})()},u=function(e,r){if(t.options.allowDropFileTypes&&-1==B(t.options.allowDropFileTypes,e.type))a();else{var n=new FileReader;n.onerror=function(){return a()},n.onload=function(){var e=n.result;/[\x00-\x08\x0e-\x1f]{2}/.test(e)?a():(o[r]=e,a())},n.readAsText(e)}},c=0;c<n.length;c++)u(n[c],c);else{if(t.state.draggingText&&t.doc.sel.contains(r)>-1)return t.state.draggingText(e),void setTimeout(function(){return t.display.input.focus()},20);try{var h=e.dataTransfer.getData("Text");if(h){var f;if(t.state.draggingText&&!t.state.draggingText.copy&&(f=t.listSelections()),Zi(t.doc,Ci(r,r)),f)for(var d=0;d<f.length;++d)ho(t.doc,"",f[d].anchor,f[d].head,"drag");t.replaceSelection(h,"around","paste"),t.display.input.focus()}}catch(e){}}}}function Do(e){e.display.dragCursor&&(e.display.lineSpace.removeChild(e.display.dragCursor),e.display.dragCursor=null)}function Wo(e){if(document.getElementsByClassName){for(var t=document.getElementsByClassName("CodeMirror"),r=[],n=0;n<t.length;n++){var i=t[n].CodeMirror;i&&r.push(i)}r.length&&r[0].operation(function(){for(var t=0;t<r.length;t++)e(r[t])})}}var Ho=!1;function Fo(){var e;Ho||(fe(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,Wo(Po)},100))}),fe(window,"blur",function(){return Wo(Sn)}),Ho=!0)}function Po(e){var t=e.display;t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize()}for(var Eo={3:"Pause",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",145:"ScrollLock",173:"-",186:";"